diff options
| author | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2017-10-10 21:21:13 +0000 |
|---|---|---|
| committer | Vlad Tsyrklevich <vlad@tsyrklevich.net> | 2017-10-10 21:21:13 +0000 |
| commit | a45919f54d4c0c33d7d633498669180accb7beca (patch) | |
| tree | 757fb4930eb97560e67e4f7f60291919eaeb3467 /llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp | |
| parent | 3f56a05ae57db4c4efd0717dd72aa437fb9376f9 (diff) | |
| download | bcm5719-llvm-a45919f54d4c0c33d7d633498669180accb7beca.tar.gz bcm5719-llvm-a45919f54d4c0c33d7d633498669180accb7beca.zip | |
Revert "Classify llvm-cfi-verify."
This reverts commit r315363. It has a simple build failure, but more
importantly I want to confirm that unit tests run in check-all to make
sure that they don't silently break in the future.
llvm-svn: 315370
Diffstat (limited to 'llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp')
| -rw-r--r-- | llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp | 212 |
1 files changed, 196 insertions, 16 deletions
diff --git a/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp b/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp index 2aaa702abf8..63dc6f128e1 100644 --- a/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp +++ b/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp @@ -17,31 +17,64 @@ // //===----------------------------------------------------------------------===// -#include "FileAnalysis.h" - -#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> #include <cstdlib> using namespace llvm; using namespace llvm::object; -using namespace llvm::cfi_verify; +cl::opt<bool> ArgDumpSymbols("sym", cl::desc("Dump the symbol table.")); cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::Required); -ExitOnError ExitOnErr; +static void printSymbols(const ObjectFile *Object) { + for (const SymbolRef &Symbol : Object->symbols()) { + outs() << "Symbol [" << format_hex_no_prefix(Symbol.getValue(), 2) + << "] = "; + + auto SymbolName = Symbol.getName(); + if (SymbolName) + outs() << *SymbolName; + else + outs() << "UNKNOWN"; + + if (Symbol.getFlags() & SymbolRef::SF_Hidden) + outs() << " .hidden"; + + outs() << " (Section = "; + + auto SymbolSection = Symbol.getSection(); + if (SymbolSection) { + StringRef SymbolSectionName; + if ((*SymbolSection)->getName(SymbolSectionName)) + outs() << "UNKNOWN)"; + else + outs() << SymbolSectionName << ")"; + } else { + outs() << "N/A)"; + } -void printIndirectCFInstructions(const FileAnalysis &Verifier) { - for (uint64_t Address : Verifier.getIndirectInstructions()) { - const auto &InstrMeta = Verifier.getInstructionOrDie(Address); - outs() << format_hex(Address, 2) << " |" - << Verifier.getMCInstrInfo()->getName( - InstrMeta.Instruction.getOpcode()) - << " "; - InstrMeta.Instruction.print(outs()); outs() << "\n"; } } @@ -54,8 +87,155 @@ int main(int argc, char **argv) { InitializeAllAsmParsers(); InitializeAllDisassemblers(); - FileAnalysis Verifier = ExitOnErr(FileAnalysis::Create(InputFilename)); - printIndirectCFInstructions(Verifier); + Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFilename); + if (!BinaryOrErr) { + errs() << "Failed to open file.\n"; + return EXIT_FAILURE; + } + + Binary &Binary = *BinaryOrErr.get().getBinary(); + ObjectFile *Object = dyn_cast<ObjectFile>(&Binary); + if (!Object) { + errs() << "Disassembling of non-objects not currently supported.\n"; + return EXIT_FAILURE; + } + + Triple TheTriple = Object->makeTriple(); + std::string TripleName = TheTriple.getTriple(); + std::string ArchName = ""; + std::string ErrorString; + + const Target *TheTarget = + TargetRegistry::lookupTarget(ArchName, TheTriple, ErrorString); + + if (!TheTarget) { + errs() << "Couldn't find target \"" << TheTriple.getTriple() + << "\", failed with error: " << ErrorString << ".\n"; + return EXIT_FAILURE; + } + + SubtargetFeatures Features = Object->getFeatures(); + + std::unique_ptr<const MCRegisterInfo> RegisterInfo( + TheTarget->createMCRegInfo(TripleName)); + if (!RegisterInfo) { + errs() << "Failed to initialise RegisterInfo.\n"; + return EXIT_FAILURE; + } + + std::unique_ptr<const MCAsmInfo> AsmInfo( + TheTarget->createMCAsmInfo(*RegisterInfo, TripleName)); + if (!AsmInfo) { + errs() << "Failed to initialise AsmInfo.\n"; + return EXIT_FAILURE; + } + + std::string MCPU = ""; + std::unique_ptr<MCSubtargetInfo> SubtargetInfo( + TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); + if (!SubtargetInfo) { + errs() << "Failed to initialise SubtargetInfo.\n"; + return EXIT_FAILURE; + } + + std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); + if (!MII) { + errs() << "Failed to initialise MII.\n"; + return EXIT_FAILURE; + } + + MCObjectFileInfo MOFI; + MCContext Context(AsmInfo.get(), RegisterInfo.get(), &MOFI); + + std::unique_ptr<const MCDisassembler> Disassembler( + TheTarget->createMCDisassembler(*SubtargetInfo, Context)); + + if (!Disassembler) { + errs() << "No disassembler available for target."; + return EXIT_FAILURE; + } + + std::unique_ptr<const MCInstrAnalysis> MIA( + TheTarget->createMCInstrAnalysis(MII.get())); + + std::unique_ptr<MCInstPrinter> Printer( + TheTarget->createMCInstPrinter(TheTriple, AsmInfo->getAssemblerDialect(), + *AsmInfo, *MII, *RegisterInfo)); + + if (ArgDumpSymbols) + printSymbols(Object); + + for (const SectionRef &Section : Object->sections()) { + outs() << "Section [" << format_hex_no_prefix(Section.getAddress(), 2) + << "] = "; + StringRef SectionName; + + if (Section.getName(SectionName)) + outs() << "UNKNOWN.\n"; + else + outs() << SectionName << "\n"; + + StringRef SectionContents; + if (Section.getContents(SectionContents)) { + errs() << "Failed to retrieve section contents.\n"; + return EXIT_FAILURE; + } + + MCInst Instruction; + uint64_t InstructionSize; + + ArrayRef<uint8_t> SectionBytes((const uint8_t *)SectionContents.data(), + Section.getSize()); + + for (uint64_t Byte = 0; Byte < Section.getSize();) { + bool BadInstruction = false; + + // Disassemble the instruction. + if (Disassembler->getInstruction( + Instruction, InstructionSize, SectionBytes.drop_front(Byte), 0, + nulls(), outs()) != MCDisassembler::Success) { + BadInstruction = true; + } + + Byte += InstructionSize; + + if (BadInstruction) + continue; + + // Skip instructions that do not affect the control flow. + const auto &InstrDesc = MII->get(Instruction.getOpcode()); + if (!InstrDesc.mayAffectControlFlow(Instruction, *RegisterInfo)) + continue; + + // Skip instructions that do not operate on register operands. + bool UsesRegisterOperand = false; + for (const auto &Operand : Instruction) { + if (Operand.isReg()) + UsesRegisterOperand = true; + } + + if (!UsesRegisterOperand) + continue; + + // Print the instruction address. + outs() << " " + << format_hex(Section.getAddress() + Byte - InstructionSize, 2) + << ": "; + + // Print the instruction bytes. + for (uint64_t i = 0; i < InstructionSize; ++i) { + outs() << format_hex_no_prefix(SectionBytes[Byte - InstructionSize + i], + 2) + << " "; + } + + // Print the instruction. + outs() << " | " << MII->getName(Instruction.getOpcode()) << " "; + Instruction.dump_pretty(outs(), Printer.get()); + + outs() << "\n"; + } + } return EXIT_SUCCESS; } |

