FileAnalysis.cpp 19 KB

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