diff options
Diffstat (limited to 'tools/llvm-cfi-verify/lib/FileAnalysis.cpp')
-rw-r--r-- | tools/llvm-cfi-verify/lib/FileAnalysis.cpp | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/tools/llvm-cfi-verify/lib/FileAnalysis.cpp b/tools/llvm-cfi-verify/lib/FileAnalysis.cpp index 29819d8d28e..8dc0802c465 100644 --- a/tools/llvm-cfi-verify/lib/FileAnalysis.cpp +++ b/tools/llvm-cfi-verify/lib/FileAnalysis.cpp @@ -105,6 +105,9 @@ Expected<FileAnalysis> FileAnalysis::Create(StringRef Filename) { if (auto SectionParseResponse = Analysis.parseCodeSections()) return std::move(SectionParseResponse); + if (auto SymbolTableParseResponse = Analysis.parseSymbolTable()) + return std::move(SymbolTableParseResponse); + return std::move(Analysis); } @@ -165,7 +168,18 @@ const Instr &FileAnalysis::getInstructionOrDie(uint64_t Address) const { bool FileAnalysis::isCFITrap(const Instr &InstrMeta) const { const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode()); - return InstrDesc.isTrap(); + return InstrDesc.isTrap() || willTrapOnCFIViolation(InstrMeta); +} + +bool FileAnalysis::willTrapOnCFIViolation(const Instr &InstrMeta) const { + const auto &InstrDesc = MII->get(InstrMeta.Instruction.getOpcode()); + if (!InstrDesc.isCall()) + return false; + uint64_t Target; + if (!MIA->evaluateBranch(InstrMeta.Instruction, InstrMeta.VMAddress, + InstrMeta.InstructionSize, Target)) + return false; + return TrapOnFailFunctionAddresses.count(Target) > 0; } bool FileAnalysis::canFallThrough(const Instr &InstrMeta) const { @@ -431,6 +445,12 @@ Error FileAnalysis::parseCodeSections() { if (!(object::ELFSectionRef(Section).getFlags() & ELF::SHF_EXECINSTR)) continue; + // Avoid checking the PLT since it produces spurious failures on AArch64 + // when ignoring DWARF data. + StringRef SectionName; + if (!Section.getName(SectionName) && SectionName == ".plt") + continue; + StringRef SectionContents; if (Section.getContents(SectionContents)) return make_error<StringError>("Failed to retrieve section contents", @@ -518,6 +538,40 @@ void FileAnalysis::addInstruction(const Instr &Instruction) { } } +Error FileAnalysis::parseSymbolTable() { + // Functions that will trap on CFI violations. + SmallSet<StringRef, 4> TrapOnFailFunctions; + TrapOnFailFunctions.insert("__cfi_slowpath"); + TrapOnFailFunctions.insert("__cfi_slowpath_diag"); + TrapOnFailFunctions.insert("abort"); + + // Look through the list of symbols for functions that will trap on CFI + // violations. + for (auto &Sym : Object->symbols()) { + auto SymNameOrErr = Sym.getName(); + if (!SymNameOrErr) + consumeError(SymNameOrErr.takeError()); + else if (TrapOnFailFunctions.count(*SymNameOrErr) > 0) { + auto AddrOrErr = Sym.getAddress(); + if (!AddrOrErr) + consumeError(AddrOrErr.takeError()); + else + TrapOnFailFunctionAddresses.insert(*AddrOrErr); + } + } + if (auto *ElfObject = dyn_cast<object::ELFObjectFileBase>(Object)) { + for (const auto &Addr : ElfObject->getPltAddresses()) { + object::SymbolRef Sym(Addr.first, Object); + auto SymNameOrErr = Sym.getName(); + if (!SymNameOrErr) + consumeError(SymNameOrErr.takeError()); + else if (TrapOnFailFunctions.count(*SymNameOrErr) > 0) + TrapOnFailFunctionAddresses.insert(Addr.second); + } + } + return Error::success(); +} + UnsupportedDisassembly::UnsupportedDisassembly(StringRef Text) : Text(Text) {} char UnsupportedDisassembly::ID; |