using Instr = ::llvm::cfi_verify::FileAnalysis::Instr;
using ::testing::Eq;
+using ::testing::Field;
namespace llvm {
namespace cfi_verify {
EXPECT_EQ(1u, GoodInstrMeta->InstructionSize);
}
+TEST_F(BasicFileAnalysisTest, CFITrapTest) {
+ Analysis.parseSectionContents(
+ {
+ 0x90, // 0: nop
+ 0xb0, 0x00, // 1: mov $0x0, %al
+ 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp
+ 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp
+ 0x48, 0xbe, 0xc4, 0x07, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi
+ 0x2f, // 20: (bad)
+ 0x41, 0x0e, // 21: rex.B (bad)
+ 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1}
+ 0x0f, 0x0b // 28: ud2
+ },
+ 0xDEADBEEF);
+
+ EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21)));
+ EXPECT_FALSE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23)));
+ EXPECT_TRUE(
+ Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28)));
+}
+
+TEST_F(BasicFileAnalysisTest, FallThroughTest) {
+ Analysis.parseSectionContents(
+ {
+ 0x90, // 0: nop
+ 0xb0, 0x00, // 1: mov $0x0, %al
+ 0x2f, // 3: (bad)
+ 0x0f, 0x0b, // 4: ud2
+ 0xff, 0x20, // 6: jmpq *(%rax)
+ 0xeb, 0x00, // 8: jmp +0
+ 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc]
+ 0xff, 0x10, // 15: callq *(rax)
+ 0x75, 0x00, // 17: jne +0
+ 0xc3, // 19: retq
+ },
+ 0xDEADBEEF);
+
+ EXPECT_TRUE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF)));
+ EXPECT_TRUE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15)));
+ EXPECT_TRUE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17)));
+ EXPECT_FALSE(
+ Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19)));
+}
+
+TEST_F(BasicFileAnalysisTest, DefiniteNextInstructionTest) {
+ Analysis.parseSectionContents(
+ {
+ 0x90, // 0: nop
+ 0xb0, 0x00, // 1: mov $0x0, %al
+ 0x2f, // 3: (bad)
+ 0x0f, 0x0b, // 4: ud2
+ 0xff, 0x20, // 6: jmpq *(%rax)
+ 0xeb, 0x00, // 8: jmp 10 [+0]
+ 0xeb, 0x05, // 10: jmp 17 [+5]
+ 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
+ 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
+ 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
+ 0xff, 0x10, // 27: callq *(rax)
+ 0x75, 0x00, // 29: jne 31 [+0]
+ 0x75, 0xe0, // 31: jne 1 [-32]
+ 0xc3, // 33: retq
+ 0xeb, 0xdd, // 34: jmp 1 [-35]
+ 0xeb, 0xdd, // 36: jmp 3 [-35]
+ 0xeb, 0xdc, // 38: jmp 4 [-36]
+ },
+ 0xDEADBEEF);
+
+ const auto *Current = Analysis.getInstruction(0xDEADBEEF);
+ const auto *Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 1);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 3);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 4);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 6);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 8);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 10);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 12);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 17);
+ // Note, definite next instruction address is out of range and should fail.
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 22);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 27);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+ Current = Analysis.getInstruction(0xDEADBEEF + 29);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+ Current = Analysis.getInstruction(0xDEADBEEF + 31);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+ Current = Analysis.getInstruction(0xDEADBEEF + 33);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 34);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress);
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 36);
+ EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current));
+
+ Current = Analysis.getInstruction(0xDEADBEEF + 38);
+ Next = Analysis.getDefiniteNextInstruction(*Current);
+ EXPECT_NE(nullptr, Next);
+ EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress);
+}
+
+TEST_F(BasicFileAnalysisTest, ControlFlowXRefsTest) {
+ Analysis.parseSectionContents(
+ {
+ 0x90, // 0: nop
+ 0xb0, 0x00, // 1: mov $0x0, %al
+ 0x2f, // 3: (bad)
+ 0x0f, 0x0b, // 4: ud2
+ 0xff, 0x20, // 6: jmpq *(%rax)
+ 0xeb, 0x00, // 8: jmp 10 [+0]
+ 0xeb, 0x05, // 10: jmp 17 [+5]
+ 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0]
+ 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678]
+ 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4]
+ 0xff, 0x10, // 27: callq *(rax)
+ 0x75, 0x00, // 29: jne 31 [+0]
+ 0x75, 0xe0, // 31: jne 1 [-32]
+ 0xc3, // 33: retq
+ 0xeb, 0xdd, // 34: jmp 1 [-35]
+ 0xeb, 0xdd, // 36: jmp 3 [-35]
+ 0xeb, 0xdc, // 38: jmp 4 [-36]
+ },
+ 0xDEADBEEF);
+ const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF);
+ std::set<const Instr *> XRefs =
+ Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(XRefs.empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF)),
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)),
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)),
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)),
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)),
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_THAT(XRefs, UnorderedElementsAre(
+ Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31))));
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+
+ InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38);
+ XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr);
+ EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty());
+}
+
} // anonymous namespace
} // end namespace cfi_verify
} // end namespace llvm