1 //===- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "../tools/llvm-cfi-verify/lib/FileAnalysis.h" 10 #include "../tools/llvm-cfi-verify/lib/GraphBuilder.h" 11 #include "gmock/gmock.h" 12 #include "gtest/gtest.h" 13 14 #include "llvm/BinaryFormat/ELF.h" 15 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" 16 #include "llvm/MC/MCAsmInfo.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstPrinter.h" 21 #include "llvm/MC/MCInstrAnalysis.h" 22 #include "llvm/MC/MCInstrDesc.h" 23 #include "llvm/MC/MCInstrInfo.h" 24 #include "llvm/MC/MCObjectFileInfo.h" 25 #include "llvm/MC/MCRegisterInfo.h" 26 #include "llvm/MC/MCSubtargetInfo.h" 27 #include "llvm/MC/TargetRegistry.h" 28 #include "llvm/Object/Binary.h" 29 #include "llvm/Object/COFF.h" 30 #include "llvm/Object/ELFObjectFile.h" 31 #include "llvm/Object/ObjectFile.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/CommandLine.h" 34 #include "llvm/Support/Error.h" 35 #include "llvm/Support/MemoryBuffer.h" 36 #include "llvm/Support/TargetSelect.h" 37 #include "llvm/Support/raw_ostream.h" 38 39 #include <cstdlib> 40 41 using Instr = ::llvm::cfi_verify::FileAnalysis::Instr; 42 using ::testing::Eq; 43 using ::testing::Field; 44 45 namespace llvm { 46 namespace cfi_verify { 47 namespace { 48 class ELFTestFileAnalysis : public FileAnalysis { 49 public: 50 ELFTestFileAnalysis(StringRef Trip) 51 : FileAnalysis(Triple(Trip), SubtargetFeatures()) {} 52 53 // Expose this method publicly for testing. 54 void parseSectionContents(ArrayRef<uint8_t> SectionBytes, 55 object::SectionedAddress Address) { 56 FileAnalysis::parseSectionContents(SectionBytes, Address); 57 } 58 59 Error initialiseDisassemblyMembers() { 60 return FileAnalysis::initialiseDisassemblyMembers(); 61 } 62 }; 63 64 class BasicFileAnalysisTest : public ::testing::Test { 65 public: 66 BasicFileAnalysisTest(StringRef Trip) 67 : SuccessfullyInitialised(false), Analysis(Trip) {} 68 protected: 69 void SetUp() override { 70 IgnoreDWARFFlag = true; 71 SuccessfullyInitialised = true; 72 if (auto Err = Analysis.initialiseDisassemblyMembers()) { 73 handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) { 74 SuccessfullyInitialised = false; 75 outs() 76 << "Note: CFIVerifyTests are disabled due to lack of support " 77 "on this build.\n"; 78 }); 79 } 80 } 81 82 bool SuccessfullyInitialised; 83 ELFTestFileAnalysis Analysis; 84 }; 85 86 class BasicX86FileAnalysisTest : public BasicFileAnalysisTest { 87 public: 88 BasicX86FileAnalysisTest() : BasicFileAnalysisTest("x86_64--") {} 89 }; 90 91 class BasicAArch64FileAnalysisTest : public BasicFileAnalysisTest { 92 public: 93 BasicAArch64FileAnalysisTest() : BasicFileAnalysisTest("aarch64--") {} 94 }; 95 96 TEST_F(BasicX86FileAnalysisTest, BasicDisassemblyTraversalTest) { 97 if (!SuccessfullyInitialised) 98 GTEST_SKIP(); 99 Analysis.parseSectionContents( 100 { 101 0x90, // 0: nop 102 0xb0, 0x00, // 1: mov $0x0, %al 103 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp 104 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp 105 0x48, 0xbe, 0xc4, 0x07, 0x40, 106 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi 107 0x2f, // 20: (bad) 108 0x41, 0x0e, // 21: rex.B (bad) 109 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 110 }, 111 {0xDEADBEEF, 0x0}); 112 113 EXPECT_EQ(nullptr, Analysis.getInstruction(0x0)); 114 EXPECT_EQ(nullptr, Analysis.getInstruction(0x1000)); 115 116 // 0xDEADBEEF: nop 117 const auto *InstrMeta = Analysis.getInstruction(0xDEADBEEF); 118 EXPECT_NE(nullptr, InstrMeta); 119 EXPECT_EQ(0xDEADBEEF, InstrMeta->VMAddress); 120 EXPECT_EQ(1u, InstrMeta->InstructionSize); 121 EXPECT_TRUE(InstrMeta->Valid); 122 123 const auto *NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); 124 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); 125 const auto *PrevInstrMeta = InstrMeta; 126 127 // 0xDEADBEEF + 1: mov $0x0, %al 128 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 1); 129 EXPECT_NE(nullptr, InstrMeta); 130 EXPECT_EQ(NextInstrMeta, InstrMeta); 131 EXPECT_EQ(0xDEADBEEF + 1, InstrMeta->VMAddress); 132 EXPECT_EQ(2u, InstrMeta->InstructionSize); 133 EXPECT_TRUE(InstrMeta->Valid); 134 135 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); 136 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); 137 PrevInstrMeta = InstrMeta; 138 139 // 0xDEADBEEF + 3: mov %rsp, %rbp 140 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 3); 141 EXPECT_NE(nullptr, InstrMeta); 142 EXPECT_EQ(NextInstrMeta, InstrMeta); 143 EXPECT_EQ(0xDEADBEEF + 3, InstrMeta->VMAddress); 144 EXPECT_EQ(3u, InstrMeta->InstructionSize); 145 EXPECT_TRUE(InstrMeta->Valid); 146 147 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); 148 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); 149 PrevInstrMeta = InstrMeta; 150 151 // 0xDEADBEEF + 6: sub $0x18, %rsp 152 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 6); 153 EXPECT_NE(nullptr, InstrMeta); 154 EXPECT_EQ(NextInstrMeta, InstrMeta); 155 EXPECT_EQ(0xDEADBEEF + 6, InstrMeta->VMAddress); 156 EXPECT_EQ(4u, InstrMeta->InstructionSize); 157 EXPECT_TRUE(InstrMeta->Valid); 158 159 NextInstrMeta = Analysis.getNextInstructionSequential(*InstrMeta); 160 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); 161 PrevInstrMeta = InstrMeta; 162 163 // 0xDEADBEEF + 10: movabs $0x4007c4, %rsi 164 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 10); 165 EXPECT_NE(nullptr, InstrMeta); 166 EXPECT_EQ(NextInstrMeta, InstrMeta); 167 EXPECT_EQ(0xDEADBEEF + 10, InstrMeta->VMAddress); 168 EXPECT_EQ(10u, InstrMeta->InstructionSize); 169 EXPECT_TRUE(InstrMeta->Valid); 170 171 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); 172 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); 173 PrevInstrMeta = InstrMeta; 174 175 // 0xDEADBEEF + 20: (bad) 176 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 20); 177 EXPECT_NE(nullptr, InstrMeta); 178 EXPECT_EQ(0xDEADBEEF + 20, InstrMeta->VMAddress); 179 EXPECT_EQ(1u, InstrMeta->InstructionSize); 180 EXPECT_FALSE(InstrMeta->Valid); 181 182 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); 183 EXPECT_EQ(PrevInstrMeta, Analysis.getPrevInstructionSequential(*InstrMeta)); 184 185 // 0xDEADBEEF + 21: rex.B (bad) 186 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 21); 187 EXPECT_NE(nullptr, InstrMeta); 188 EXPECT_EQ(0xDEADBEEF + 21, InstrMeta->VMAddress); 189 EXPECT_EQ(2u, InstrMeta->InstructionSize); 190 EXPECT_FALSE(InstrMeta->Valid); 191 192 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); 193 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); 194 195 // 0xDEADBEEF + 6: (bad) {%k1} 196 InstrMeta = Analysis.getInstruction(0xDEADBEEF + 23); 197 EXPECT_NE(nullptr, InstrMeta); 198 EXPECT_EQ(0xDEADBEEF + 23, InstrMeta->VMAddress); 199 EXPECT_EQ(5u, InstrMeta->InstructionSize); 200 EXPECT_FALSE(InstrMeta->Valid); 201 202 EXPECT_EQ(nullptr, Analysis.getNextInstructionSequential(*InstrMeta)); 203 EXPECT_EQ(nullptr, Analysis.getPrevInstructionSequential(*InstrMeta)); 204 } 205 206 TEST_F(BasicX86FileAnalysisTest, PrevAndNextFromBadInst) { 207 if (!SuccessfullyInitialised) 208 GTEST_SKIP(); 209 Analysis.parseSectionContents( 210 { 211 0x90, // 0: nop 212 0x2f, // 1: (bad) 213 0x90 // 2: nop 214 }, 215 {0xDEADBEEF, 0x0}); 216 const auto &BadInstrMeta = Analysis.getInstructionOrDie(0xDEADBEEF + 1); 217 const auto *GoodInstrMeta = 218 Analysis.getPrevInstructionSequential(BadInstrMeta); 219 EXPECT_NE(nullptr, GoodInstrMeta); 220 EXPECT_EQ(0xDEADBEEF, GoodInstrMeta->VMAddress); 221 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize); 222 223 GoodInstrMeta = Analysis.getNextInstructionSequential(BadInstrMeta); 224 EXPECT_NE(nullptr, GoodInstrMeta); 225 EXPECT_EQ(0xDEADBEEF + 2, GoodInstrMeta->VMAddress); 226 EXPECT_EQ(1u, GoodInstrMeta->InstructionSize); 227 } 228 229 TEST_F(BasicX86FileAnalysisTest, CFITrapTest) { 230 if (!SuccessfullyInitialised) 231 GTEST_SKIP(); 232 Analysis.parseSectionContents( 233 { 234 0x90, // 0: nop 235 0xb0, 0x00, // 1: mov $0x0, %al 236 0x48, 0x89, 0xe5, // 3: mov %rsp, %rbp 237 0x48, 0x83, 0xec, 0x18, // 6: sub $0x18, %rsp 238 0x48, 0xbe, 0xc4, 0x07, 0x40, 239 0x00, 0x00, 0x00, 0x00, 0x00, // 10: movabs $0x4007c4, %rsi 240 0x2f, // 20: (bad) 241 0x41, 0x0e, // 21: rex.B (bad) 242 0x62, 0x72, 0x65, 0x61, 0x6b, // 23: (bad) {%k1} 243 0x0f, 0x0b // 28: ud2 244 }, 245 {0xDEADBEEF, 0x0}); 246 247 EXPECT_FALSE(Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF))); 248 EXPECT_FALSE( 249 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 3))); 250 EXPECT_FALSE( 251 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 6))); 252 EXPECT_FALSE( 253 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 10))); 254 EXPECT_FALSE( 255 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 20))); 256 EXPECT_FALSE( 257 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 21))); 258 EXPECT_FALSE( 259 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 23))); 260 EXPECT_TRUE( 261 Analysis.isCFITrap(Analysis.getInstructionOrDie(0xDEADBEEF + 28))); 262 } 263 264 TEST_F(BasicX86FileAnalysisTest, FallThroughTest) { 265 if (!SuccessfullyInitialised) 266 GTEST_SKIP(); 267 Analysis.parseSectionContents( 268 { 269 0x90, // 0: nop 270 0xb0, 0x00, // 1: mov $0x0, %al 271 0x2f, // 3: (bad) 272 0x0f, 0x0b, // 4: ud2 273 0xff, 0x20, // 6: jmpq *(%rax) 274 0xeb, 0x00, // 8: jmp +0 275 0xe8, 0x45, 0xfe, 0xff, 0xff, // 10: callq [some loc] 276 0xff, 0x10, // 15: callq *(rax) 277 0x75, 0x00, // 17: jne +0 278 0xc3, // 19: retq 279 }, 280 {0xDEADBEEF, 0x0}); 281 282 EXPECT_TRUE( 283 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF))); 284 EXPECT_TRUE( 285 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 1))); 286 EXPECT_FALSE( 287 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 3))); 288 EXPECT_FALSE( 289 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 4))); 290 EXPECT_FALSE( 291 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 6))); 292 EXPECT_FALSE( 293 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 8))); 294 EXPECT_FALSE( 295 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 10))); 296 EXPECT_FALSE( 297 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 15))); 298 EXPECT_TRUE( 299 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 17))); 300 EXPECT_FALSE( 301 Analysis.canFallThrough(Analysis.getInstructionOrDie(0xDEADBEEF + 19))); 302 } 303 304 TEST_F(BasicX86FileAnalysisTest, DefiniteNextInstructionTest) { 305 if (!SuccessfullyInitialised) 306 GTEST_SKIP(); 307 Analysis.parseSectionContents( 308 { 309 0x90, // 0: nop 310 0xb0, 0x00, // 1: mov $0x0, %al 311 0x2f, // 3: (bad) 312 0x0f, 0x0b, // 4: ud2 313 0xff, 0x20, // 6: jmpq *(%rax) 314 0xeb, 0x00, // 8: jmp 10 [+0] 315 0xeb, 0x05, // 10: jmp 17 [+5] 316 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0] 317 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678] 318 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4] 319 0xff, 0x10, // 27: callq *(rax) 320 0x75, 0x00, // 29: jne 31 [+0] 321 0x75, 0xe0, // 31: jne 1 [-32] 322 0xc3, // 33: retq 323 0xeb, 0xdd, // 34: jmp 1 [-35] 324 0xeb, 0xdd, // 36: jmp 3 [-35] 325 0xeb, 0xdc, // 38: jmp 4 [-36] 326 }, 327 {0xDEADBEEF, 0x0}); 328 329 const auto *Current = Analysis.getInstruction(0xDEADBEEF); 330 const auto *Next = Analysis.getDefiniteNextInstruction(*Current); 331 EXPECT_NE(nullptr, Next); 332 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress); 333 334 Current = Analysis.getInstruction(0xDEADBEEF + 1); 335 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 336 337 Current = Analysis.getInstruction(0xDEADBEEF + 3); 338 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 339 340 Current = Analysis.getInstruction(0xDEADBEEF + 4); 341 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 342 343 Current = Analysis.getInstruction(0xDEADBEEF + 6); 344 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 345 346 Current = Analysis.getInstruction(0xDEADBEEF + 8); 347 Next = Analysis.getDefiniteNextInstruction(*Current); 348 EXPECT_NE(nullptr, Next); 349 EXPECT_EQ(0xDEADBEEF + 10, Next->VMAddress); 350 351 Current = Analysis.getInstruction(0xDEADBEEF + 10); 352 Next = Analysis.getDefiniteNextInstruction(*Current); 353 EXPECT_NE(nullptr, Next); 354 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress); 355 356 Current = Analysis.getInstruction(0xDEADBEEF + 12); 357 Next = Analysis.getDefiniteNextInstruction(*Current); 358 EXPECT_NE(nullptr, Next); 359 EXPECT_EQ(0xDEADBEEF + 17, Next->VMAddress); 360 361 Current = Analysis.getInstruction(0xDEADBEEF + 17); 362 // Note, definite next instruction address is out of range and should fail. 363 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 364 Next = Analysis.getDefiniteNextInstruction(*Current); 365 366 Current = Analysis.getInstruction(0xDEADBEEF + 22); 367 Next = Analysis.getDefiniteNextInstruction(*Current); 368 EXPECT_NE(nullptr, Next); 369 EXPECT_EQ(0xDEADBEEF + 31, Next->VMAddress); 370 371 Current = Analysis.getInstruction(0xDEADBEEF + 27); 372 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 373 Current = Analysis.getInstruction(0xDEADBEEF + 29); 374 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 375 Current = Analysis.getInstruction(0xDEADBEEF + 31); 376 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 377 Current = Analysis.getInstruction(0xDEADBEEF + 33); 378 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 379 380 Current = Analysis.getInstruction(0xDEADBEEF + 34); 381 Next = Analysis.getDefiniteNextInstruction(*Current); 382 EXPECT_NE(nullptr, Next); 383 EXPECT_EQ(0xDEADBEEF + 1, Next->VMAddress); 384 385 Current = Analysis.getInstruction(0xDEADBEEF + 36); 386 EXPECT_EQ(nullptr, Analysis.getDefiniteNextInstruction(*Current)); 387 388 Current = Analysis.getInstruction(0xDEADBEEF + 38); 389 Next = Analysis.getDefiniteNextInstruction(*Current); 390 EXPECT_NE(nullptr, Next); 391 EXPECT_EQ(0xDEADBEEF + 4, Next->VMAddress); 392 } 393 394 TEST_F(BasicX86FileAnalysisTest, ControlFlowXRefsTest) { 395 if (!SuccessfullyInitialised) 396 GTEST_SKIP(); 397 Analysis.parseSectionContents( 398 { 399 0x90, // 0: nop 400 0xb0, 0x00, // 1: mov $0x0, %al 401 0x2f, // 3: (bad) 402 0x0f, 0x0b, // 4: ud2 403 0xff, 0x20, // 6: jmpq *(%rax) 404 0xeb, 0x00, // 8: jmp 10 [+0] 405 0xeb, 0x05, // 10: jmp 17 [+5] 406 0xe8, 0x00, 0x00, 0x00, 0x00, // 12: callq 17 [+0] 407 0xe8, 0x78, 0x56, 0x34, 0x12, // 17: callq 0x1234569f [+0x12345678] 408 0xe8, 0x04, 0x00, 0x00, 0x00, // 22: callq 31 [+4] 409 0xff, 0x10, // 27: callq *(rax) 410 0x75, 0x00, // 29: jne 31 [+0] 411 0x75, 0xe0, // 31: jne 1 [-32] 412 0xc3, // 33: retq 413 0xeb, 0xdd, // 34: jmp 1 [-35] 414 0xeb, 0xdd, // 36: jmp 3 [-35] 415 0xeb, 0xdc, // 38: jmp 4 [-36] 416 }, 417 {0xDEADBEEF, 0x0}); 418 const auto *InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF); 419 std::set<const Instr *> XRefs = 420 Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 421 EXPECT_TRUE(XRefs.empty()); 422 423 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 1); 424 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 425 EXPECT_THAT(XRefs, UnorderedElementsAre( 426 Field(&Instr::VMAddress, Eq(0xDEADBEEF)), 427 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)), 428 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 34)))); 429 430 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 3); 431 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 432 EXPECT_THAT(XRefs, UnorderedElementsAre( 433 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 1)), 434 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 36)))); 435 436 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 4); 437 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 438 EXPECT_THAT(XRefs, UnorderedElementsAre( 439 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 38)))); 440 441 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 6); 442 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 443 444 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 8); 445 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 446 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 447 448 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 10); 449 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 450 EXPECT_THAT(XRefs, UnorderedElementsAre( 451 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 8)))); 452 453 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 12); 454 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 455 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 456 457 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 17); 458 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 459 EXPECT_THAT(XRefs, UnorderedElementsAre( 460 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 10)), 461 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 12)))); 462 463 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 22); 464 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 465 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 466 467 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 27); 468 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 469 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 470 471 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 29); 472 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 473 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 474 475 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 31); 476 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 477 EXPECT_THAT(XRefs, UnorderedElementsAre( 478 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 22)), 479 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 29)))); 480 481 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 33); 482 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 483 EXPECT_THAT(XRefs, UnorderedElementsAre( 484 Field(&Instr::VMAddress, Eq(0xDEADBEEF + 31)))); 485 486 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 34); 487 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 488 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 489 490 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 36); 491 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 492 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 493 494 InstrMetaPtr = &Analysis.getInstructionOrDie(0xDEADBEEF + 38); 495 XRefs = Analysis.getDirectControlFlowXRefs(*InstrMetaPtr); 496 EXPECT_TRUE(Analysis.getDirectControlFlowXRefs(*InstrMetaPtr).empty()); 497 } 498 499 TEST_F(BasicX86FileAnalysisTest, CFIProtectionInvalidTargets) { 500 if (!SuccessfullyInitialised) 501 GTEST_SKIP(); 502 Analysis.parseSectionContents( 503 { 504 0x90, // 0: nop 505 0x0f, 0x0b, // 1: ud2 506 0x75, 0x00, // 3: jne 5 [+0] 507 }, 508 {0xDEADBEEF, 0x0}); 509 GraphResult Result = 510 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0}); 511 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, 512 Analysis.validateCFIProtection(Result)); 513 Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 1, 0x0}); 514 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, 515 Analysis.validateCFIProtection(Result)); 516 Result = GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); 517 EXPECT_EQ(CFIProtectionStatus::FAIL_NOT_INDIRECT_CF, 518 Analysis.validateCFIProtection(Result)); 519 Result = GraphBuilder::buildFlowGraph(Analysis, {0x12345678, 0x0}); 520 EXPECT_EQ(CFIProtectionStatus::FAIL_INVALID_INSTRUCTION, 521 Analysis.validateCFIProtection(Result)); 522 } 523 524 TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicFallthroughToUd2) { 525 if (!SuccessfullyInitialised) 526 GTEST_SKIP(); 527 Analysis.parseSectionContents( 528 { 529 0x75, 0x02, // 0: jne 4 [+2] 530 0x0f, 0x0b, // 2: ud2 531 0xff, 0x10, // 4: callq *(%rax) 532 }, 533 {0xDEADBEEF, 0x0}); 534 GraphResult Result = 535 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); 536 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 537 Analysis.validateCFIProtection(Result)); 538 } 539 540 TEST_F(BasicX86FileAnalysisTest, CFIProtectionBasicJumpToUd2) { 541 if (!SuccessfullyInitialised) 542 GTEST_SKIP(); 543 Analysis.parseSectionContents( 544 { 545 0x75, 0x02, // 0: jne 4 [+2] 546 0xff, 0x10, // 2: callq *(%rax) 547 0x0f, 0x0b, // 4: ud2 548 }, 549 {0xDEADBEEF, 0x0}); 550 GraphResult Result = 551 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); 552 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 553 Analysis.validateCFIProtection(Result)); 554 } 555 556 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathUd2) { 557 if (!SuccessfullyInitialised) 558 GTEST_SKIP(); 559 Analysis.parseSectionContents( 560 { 561 0x75, 0x03, // 0: jne 5 [+3] 562 0x90, // 2: nop 563 0xff, 0x10, // 3: callq *(%rax) 564 0x0f, 0x0b, // 5: ud2 565 0x75, 0xf9, // 7: jne 2 [-7] 566 0x0f, 0x0b, // 9: ud2 567 }, 568 {0xDEADBEEF, 0x0}); 569 GraphResult Result = 570 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); 571 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 572 Analysis.validateCFIProtection(Result)); 573 } 574 575 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualPathSingleUd2) { 576 if (!SuccessfullyInitialised) 577 GTEST_SKIP(); 578 Analysis.parseSectionContents( 579 { 580 0x75, 0x05, // 0: jne 7 [+5] 581 0x90, // 2: nop 582 0xff, 0x10, // 3: callq *(%rax) 583 0x75, 0xfb, // 5: jne 2 [-5] 584 0x0f, 0x0b, // 7: ud2 585 }, 586 {0xDEADBEEF, 0x0}); 587 GraphResult Result = 588 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 3, 0x0}); 589 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 590 Analysis.validateCFIProtection(Result)); 591 } 592 593 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitUpwards) { 594 if (!SuccessfullyInitialised) 595 GTEST_SKIP(); 596 Analysis.parseSectionContents( 597 { 598 0x75, 0x06, // 0: jne 8 [+6] 599 0x90, // 2: nop 600 0x90, // 3: nop 601 0x90, // 4: nop 602 0x90, // 5: nop 603 0xff, 0x10, // 6: callq *(%rax) 604 0x0f, 0x0b, // 8: ud2 605 }, 606 {0xDEADBEEF, 0x0}); 607 uint64_t PrevSearchLengthForConditionalBranch = 608 SearchLengthForConditionalBranch; 609 SearchLengthForConditionalBranch = 2; 610 611 GraphResult Result = 612 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 6, 0x0}); 613 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, 614 Analysis.validateCFIProtection(Result)); 615 616 SearchLengthForConditionalBranch = PrevSearchLengthForConditionalBranch; 617 } 618 619 TEST_F(BasicX86FileAnalysisTest, CFIProtectionDualFailLimitDownwards) { 620 if (!SuccessfullyInitialised) 621 GTEST_SKIP(); 622 Analysis.parseSectionContents( 623 { 624 0x75, 0x02, // 0: jne 4 [+2] 625 0xff, 0x10, // 2: callq *(%rax) 626 0x90, // 4: nop 627 0x90, // 5: nop 628 0x90, // 6: nop 629 0x90, // 7: nop 630 0x0f, 0x0b, // 8: ud2 631 }, 632 {0xDEADBEEF, 0x0}); 633 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; 634 SearchLengthForUndef = 2; 635 636 GraphResult Result = 637 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 2, 0x0}); 638 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, 639 Analysis.validateCFIProtection(Result)); 640 641 SearchLengthForUndef = PrevSearchLengthForUndef; 642 } 643 644 TEST_F(BasicX86FileAnalysisTest, CFIProtectionGoodAndBadPaths) { 645 if (!SuccessfullyInitialised) 646 GTEST_SKIP(); 647 Analysis.parseSectionContents( 648 { 649 0xeb, 0x02, // 0: jmp 4 [+2] 650 0x75, 0x02, // 2: jne 6 [+2] 651 0xff, 0x10, // 4: callq *(%rax) 652 0x0f, 0x0b, // 6: ud2 653 }, 654 {0xDEADBEEF, 0x0}); 655 GraphResult Result = 656 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); 657 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, 658 Analysis.validateCFIProtection(Result)); 659 } 660 661 TEST_F(BasicX86FileAnalysisTest, CFIProtectionWithUnconditionalJumpInFallthrough) { 662 if (!SuccessfullyInitialised) 663 GTEST_SKIP(); 664 Analysis.parseSectionContents( 665 { 666 0x75, 0x04, // 0: jne 6 [+4] 667 0xeb, 0x00, // 2: jmp 4 [+0] 668 0xff, 0x10, // 4: callq *(%rax) 669 0x0f, 0x0b, // 6: ud2 670 }, 671 {0xDEADBEEF, 0x0}); 672 GraphResult Result = 673 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); 674 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 675 Analysis.validateCFIProtection(Result)); 676 } 677 678 TEST_F(BasicX86FileAnalysisTest, CFIProtectionComplexExample) { 679 if (!SuccessfullyInitialised) 680 GTEST_SKIP(); 681 // See unittests/GraphBuilder.cpp::BuildFlowGraphComplexExample for this 682 // graph. 683 Analysis.parseSectionContents( 684 { 685 0x75, 0x12, // 0: jne 20 [+18] 686 0xeb, 0x03, // 2: jmp 7 [+3] 687 0x75, 0x10, // 4: jne 22 [+16] 688 0x90, // 6: nop 689 0x90, // 7: nop 690 0x90, // 8: nop 691 0xff, 0x10, // 9: callq *(%rax) 692 0xeb, 0xfc, // 11: jmp 9 [-4] 693 0x75, 0xfa, // 13: jne 9 [-6] 694 0xe8, 0x78, 0x56, 0x34, 0x12, // 15: callq OUTOFBOUNDS [+0x12345678] 695 0x90, // 20: nop 696 0x90, // 21: nop 697 0x0f, 0x0b, // 22: ud2 698 }, 699 {0xDEADBEEF, 0x0}); 700 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; 701 SearchLengthForUndef = 5; 702 GraphResult Result = 703 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0}); 704 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, 705 Analysis.validateCFIProtection(Result)); 706 SearchLengthForUndef = PrevSearchLengthForUndef; 707 } 708 709 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTest) { 710 Analysis.parseSectionContents( 711 { 712 0x77, 0x0d, // 0x688118: ja 0x688127 [+12] 713 0x48, 0x89, 0xdf, // 0x68811a: mov %rbx, %rdi 714 0xff, 0xd0, // 0x68811d: callq *%rax 715 0x48, 0x89, 0xdf, // 0x68811f: mov %rbx, %rdi 716 0xe8, 0x09, 0x00, 0x00, 0x00, // 0x688122: callq 0x688130 717 0x0f, 0x0b, // 0x688127: ud2 718 }, 719 {0x688118, 0x0}); 720 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; 721 SearchLengthForUndef = 1; 722 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x68811d, 0x0}); 723 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 724 Analysis.validateCFIProtection(Result)); 725 SearchLengthForUndef = PrevSearchLengthForUndef; 726 } 727 728 TEST_F(BasicX86FileAnalysisTest, UndefSearchLengthOneTestFarAway) { 729 Analysis.parseSectionContents( 730 { 731 0x74, 0x73, // 0x7759eb: je 0x775a60 732 0xe9, 0x1c, 0x04, 0x00, 0x00, 0x00, // 0x7759ed: jmpq 0x775e0e 733 }, 734 {0x7759eb, 0x0}); 735 736 Analysis.parseSectionContents( 737 { 738 0x0f, 0x85, 0xb2, 0x03, 0x00, 0x00, // 0x775a56: jne 0x775e0e 739 0x48, 0x83, 0xc3, 0xf4, // 0x775a5c: add $0xfffffffffffffff4,%rbx 740 0x48, 0x8b, 0x7c, 0x24, 0x10, // 0x775a60: mov 0x10(%rsp),%rdi 741 0x48, 0x89, 0xde, // 0x775a65: mov %rbx,%rsi 742 0xff, 0xd1, // 0x775a68: callq *%rcx 743 }, 744 {0x775a56, 0x0}); 745 746 Analysis.parseSectionContents( 747 { 748 0x0f, 0x0b, // 0x775e0e: ud2 749 }, 750 {0x775e0e, 0x0}); 751 uint64_t PrevSearchLengthForUndef = SearchLengthForUndef; 752 SearchLengthForUndef = 1; 753 GraphResult Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); 754 EXPECT_EQ(CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH, 755 Analysis.validateCFIProtection(Result)); 756 SearchLengthForUndef = 2; 757 Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); 758 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 759 Analysis.validateCFIProtection(Result)); 760 SearchLengthForUndef = 3; 761 Result = GraphBuilder::buildFlowGraph(Analysis, {0x775a68, 0x0}); 762 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 763 Analysis.validateCFIProtection(Result)); 764 SearchLengthForUndef = PrevSearchLengthForUndef; 765 } 766 767 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit) { 768 if (!SuccessfullyInitialised) 769 GTEST_SKIP(); 770 Analysis.parseSectionContents( 771 { 772 0x75, 0x02, // 0: jne 4 [+2] 773 0x0f, 0x0b, // 2: ud2 774 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %rax 775 0xff, 0x10, // 10: callq *(%rax) 776 }, 777 {0xDEADBEEF, 0x0}); 778 GraphResult Result = 779 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 10, 0x0}); 780 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 781 Analysis.validateCFIProtection(Result)); 782 } 783 784 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathExplicit2) { 785 if (!SuccessfullyInitialised) 786 GTEST_SKIP(); 787 Analysis.parseSectionContents( 788 { 789 0x75, 0x02, // 0: jne 4 [+2] 790 0x0f, 0x0b, // 2: ud2 791 0x48, 0x83, 0xc0, 0x00, // 4: add $0x0, %rax 792 0xff, 0x10, // 8: callq *(%rax) 793 }, 794 {0xDEADBEEF, 0x0}); 795 GraphResult Result = 796 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0}); 797 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 798 Analysis.validateCFIProtection(Result)); 799 } 800 801 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberSinglePathImplicit) { 802 if (!SuccessfullyInitialised) 803 GTEST_SKIP(); 804 Analysis.parseSectionContents( 805 { 806 0x75, 0x02, // 0: jne 4 [+2] 807 0x0f, 0x0b, // 2: ud2 808 0x05, 0x00, 0x00, 0x00, 0x00, // 4: add $0x0, %eax 809 0xff, 0x10, // 9: callq *(%rax) 810 }, 811 {0xDEADBEEF, 0x0}); 812 GraphResult Result = 813 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 9, 0x0}); 814 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 815 Analysis.validateCFIProtection(Result)); 816 } 817 818 TEST_F(BasicX86FileAnalysisTest, CFIProtectionClobberDualPathImplicit) { 819 if (!SuccessfullyInitialised) 820 GTEST_SKIP(); 821 Analysis.parseSectionContents( 822 { 823 0x75, 0x04, // 0: jne 6 [+4] 824 0x0f, 0x31, // 2: rdtsc (note: affects eax) 825 0xff, 0x10, // 4: callq *(%rax) 826 0x0f, 0x0b, // 6: ud2 827 0x75, 0xf9, // 8: jne 2 [-7] 828 0x0f, 0x0b, // 10: ud2 829 }, 830 {0xDEADBEEF, 0x0}); 831 GraphResult Result = 832 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 4, 0x0}); 833 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 834 Analysis.validateCFIProtection(Result)); 835 } 836 837 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicUnprotected) { 838 if (!SuccessfullyInitialised) 839 GTEST_SKIP(); 840 Analysis.parseSectionContents( 841 { 842 0x00, 0x01, 0x3f, 0xd6, // 0: blr x8 843 }, 844 {0xDEADBEEF, 0x0}); 845 GraphResult Result = 846 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF, 0x0}); 847 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, 848 Analysis.validateCFIProtection(Result)); 849 } 850 851 TEST_F(BasicAArch64FileAnalysisTest, AArch64BasicProtected) { 852 if (!SuccessfullyInitialised) 853 GTEST_SKIP(); 854 Analysis.parseSectionContents( 855 { 856 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 857 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 858 0x00, 0x01, 0x3f, 0xd6, // 8: blr x8 859 }, 860 {0xDEADBEEF, 0x0}); 861 GraphResult Result = 862 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 8, 0x0}); 863 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 864 Analysis.validateCFIProtection(Result)); 865 } 866 867 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberBasic) { 868 if (!SuccessfullyInitialised) 869 GTEST_SKIP(); 870 Analysis.parseSectionContents( 871 { 872 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 873 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 874 0x08, 0x05, 0x00, 0x91, // 8: add x8, x8, #1 875 0x00, 0x01, 0x3f, 0xd6, // 12: blr x8 876 }, 877 {0xDEADBEEF, 0x0}); 878 GraphResult Result = 879 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); 880 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 881 Analysis.validateCFIProtection(Result)); 882 } 883 884 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberOneLoad) { 885 if (!SuccessfullyInitialised) 886 GTEST_SKIP(); 887 Analysis.parseSectionContents( 888 { 889 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 890 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 891 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 892 0x20, 0x00, 0x1f, 0xd6, // 12: br x1 893 }, 894 {0xDEADBEEF, 0x0}); 895 GraphResult Result = 896 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); 897 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 898 Analysis.validateCFIProtection(Result)); 899 } 900 901 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddGood) { 902 if (!SuccessfullyInitialised) 903 GTEST_SKIP(); 904 Analysis.parseSectionContents( 905 { 906 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 907 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 908 0x21, 0x04, 0x00, 0x91, // 8: add x1, x1, #1 909 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 910 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 911 }, 912 {0xDEADBEEF, 0x0}); 913 GraphResult Result = 914 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 915 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 916 Analysis.validateCFIProtection(Result)); 917 } 918 919 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad) { 920 if (!SuccessfullyInitialised) 921 GTEST_SKIP(); 922 Analysis.parseSectionContents( 923 { 924 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 925 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 926 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 927 0x21, 0x04, 0x00, 0x91, // 12: add x1, x1, #1 928 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 929 }, 930 {0xDEADBEEF, 0x0}); 931 GraphResult Result = 932 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 933 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 934 Analysis.validateCFIProtection(Result)); 935 } 936 937 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberLoadAddBad2) { 938 if (!SuccessfullyInitialised) 939 GTEST_SKIP(); 940 Analysis.parseSectionContents( 941 { 942 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 943 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 944 0x29, 0x04, 0x00, 0x91, // 16: add x9, x1, #1 945 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 946 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 947 }, 948 {0xDEADBEEF, 0x0}); 949 GraphResult Result = 950 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 951 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 952 Analysis.validateCFIProtection(Result)); 953 } 954 955 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberTwoLoads) { 956 if (!SuccessfullyInitialised) 957 GTEST_SKIP(); 958 Analysis.parseSectionContents( 959 { 960 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 961 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 962 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 963 0x21, 0x08, 0x40, 0xf9, // 12: ldr x1, [x1,#16] 964 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 965 }, 966 {0xDEADBEEF, 0x0}); 967 GraphResult Result = 968 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 969 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 970 Analysis.validateCFIProtection(Result)); 971 } 972 973 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedSecondLoad) { 974 if (!SuccessfullyInitialised) 975 GTEST_SKIP(); 976 Analysis.parseSectionContents( 977 { 978 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 979 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 980 0x21, 0x09, 0x40, 0xf9, // 8: ldr x1, [x9,#16] 981 0x21, 0x09, 0x40, 0xf9, // 12: ldr x1, [x9,#16] 982 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 983 }, 984 {0xDEADBEEF, 0x0}); 985 GraphResult Result = 986 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 987 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 988 Analysis.validateCFIProtection(Result)); 989 } 990 991 TEST_F(BasicAArch64FileAnalysisTest, AArch64ClobberUnrelatedLoads) { 992 if (!SuccessfullyInitialised) 993 GTEST_SKIP(); 994 Analysis.parseSectionContents( 995 { 996 0x49, 0x00, 0x00, 0x54, // 0: b.ls 8 997 0x20, 0x00, 0x20, 0xd4, // 4: brk #0x1 998 0x22, 0x09, 0x40, 0xf9, // 8: ldr x2, [x9,#16] 999 0x22, 0x08, 0x40, 0xf9, // 12: ldr x2, [x1,#16] 1000 0x20, 0x00, 0x1f, 0xd6, // 16: br x1 1001 }, 1002 {0xDEADBEEF, 0x0}); 1003 GraphResult Result = 1004 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 16, 0x0}); 1005 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 1006 Analysis.validateCFIProtection(Result)); 1007 } 1008 1009 TEST_F(BasicAArch64FileAnalysisTest, AArch64GoodAndBadPaths) { 1010 if (!SuccessfullyInitialised) 1011 GTEST_SKIP(); 1012 Analysis.parseSectionContents( 1013 { 1014 0x03, 0x00, 0x00, 0x14, // 0: b 12 1015 0x49, 0x00, 0x00, 0x54, // 4: b.ls 8 1016 0x20, 0x00, 0x20, 0xd4, // 8: brk #0x1 1017 0x20, 0x00, 0x1f, 0xd6, // 12: br x1 1018 }, 1019 {0xDEADBEEF, 0x0}); 1020 GraphResult Result = 1021 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 12, 0x0}); 1022 EXPECT_EQ(CFIProtectionStatus::FAIL_ORPHANS, 1023 Analysis.validateCFIProtection(Result)); 1024 } 1025 1026 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPaths) { 1027 if (!SuccessfullyInitialised) 1028 GTEST_SKIP(); 1029 Analysis.parseSectionContents( 1030 { 1031 0xc9, 0x00, 0x00, 0x54, // 0: b.ls 24 1032 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16] 1033 0x03, 0x00, 0x00, 0x14, // 8: b 12 1034 0x69, 0x00, 0x00, 0x54, // 12: b.ls 12 1035 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16] 1036 0x20, 0x00, 0x1f, 0xd6, // 20: br x1 1037 0x20, 0x00, 0x20, 0xd4, // 24: brk #0x1 1038 }, 1039 {0xDEADBEEF, 0x0}); 1040 GraphResult Result = 1041 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 20, 0x0}); 1042 EXPECT_EQ(CFIProtectionStatus::PROTECTED, 1043 Analysis.validateCFIProtection(Result)); 1044 } 1045 1046 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad1) { 1047 if (!SuccessfullyInitialised) 1048 GTEST_SKIP(); 1049 Analysis.parseSectionContents( 1050 { 1051 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28 1052 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16] 1053 0x21, 0x08, 0x40, 0xf9, // 8: ldr x1, [x1,#16] 1054 0x03, 0x00, 0x00, 0x14, // 12: b 12 1055 0x69, 0x00, 0x00, 0x54, // 16: b.ls 12 1056 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16] 1057 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 1058 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 1059 }, 1060 {0xDEADBEEF, 0x0}); 1061 GraphResult Result = 1062 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0}); 1063 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 1064 Analysis.validateCFIProtection(Result)); 1065 } 1066 1067 TEST_F(BasicAArch64FileAnalysisTest, AArch64TwoPathsBadLoad2) { 1068 if (!SuccessfullyInitialised) 1069 GTEST_SKIP(); 1070 Analysis.parseSectionContents( 1071 { 1072 0xe9, 0x00, 0x00, 0x54, // 0: b.ls 28 1073 0x21, 0x08, 0x40, 0xf9, // 4: ldr x1, [x1,#16] 1074 0x03, 0x00, 0x00, 0x14, // 8: b 12 1075 0x89, 0x00, 0x00, 0x54, // 12: b.ls 16 1076 0x21, 0x08, 0x40, 0xf9, // 16: ldr x1, [x1,#16] 1077 0x21, 0x08, 0x40, 0xf9, // 20: ldr x1, [x1,#16] 1078 0x20, 0x00, 0x1f, 0xd6, // 24: br x1 1079 0x20, 0x00, 0x20, 0xd4, // 28: brk #0x1 1080 }, 1081 {0xDEADBEEF, 0x0}); 1082 GraphResult Result = 1083 GraphBuilder::buildFlowGraph(Analysis, {0xDEADBEEF + 24, 0x0}); 1084 EXPECT_EQ(CFIProtectionStatus::FAIL_REGISTER_CLOBBERED, 1085 Analysis.validateCFIProtection(Result)); 1086 } 1087 1088 } // anonymous namespace 1089 } // end namespace cfi_verify 1090 } // end namespace llvm 1091 1092 int main(int argc, char **argv) { 1093 ::testing::InitGoogleTest(&argc, argv); 1094 llvm::cl::ParseCommandLineOptions(argc, argv); 1095 1096 llvm::InitializeAllTargetInfos(); 1097 llvm::InitializeAllTargetMCs(); 1098 llvm::InitializeAllAsmParsers(); 1099 llvm::InitializeAllDisassemblers(); 1100 1101 return RUN_ALL_TESTS(); 1102 } 1103