FileAnalysis.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. //===- FileAnalysis.cpp -----------------------------------------*- C++ -*-===//
  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. #include "FileAnalysis.h"
  9. #include "GraphBuilder.h"
  10. #include "llvm/BinaryFormat/ELF.h"
  11. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  12. #include "llvm/MC/MCAsmInfo.h"
  13. #include "llvm/MC/MCContext.h"
  14. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  15. #include "llvm/MC/MCInst.h"
  16. #include "llvm/MC/MCInstPrinter.h"
  17. #include "llvm/MC/MCInstrAnalysis.h"
  18. #include "llvm/MC/MCInstrDesc.h"
  19. #include "llvm/MC/MCInstrInfo.h"
  20. #include "llvm/MC/MCObjectFileInfo.h"
  21. #include "llvm/MC/MCRegisterInfo.h"
  22. #include "llvm/MC/MCSubtargetInfo.h"
  23. #include "llvm/MC/MCTargetOptions.h"
  24. #include "llvm/MC/TargetRegistry.h"
  25. #include "llvm/Object/Binary.h"
  26. #include "llvm/Object/COFF.h"
  27. #include "llvm/Object/ELFObjectFile.h"
  28. #include "llvm/Object/ObjectFile.h"
  29. #include "llvm/Support/Casting.h"
  30. #include "llvm/Support/CommandLine.h"
  31. #include "llvm/Support/Error.h"
  32. #include "llvm/Support/MemoryBuffer.h"
  33. #include "llvm/Support/TargetSelect.h"
  34. #include "llvm/Support/raw_ostream.h"
  35. using Instr = llvm::cfi_verify::FileAnalysis::Instr;
  36. using LLVMSymbolizer = llvm::symbolize::LLVMSymbolizer;
  37. namespace llvm {
  38. namespace cfi_verify {
  39. bool IgnoreDWARFFlag;
  40. static cl::opt<bool, true> IgnoreDWARFArg(
  41. "ignore-dwarf",
  42. cl::desc(
  43. "Ignore all DWARF data. This relaxes the requirements for all "
  44. "statically linked libraries to have been compiled with '-g', but "
  45. "will result in false positives for 'CFI unprotected' instructions."),
  46. cl::location(IgnoreDWARFFlag), cl::init(false));
  47. StringRef stringCFIProtectionStatus(CFIProtectionStatus Status) {
  48. switch (Status) {
  49. case CFIProtectionStatus::PROTECTED:
  50. return "PROTECTED";
  51. case CFIProtectionStatus::FAIL_NOT_INDIRECT_CF:
  52. return "FAIL_NOT_INDIRECT_CF";
  53. case CFIProtectionStatus::FAIL_ORPHANS:
  54. return "FAIL_ORPHANS";
  55. case CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH:
  56. return "FAIL_BAD_CONDITIONAL_BRANCH";
  57. case CFIProtectionStatus::FAIL_REGISTER_CLOBBERED:
  58. return "FAIL_REGISTER_CLOBBERED";
  59. case CFIProtectionStatus::FAIL_INVALID_INSTRUCTION:
  60. return "FAIL_INVALID_INSTRUCTION";
  61. }
  62. llvm_unreachable("Attempted to stringify an unknown enum value.");
  63. }
  64. Expected<FileAnalysis> FileAnalysis::Create(StringRef Filename) {
  65. // Open the filename provided.
  66. Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
  67. object::createBinary(Filename);
  68. if (!BinaryOrErr)
  69. return BinaryOrErr.takeError();
  70. // Construct the object and allow it to take ownership of the binary.
  71. object::OwningBinary<object::Binary> Binary = std::move(BinaryOrErr.get());
  72. FileAnalysis Analysis(std::move(Binary));
  73. Analysis.Object = dyn_cast<object::ObjectFile>(Analysis.Binary.getBinary());
  74. if (!Analysis.Object)
  75. return make_error<UnsupportedDisassembly>("Failed to cast object");
  76. switch (Analysis.Object->getArch()) {
  77. case Triple::x86:
  78. case Triple::x86_64:
  79. case Triple::aarch64:
  80. case Triple::aarch64_be:
  81. break;
  82. default:
  83. return make_error<UnsupportedDisassembly>("Unsupported architecture.");
  84. }
  85. Analysis.ObjectTriple = Analysis.Object->makeTriple();
  86. Analysis.Features = Analysis.Object->getFeatures();
  87. // Init the rest of the object.
  88. if (auto InitResponse = Analysis.initialiseDisassemblyMembers())
  89. return std::move(InitResponse);
  90. if (auto SectionParseResponse = Analysis.parseCodeSections())
  91. return std::move(SectionParseResponse);
  92. if (auto SymbolTableParseResponse = Analysis.parseSymbolTable())
  93. return std::move(SymbolTableParseResponse);
  94. return std::move(Analysis);
  95. }
  96. FileAnalysis::FileAnalysis(object::OwningBinary<object::Binary> Binary)
  97. : Binary(std::move(Binary)) {}
  98. FileAnalysis::FileAnalysis(const Triple &ObjectTriple,
  99. const SubtargetFeatures &Features)
  100. : ObjectTriple(ObjectTriple), Features(Features) {}
  101. const Instr *
  102. FileAnalysis::getPrevInstructionSequential(const Instr &InstrMeta) const {
  103. std::map<uint64_t, Instr>::const_iterator KV =
  104. Instructions.find(InstrMeta.VMAddress);
  105. if (KV == Instructions.end() || KV == Instructions.begin())
  106. return nullptr;
  107. if (!(--KV)->second.Valid)
  108. return nullptr;
  109. return &KV->second;
  110. }
  111. const Instr *
  112. FileAnalysis::getNextInstructionSequential(const Instr &InstrMeta) const {
  113. std::map<uint64_t, Instr>::const_iterator KV =
  114. Instructions.find(InstrMeta.VMAddress);
  115. if (KV == Instructions.end() || ++KV == Instructions.end())
  116. return nullptr;
  117. if (!KV->second.Valid)
  118. return nullptr;
  119. return &KV->second;
  120. }
  121. bool FileAnalysis::usesRegisterOperand(const Instr &InstrMeta) const {
  122. for (const auto &Operand : InstrMeta.Instruction) {
  123. if (Operand.isReg())
  124. return true;
  125. }
  126. return false;
  127. }
  128. const Instr *FileAnalysis::getInstruction(uint64_t Address) const {
  129. const auto &InstrKV = Instructions.find(Address);
  130. if (InstrKV == Instructions.end())
  131. return nullptr;
  132. return &InstrKV->second;
  133. }
  134. const Instr &FileAnalysis::getInstructionOrDie(uint64_t Address) const {
  135. const auto &InstrKV = Instructions.find(Address);
  136. assert(InstrKV != Instructions.end() && "Address doesn't exist.");
  137. return InstrKV->second;
  138. }
  139. bool FileAnalysis::isCFITrap(const Instr &InstrMeta) const {
  140. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  141. return InstrDesc.isTrap() || willTrapOnCFIViolation(InstrMeta);
  142. }
  143. bool FileAnalysis::willTrapOnCFIViolation(const Instr &InstrMeta) const {
  144. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  145. if (!InstrDesc.isCall())
  146. return false;
  147. uint64_t Target;
  148. if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress,
  149. InstrMeta.InstructionSize, Target))
  150. return false;
  151. return TrapOnFailFunctionAddresses.contains(Target);
  152. }
  153. bool FileAnalysis::canFallThrough(const Instr &InstrMeta) const {
  154. if (!InstrMeta.Valid)
  155. return false;
  156. if (isCFITrap(InstrMeta))
  157. return false;
  158. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  159. if (InstrDesc.mayAffectControlFlow(InstrMeta.Instruction, *RegisterInfo))
  160. return InstrDesc.isConditionalBranch();
  161. return true;
  162. }
  163. const Instr *
  164. FileAnalysis::getDefiniteNextInstruction(const Instr &InstrMeta) const {
  165. if (!InstrMeta.Valid)
  166. return nullptr;
  167. if (isCFITrap(InstrMeta))
  168. return nullptr;
  169. const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode());
  170. const Instr *NextMetaPtr;
  171. if (InstrDesc.mayAffectControlFlow(InstrMeta.Instruction, *RegisterInfo)) {
  172. if (InstrDesc.isConditionalBranch())
  173. return nullptr;
  174. uint64_t Target;
  175. if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress,
  176. InstrMeta.InstructionSize, Target))
  177. return nullptr;
  178. NextMetaPtr = getInstruction(Target);
  179. } else {
  180. NextMetaPtr =
  181. getInstruction(InstrMeta.VMAddress + InstrMeta.InstructionSize);
  182. }
  183. if (!NextMetaPtr || !NextMetaPtr->Valid)
  184. return nullptr;
  185. return NextMetaPtr;
  186. }
  187. std::set<const Instr *>
  188. FileAnalysis::getDirectControlFlowXRefs(const Instr &InstrMeta) const {
  189. std::set<const Instr *> CFCrossReferences;
  190. const Instr *PrevInstruction = getPrevInstructionSequential(InstrMeta);
  191. if (PrevInstruction && canFallThrough(*PrevInstruction))
  192. CFCrossReferences.insert(PrevInstruction);
  193. const auto &TargetRefsKV = StaticBranchTargetings.find(InstrMeta.VMAddress);
  194. if (TargetRefsKV == StaticBranchTargetings.end())
  195. return CFCrossReferences;
  196. for (uint64_t SourceInstrAddress : TargetRefsKV->second) {
  197. const auto &SourceInstrKV = Instructions.find(SourceInstrAddress);
  198. if (SourceInstrKV == Instructions.end()) {
  199. errs() << "Failed to find source instruction at address "
  200. << format_hex(SourceInstrAddress, 2)
  201. << " for the cross-reference to instruction at address "
  202. << format_hex(InstrMeta.VMAddress, 2) << ".\n";
  203. continue;
  204. }
  205. CFCrossReferences.insert(&SourceInstrKV->second);
  206. }
  207. return CFCrossReferences;
  208. }
  209. const std::set<object::SectionedAddress> &
  210. FileAnalysis::getIndirectInstructions() const {
  211. return IndirectInstructions;
  212. }
  213. const MCRegisterInfo *FileAnalysis::getRegisterInfo() const {
  214. return RegisterInfo.get();
  215. }
  216. const MCInstrInfo *FileAnalysis::getMCInstrInfo() const { return MII.get(); }
  217. const MCInstrAnalysis *FileAnalysis::getMCInstrAnalysis() const {
  218. return MIA.get();
  219. }
  220. Expected<DIInliningInfo>
  221. FileAnalysis::symbolizeInlinedCode(object::SectionedAddress Address) {
  222. assert(Symbolizer != nullptr && "Symbolizer is invalid.");
  223. return Symbolizer->symbolizeInlinedCode(std::string(Object->getFileName()),
  224. Address);
  225. }
  226. CFIProtectionStatus
  227. FileAnalysis::validateCFIProtection(const GraphResult &Graph) const {
  228. const Instr *InstrMetaPtr = getInstruction(Graph.BaseAddress);
  229. if (!InstrMetaPtr)
  230. return CFIProtectionStatus::FAIL_INVALID_INSTRUCTION;
  231. const auto &InstrDesc = MII->get(InstrMetaPtr->Instruction.getOpcode());
  232. if (!InstrDesc.mayAffectControlFlow(InstrMetaPtr->Instruction, *RegisterInfo))
  233. return CFIProtectionStatus::FAIL_NOT_INDIRECT_CF;
  234. if (!usesRegisterOperand(*InstrMetaPtr))
  235. return CFIProtectionStatus::FAIL_NOT_INDIRECT_CF;
  236. if (!Graph.OrphanedNodes.empty())
  237. return CFIProtectionStatus::FAIL_ORPHANS;
  238. for (const auto &BranchNode : Graph.ConditionalBranchNodes) {
  239. if (!BranchNode.CFIProtection)
  240. return CFIProtectionStatus::FAIL_BAD_CONDITIONAL_BRANCH;
  241. }
  242. if (indirectCFOperandClobber(Graph) != Graph.BaseAddress)
  243. return CFIProtectionStatus::FAIL_REGISTER_CLOBBERED;
  244. return CFIProtectionStatus::PROTECTED;
  245. }
  246. uint64_t FileAnalysis::indirectCFOperandClobber(const GraphResult &Graph) const {
  247. assert(Graph.OrphanedNodes.empty() && "Orphaned nodes should be empty.");
  248. // Get the set of registers we must check to ensure they're not clobbered.
  249. const Instr &IndirectCF = getInstructionOrDie(Graph.BaseAddress);
  250. DenseSet<unsigned> RegisterNumbers;
  251. for (const auto &Operand : IndirectCF.Instruction) {
  252. if (Operand.isReg())
  253. RegisterNumbers.insert(Operand.getReg());
  254. }
  255. assert(RegisterNumbers.size() && "Zero register operands on indirect CF.");
  256. // Now check all branches to indirect CFs and ensure no clobbering happens.
  257. for (const auto &Branch : Graph.ConditionalBranchNodes) {
  258. uint64_t Node;
  259. if (Branch.IndirectCFIsOnTargetPath)
  260. Node = Branch.Target;
  261. else
  262. Node = Branch.Fallthrough;
  263. // Some architectures (e.g., AArch64) cannot load in an indirect branch, so
  264. // we allow them one load.
  265. bool canLoad = !MII->get(IndirectCF.Instruction.getOpcode()).mayLoad();
  266. // We walk backwards from the indirect CF. It is the last node returned by
  267. // Graph.flattenAddress, so we skip it since we already handled it.
  268. DenseSet<unsigned> CurRegisterNumbers = RegisterNumbers;
  269. std::vector<uint64_t> Nodes = Graph.flattenAddress(Node);
  270. for (auto I = Nodes.rbegin() + 1, E = Nodes.rend(); I != E; ++I) {
  271. Node = *I;
  272. const Instr &NodeInstr = getInstructionOrDie(Node);
  273. const auto &InstrDesc = MII->get(NodeInstr.Instruction.getOpcode());
  274. for (auto RI = CurRegisterNumbers.begin(), RE = CurRegisterNumbers.end();
  275. RI != RE; ++RI) {
  276. unsigned RegNum = *RI;
  277. if (InstrDesc.hasDefOfPhysReg(NodeInstr.Instruction, RegNum,
  278. *RegisterInfo)) {
  279. if (!canLoad || !InstrDesc.mayLoad())
  280. return Node;
  281. canLoad = false;
  282. CurRegisterNumbers.erase(RI);
  283. // Add the registers this load reads to those we check for clobbers.
  284. for (unsigned i = InstrDesc.getNumDefs(),
  285. e = InstrDesc.getNumOperands(); i != e; i++) {
  286. const auto &Operand = NodeInstr.Instruction.getOperand(i);
  287. if (Operand.isReg())
  288. CurRegisterNumbers.insert(Operand.getReg());
  289. }
  290. break;
  291. }
  292. }
  293. }
  294. }
  295. return Graph.BaseAddress;
  296. }
  297. void FileAnalysis::printInstruction(const Instr &InstrMeta,
  298. raw_ostream &OS) const {
  299. Printer->printInst(&InstrMeta.Instruction, 0, "", *SubtargetInfo.get(), OS);
  300. }
  301. Error FileAnalysis::initialiseDisassemblyMembers() {
  302. std::string TripleName = ObjectTriple.getTriple();
  303. ArchName = "";
  304. MCPU = "";
  305. std::string ErrorString;
  306. LLVMSymbolizer::Options Opt;
  307. Opt.UseSymbolTable = false;
  308. Symbolizer.reset(new LLVMSymbolizer(Opt));
  309. ObjectTarget =
  310. TargetRegistry::lookupTarget(ArchName, ObjectTriple, ErrorString);
  311. if (!ObjectTarget)
  312. return make_error<UnsupportedDisassembly>(
  313. (Twine("Couldn't find target \"") + ObjectTriple.getTriple() +
  314. "\", failed with error: " + ErrorString)
  315. .str());
  316. RegisterInfo.reset(ObjectTarget->createMCRegInfo(TripleName));
  317. if (!RegisterInfo)
  318. return make_error<UnsupportedDisassembly>(
  319. "Failed to initialise RegisterInfo.");
  320. MCTargetOptions MCOptions;
  321. AsmInfo.reset(
  322. ObjectTarget->createMCAsmInfo(*RegisterInfo, TripleName, MCOptions));
  323. if (!AsmInfo)
  324. return make_error<UnsupportedDisassembly>("Failed to initialise AsmInfo.");
  325. SubtargetInfo.reset(ObjectTarget->createMCSubtargetInfo(
  326. TripleName, MCPU, Features.getString()));
  327. if (!SubtargetInfo)
  328. return make_error<UnsupportedDisassembly>(
  329. "Failed to initialise SubtargetInfo.");
  330. MII.reset(ObjectTarget->createMCInstrInfo());
  331. if (!MII)
  332. return make_error<UnsupportedDisassembly>("Failed to initialise MII.");
  333. Context.reset(new MCContext(Triple(TripleName), AsmInfo.get(),
  334. RegisterInfo.get(), SubtargetInfo.get()));
  335. Disassembler.reset(
  336. ObjectTarget->createMCDisassembler(*SubtargetInfo, *Context));
  337. if (!Disassembler)
  338. return make_error<UnsupportedDisassembly>(
  339. "No disassembler available for target");
  340. MIA.reset(ObjectTarget->createMCInstrAnalysis(MII.get()));
  341. Printer.reset(ObjectTarget->createMCInstPrinter(
  342. ObjectTriple, AsmInfo->getAssemblerDialect(), *AsmInfo, *MII,
  343. *RegisterInfo));
  344. return Error::success();
  345. }
  346. Error FileAnalysis::parseCodeSections() {
  347. if (!IgnoreDWARFFlag) {
  348. std::unique_ptr<DWARFContext> DWARF = DWARFContext::create(*Object);
  349. if (!DWARF)
  350. return make_error<StringError>("Could not create DWARF information.",
  351. inconvertibleErrorCode());
  352. bool LineInfoValid = false;
  353. for (auto &Unit : DWARF->compile_units()) {
  354. const auto &LineTable = DWARF->getLineTableForUnit(Unit.get());
  355. if (LineTable && !LineTable->Rows.empty()) {
  356. LineInfoValid = true;
  357. break;
  358. }
  359. }
  360. if (!LineInfoValid)
  361. return make_error<StringError>(
  362. "DWARF line information missing. Did you compile with '-g'?",
  363. inconvertibleErrorCode());
  364. }
  365. for (const object::SectionRef &Section : Object->sections()) {
  366. // Ensure only executable sections get analysed.
  367. if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR))
  368. continue;
  369. // Avoid checking the PLT since it produces spurious failures on AArch64
  370. // when ignoring DWARF data.
  371. Expected<StringRef> NameOrErr = Section.getName();
  372. if (NameOrErr && *NameOrErr == ".plt")
  373. continue;
  374. consumeError(NameOrErr.takeError());
  375. Expected<StringRef> Contents = Section.getContents();
  376. if (!Contents)
  377. return Contents.takeError();
  378. ArrayRef<uint8_t> SectionBytes = arrayRefFromStringRef(*Contents);
  379. parseSectionContents(SectionBytes,
  380. {Section.getAddress(), Section.getIndex()});
  381. }
  382. return Error::success();
  383. }
  384. void FileAnalysis::parseSectionContents(ArrayRef<uint8_t> SectionBytes,
  385. object::SectionedAddress Address) {
  386. assert(Symbolizer && "Symbolizer is uninitialised.");
  387. MCInst Instruction;
  388. Instr InstrMeta;
  389. uint64_t InstructionSize;
  390. for (uint64_t Byte = 0; Byte < SectionBytes.size();) {
  391. bool ValidInstruction =
  392. Disassembler->getInstruction(Instruction, InstructionSize,
  393. SectionBytes.drop_front(Byte), 0,
  394. outs()) == MCDisassembler::Success;
  395. Byte += InstructionSize;
  396. uint64_t VMAddress = Address.Address + Byte - InstructionSize;
  397. InstrMeta.Instruction = Instruction;
  398. InstrMeta.VMAddress = VMAddress;
  399. InstrMeta.InstructionSize = InstructionSize;
  400. InstrMeta.Valid = ValidInstruction;
  401. addInstruction(InstrMeta);
  402. if (!ValidInstruction)
  403. continue;
  404. // Skip additional parsing for instructions that do not affect the control
  405. // flow.
  406. const auto &InstrDesc = MII->get(Instruction.getOpcode());
  407. if (!InstrDesc.mayAffectControlFlow(Instruction, *RegisterInfo))
  408. continue;
  409. uint64_t Target;
  410. if (MIA->evaluateBranch(Instruction, VMAddress, InstructionSize, Target)) {
  411. // If the target can be evaluated, it's not indirect.
  412. StaticBranchTargetings[Target].push_back(VMAddress);
  413. continue;
  414. }
  415. if (!usesRegisterOperand(InstrMeta))
  416. continue;
  417. if (InstrDesc.isReturn())
  418. continue;
  419. // Check if this instruction exists in the range of the DWARF metadata.
  420. if (!IgnoreDWARFFlag) {
  421. auto LineInfo =
  422. Symbolizer->symbolizeCode(std::string(Object->getFileName()),
  423. {VMAddress, Address.SectionIndex});
  424. if (!LineInfo) {
  425. handleAllErrors(LineInfo.takeError(), [](const ErrorInfoBase &E) {
  426. errs() << "Symbolizer failed to get line: " << E.message() << "\n";
  427. });
  428. continue;
  429. }
  430. if (LineInfo->FileName == DILineInfo::BadString)
  431. continue;
  432. }
  433. IndirectInstructions.insert({VMAddress, Address.SectionIndex});
  434. }
  435. }
  436. void FileAnalysis::addInstruction(const Instr &Instruction) {
  437. const auto &KV =
  438. Instructions.insert(std::make_pair(Instruction.VMAddress, Instruction));
  439. if (!KV.second) {
  440. errs() << "Failed to add instruction at address "
  441. << format_hex(Instruction.VMAddress, 2)
  442. << ": Instruction at this address already exists.\n";
  443. exit(EXIT_FAILURE);
  444. }
  445. }
  446. Error FileAnalysis::parseSymbolTable() {
  447. // Functions that will trap on CFI violations.
  448. SmallSet<StringRef, 4> TrapOnFailFunctions;
  449. TrapOnFailFunctions.insert("__cfi_slowpath");
  450. TrapOnFailFunctions.insert("__cfi_slowpath_diag");
  451. TrapOnFailFunctions.insert("abort");
  452. // Look through the list of symbols for functions that will trap on CFI
  453. // violations.
  454. for (auto &Sym : Object->symbols()) {
  455. auto SymNameOrErr = Sym.getName();
  456. if (!SymNameOrErr)
  457. consumeError(SymNameOrErr.takeError());
  458. else if (TrapOnFailFunctions.contains(*SymNameOrErr)) {
  459. auto AddrOrErr = Sym.getAddress();
  460. if (!AddrOrErr)
  461. consumeError(AddrOrErr.takeError());
  462. else
  463. TrapOnFailFunctionAddresses.insert(*AddrOrErr);
  464. }
  465. }
  466. if (auto *ElfObject = dyn_cast<object::ELFObjectFileBase>(Object)) {
  467. for (const auto &Addr : ElfObject->getPltAddresses()) {
  468. if (!Addr.first)
  469. continue;
  470. object::SymbolRef Sym(*Addr.first, Object);
  471. auto SymNameOrErr = Sym.getName();
  472. if (!SymNameOrErr)
  473. consumeError(SymNameOrErr.takeError());
  474. else if (TrapOnFailFunctions.contains(*SymNameOrErr))
  475. TrapOnFailFunctionAddresses.insert(Addr.second);
  476. }
  477. }
  478. return Error::success();
  479. }
  480. UnsupportedDisassembly::UnsupportedDisassembly(StringRef Text)
  481. : Text(std::string(Text)) {}
  482. char UnsupportedDisassembly::ID;
  483. void UnsupportedDisassembly::log(raw_ostream &OS) const {
  484. OS << "Could not initialise disassembler: " << Text;
  485. }
  486. std::error_code UnsupportedDisassembly::convertToErrorCode() const {
  487. return std::error_code();
  488. }
  489. } // namespace cfi_verify
  490. } // namespace llvm