diff options
Diffstat (limited to 'llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp')
-rw-r--r-- | llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp index 00bea1b4c43..66fdc42ccfc 100644 --- a/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp +++ b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp @@ -39,6 +39,7 @@ using Instr = ::llvm::cfi_verify::FileAnalysis::Instr; using ::testing::Eq; +using ::testing::Field; namespace llvm { namespace cfi_verify { @@ -199,6 +200,268 @@ TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) { 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 |