diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp')
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp | 114 | 
1 files changed, 97 insertions, 17 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp index 8373f0ce3f1e..6a9151570908 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -158,6 +158,8 @@ cl::opt<bool>  llvm::NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling "                                                   "instructions, do not print "                                                   "the instruction bytes.")); +cl::opt<bool> +llvm::NoLeadingAddr("no-leading-addr", cl::desc("Print no leading address"));  cl::opt<bool>  llvm::UnwindInfo("unwind-info", cl::desc("Display unwind information")); @@ -213,6 +215,8 @@ cl::opt<unsigned long long>                  cl::value_desc("address"), cl::init(UINT64_MAX));  static StringRef ToolName; +typedef std::vector<std::tuple<uint64_t, StringRef, uint8_t>> SectionSymbolsTy; +  namespace {  typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate; @@ -357,7 +361,16 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {    llvm::Triple TheTriple("unknown-unknown-unknown");    if (TripleName.empty()) {      if (Obj) { -      TheTriple.setArch(Triple::ArchType(Obj->getArch())); +      auto Arch = Obj->getArch(); +      TheTriple.setArch(Triple::ArchType(Arch)); + +      // For ARM targets, try to use the build attributes to build determine +      // the build target. Target features are also added, but later during +      // disassembly. +      if (Arch == Triple::arm || Arch == Triple::armeb) { +        Obj->setARMSubArch(TheTriple); +      } +        // TheTriple defaults to ELF, and COFF doesn't have an environment:        // the best we can do here is indicate that it is mach-o.        if (Obj->isMachO()) @@ -369,8 +382,16 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {            TheTriple.setTriple("thumbv7-windows");        }      } -  } else +  } else {      TheTriple.setTriple(Triple::normalize(TripleName)); +    // Use the triple, but also try to combine with ARM build attributes. +    if (Obj) { +      auto Arch = Obj->getArch(); +      if (Arch == Triple::arm || Arch == Triple::armeb) { +        Obj->setARMSubArch(TheTriple); +      } +    } +  }    // Get the target specific parser.    std::string Error; @@ -464,10 +485,13 @@ void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address,      auto FileBuffer = SourceCache.find(LineInfo.FileName);      if (FileBuffer != SourceCache.end()) {        auto LineBuffer = LineCache.find(LineInfo.FileName); -      if (LineBuffer != LineCache.end()) +      if (LineBuffer != LineCache.end()) { +        if (LineInfo.Line > LineBuffer->second.size()) +          return;          // Vector begins at 0, line numbers are non-zero          OS << Delimiter << LineBuffer->second[LineInfo.Line - 1].ltrim()             << "\n"; +      }      }    }    OldLineInfo = LineInfo; @@ -491,7 +515,8 @@ public:                           MCSubtargetInfo const &STI, SourcePrinter *SP) {      if (SP && (PrintSource || PrintLines))        SP->printSourceLine(OS, Address); -    OS << format("%8" PRIx64 ":", Address); +    if (!NoLeadingAddr) +      OS << format("%8" PRIx64 ":", Address);      if (!NoShowRawInsn) {        OS << "\t";        dumpBytes(Bytes, OS); @@ -509,7 +534,8 @@ public:                   raw_ostream &OS) {      uint32_t opcode =        (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0]; -    OS << format("%8" PRIx64 ":", Address); +    if (!NoLeadingAddr) +      OS << format("%8" PRIx64 ":", Address);      if (!NoShowRawInsn) {        OS << "\t";        dumpBytes(Bytes.slice(0, 4), OS); @@ -570,6 +596,9 @@ public:    void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,                   uint64_t Address, raw_ostream &OS, StringRef Annot,                   MCSubtargetInfo const &STI, SourcePrinter *SP) override { +    if (SP && (PrintSource || PrintLines)) +      SP->printSourceLine(OS, Address); +      if (!MI) {        OS << " <unknown>";        return; @@ -601,7 +630,8 @@ public:                   MCSubtargetInfo const &STI, SourcePrinter *SP) override {      if (SP && (PrintSource || PrintLines))        SP->printSourceLine(OS, Address); -    OS << format("%8" PRId64 ":", Address / 8); +    if (!NoLeadingAddr) +      OS << format("%8" PRId64 ":", Address / 8);      if (!NoShowRawInsn) {        OS << "\t";        dumpBytes(Bytes, OS); @@ -1091,6 +1121,52 @@ static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) {    llvm_unreachable("Unsupported binary format");  } +template <class ELFT> static void +addDynamicElfSymbols(const ELFObjectFile<ELFT> *Obj, +                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) { +  for (auto Symbol : Obj->getDynamicSymbolIterators()) { +    uint8_t SymbolType = Symbol.getELFType(); +    if (SymbolType != ELF::STT_FUNC || Symbol.getSize() == 0) +      continue; + +    Expected<uint64_t> AddressOrErr = Symbol.getAddress(); +    if (!AddressOrErr) +      report_error(Obj->getFileName(), AddressOrErr.takeError()); +    uint64_t Address = *AddressOrErr; + +    Expected<StringRef> Name = Symbol.getName(); +    if (!Name) +      report_error(Obj->getFileName(), Name.takeError()); +    if (Name->empty()) +      continue; + +    Expected<section_iterator> SectionOrErr = Symbol.getSection(); +    if (!SectionOrErr) +      report_error(Obj->getFileName(), SectionOrErr.takeError()); +    section_iterator SecI = *SectionOrErr; +    if (SecI == Obj->section_end()) +      continue; + +    AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); +  } +} + +static void +addDynamicElfSymbols(const ObjectFile *Obj, +                     std::map<SectionRef, SectionSymbolsTy> &AllSymbols) { +  assert(Obj->isELF()); +  if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj)) +    addDynamicElfSymbols(Elf32LEObj, AllSymbols); +  else if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj)) +    addDynamicElfSymbols(Elf64LEObj, AllSymbols); +  else if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj)) +    addDynamicElfSymbols(Elf32BEObj, AllSymbols); +  else if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj)) +    addDynamicElfSymbols(Elf64BEObj, AllSymbols); +  else +    llvm_unreachable("Unsupported binary format"); +} +  static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    if (StartAddress > StopAddress)      error("Start address should be less than stop address"); @@ -1165,7 +1241,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    // Create a mapping from virtual address to symbol name.  This is used to    // pretty print the symbols while disassembling. -  typedef std::vector<std::tuple<uint64_t, StringRef, uint8_t>> SectionSymbolsTy;    std::map<SectionRef, SectionSymbolsTy> AllSymbols;    for (const SymbolRef &Symbol : Obj->symbols()) {      Expected<uint64_t> AddressOrErr = Symbol.getAddress(); @@ -1193,6 +1268,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType);    } +  if (AllSymbols.empty() && Obj->isELF()) +    addDynamicElfSymbols(Obj, AllSymbols);    // Create a mapping from virtual address to section.    std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses; @@ -1811,9 +1888,9 @@ void llvm::printExportsTrie(const ObjectFile *o) {    }  } -void llvm::printRebaseTable(const ObjectFile *o) { +void llvm::printRebaseTable(ObjectFile *o) {    outs() << "Rebase table:\n"; -  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) +  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))      printMachORebaseTable(MachO);    else {      errs() << "This operation is only currently supported " @@ -1822,9 +1899,9 @@ void llvm::printRebaseTable(const ObjectFile *o) {    }  } -void llvm::printBindTable(const ObjectFile *o) { +void llvm::printBindTable(ObjectFile *o) {    outs() << "Bind table:\n"; -  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) +  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))      printMachOBindTable(MachO);    else {      errs() << "This operation is only currently supported " @@ -1833,9 +1910,9 @@ void llvm::printBindTable(const ObjectFile *o) {    }  } -void llvm::printLazyBindTable(const ObjectFile *o) { +void llvm::printLazyBindTable(ObjectFile *o) {    outs() << "Lazy bind table:\n"; -  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) +  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))      printMachOLazyBindTable(MachO);    else {      errs() << "This operation is only currently supported " @@ -1844,9 +1921,9 @@ void llvm::printLazyBindTable(const ObjectFile *o) {    }  } -void llvm::printWeakBindTable(const ObjectFile *o) { +void llvm::printWeakBindTable(ObjectFile *o) {    outs() << "Weak bind table:\n"; -  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o)) +  if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))      printMachOWeakBindTable(MachO);    else {      errs() << "This operation is only currently supported " @@ -1944,7 +2021,7 @@ static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) {    report_error(o->getFileName(), "Invalid/Unsupported object file format");  } -static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) { +static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {    StringRef ArchiveName = a != nullptr ? a->getFileName() : "";    // Avoid other output when using a raw option.    if (!RawClangAST) { @@ -1987,7 +2064,10 @@ static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) {    if (DwarfDumpType != DIDT_Null) {      std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*o));      // Dump the complete DWARF structure. -    DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */); +    DIDumpOptions DumpOpts; +    DumpOpts.DumpType = DwarfDumpType; +    DumpOpts.DumpEH = true; +    DICtx->dump(outs(), DumpOpts);    }  }  | 
