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