diff options
Diffstat (limited to 'tools/llvm-objdump/llvm-objdump.cpp')
| -rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 562 | 
1 files changed, 321 insertions, 241 deletions
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 275eb9c6a454..22167c788901 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -73,6 +73,13 @@ Disassembled("d", cl::desc("Alias for --disassemble"),               cl::aliasopt(Disassemble));  cl::opt<bool> +llvm::DisassembleAll("disassemble-all", +  cl::desc("Display assembler mnemonics for the machine instructions")); +static cl::alias +DisassembleAlld("D", cl::desc("Alias for --disassemble-all"), +             cl::aliasopt(DisassembleAll)); + +cl::opt<bool>  llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));  cl::opt<bool> @@ -130,6 +137,13 @@ SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),                        cl::aliasopt(SectionHeaders));  cl::list<std::string> +llvm::FilterSections("section", cl::desc("Operate on the specified sections only. " +                                         "With -macho dump segment,section")); +cl::alias +static FilterSectionsj("j", cl::desc("Alias for --section"), +                 cl::aliasopt(llvm::FilterSections)); + +cl::list<std::string>  llvm::MAttrs("mattr",    cl::CommaSeparated,    cl::desc("Target specific attributes"), @@ -163,22 +177,86 @@ cl::opt<bool> PrintFaultMaps("fault-map-section",                               cl::desc("Display contents of faultmap section"));  static StringRef ToolName; -static int ReturnValue = EXIT_SUCCESS; -bool llvm::error(std::error_code EC) { +namespace { +typedef std::function<bool(llvm::object::SectionRef const &)> FilterPredicate; + +class SectionFilterIterator { +public: +  SectionFilterIterator(FilterPredicate P, +                        llvm::object::section_iterator const &I, +                        llvm::object::section_iterator const &E) +      : Predicate(P), Iterator(I), End(E) { +    ScanPredicate(); +  } +  const llvm::object::SectionRef &operator*() const { return *Iterator; } +  SectionFilterIterator &operator++() { +    ++Iterator; +    ScanPredicate(); +    return *this; +  } +  bool operator!=(SectionFilterIterator const &Other) const { +    return Iterator != Other.Iterator; +  } + +private: +  void ScanPredicate() { +    while (Iterator != End && !Predicate(*Iterator)) { +      ++Iterator; +    } +  } +  FilterPredicate Predicate; +  llvm::object::section_iterator Iterator; +  llvm::object::section_iterator End; +}; + +class SectionFilter { +public: +  SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O) +      : Predicate(P), Object(O) {} +  SectionFilterIterator begin() { +    return SectionFilterIterator(Predicate, Object.section_begin(), +                                 Object.section_end()); +  } +  SectionFilterIterator end() { +    return SectionFilterIterator(Predicate, Object.section_end(), +                                 Object.section_end()); +  } + +private: +  FilterPredicate Predicate; +  llvm::object::ObjectFile const &Object; +}; +SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) { +  return SectionFilter([](llvm::object::SectionRef const &S) { +                         if(FilterSections.empty()) +                           return true; +                         llvm::StringRef String; +                         std::error_code error = S.getName(String); +                         if (error) +                           return false; +                         return std::find(FilterSections.begin(), +                                          FilterSections.end(), +                                          String) != FilterSections.end(); +                       }, +                       O); +} +} + +void llvm::error(std::error_code EC) {    if (!EC) -    return false; +    return; -  outs() << ToolName << ": error reading file: " << EC.message() << ".\n"; -  outs().flush(); -  ReturnValue = EXIT_FAILURE; -  return true; +  errs() << ToolName << ": error reading file: " << EC.message() << ".\n"; +  errs().flush(); +  exit(1);  } -static void report_error(StringRef File, std::error_code EC) { +LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, +                                                std::error_code EC) {    assert(EC);    errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n"; -  ReturnValue = EXIT_FAILURE; +  exit(1);  }  static const Target *getTarget(const ObjectFile *Obj = nullptr) { @@ -205,10 +283,8 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {    std::string Error;    const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple,                                                           Error); -  if (!TheTarget) { -    errs() << ToolName << ": " << Error; -    return nullptr; -  } +  if (!TheTarget) +    report_fatal_error("can't find target: " + Error);    // Update the triple name and return the found target.    TripleName = TheTriple.getTriple(); @@ -301,11 +377,12 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) {  template <class ELFT>  static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, -                                                DataRefImpl Rel, +                                                const RelocationRef &RelRef,                                                  SmallVectorImpl<char> &Result) { +  DataRefImpl Rel = RelRef.getRawDataRefImpl(); +    typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;    typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; -  typedef typename ELFObjectFile<ELFT>::Elf_Rel Elf_Rel;    typedef typename ELFObjectFile<ELFT>::Elf_Rela Elf_Rela;    const ELFFile<ELFT> &EF = *Obj->getELFFile(); @@ -327,36 +404,31 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,    if (std::error_code EC = StrTabOrErr.getError())      return EC;    StringRef StrTab = *StrTabOrErr; -  uint8_t type; +  uint8_t type = RelRef.getType();    StringRef res;    int64_t addend = 0; -  uint16_t symbol_index = 0;    switch (Sec->sh_type) {    default:      return object_error::parse_failed;    case ELF::SHT_REL: { -    const Elf_Rel *ERel = Obj->getRel(Rel); -    type = ERel->getType(EF.isMips64EL()); -    symbol_index = ERel->getSymbol(EF.isMips64EL());      // TODO: Read implicit addend from section data.      break;    }    case ELF::SHT_RELA: {      const Elf_Rela *ERela = Obj->getRela(Rel); -    type = ERela->getType(EF.isMips64EL()); -    symbol_index = ERela->getSymbol(EF.isMips64EL());      addend = ERela->r_addend;      break;    }    } -  const Elf_Sym *symb = -      EF.template getEntry<Elf_Sym>(Sec->sh_link, symbol_index); +  symbol_iterator SI = RelRef.getSymbol(); +  const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());    StringRef Target; -  ErrorOr<const Elf_Shdr *> SymSec = EF.getSection(symb); -  if (std::error_code EC = SymSec.getError()) -    return EC;    if (symb->getType() == ELF::STT_SECTION) { -    ErrorOr<StringRef> SecName = EF.getSectionName(*SymSec); +    ErrorOr<section_iterator> SymSI = SI->getSection(); +    if (std::error_code EC = SymSI.getError()) +      return EC; +    const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); +    ErrorOr<StringRef> SecName = EF.getSectionName(SymSec);      if (std::error_code EC = SecName.getError())        return EC;      Target = *SecName; @@ -404,6 +476,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,      break;    }    case ELF::EM_386: +  case ELF::EM_IAMCU:    case ELF::EM_ARM:    case ELF::EM_HEXAGON:    case ELF::EM_MIPS: @@ -418,9 +491,8 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,  }  static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, -                                                const RelocationRef &RelRef, +                                                const RelocationRef &Rel,                                                  SmallVectorImpl<char> &Result) { -  DataRefImpl Rel = RelRef.getRawDataRefImpl();    if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))      return getRelocationValueString(ELF32LE, Rel, Result);    if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj)) @@ -471,7 +543,7 @@ static void printRelocationTargetName(const MachOObjectFile *O,      // If we couldn't find a symbol that this relocation refers to, try      // to find a section beginning instead. -    for (const SectionRef &Section : O->sections()) { +    for (const SectionRef &Section : ToolSectionFilter(*O)) {        std::error_code ec;        StringRef Name; @@ -496,8 +568,8 @@ static void printRelocationTargetName(const MachOObjectFile *O,      symbol_iterator SI = O->symbol_begin();      advance(SI, Val);      ErrorOr<StringRef> SOrErr = SI->getName(); -    if (!error(SOrErr.getError())) -      S = *SOrErr; +    error(SOrErr.getError()); +    S = *SOrErr;    } else {      section_iterator SI = O->section_begin();      // Adjust for the fact that sections are 1-indexed. @@ -732,10 +804,6 @@ static bool getHidden(RelocationRef RelRef) {  static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    const Target *TheTarget = getTarget(Obj); -  // getTarget() will have already issued a diagnostic if necessary, so -  // just bail here if it failed. -  if (!TheTarget) -    return;    // Package up features to be passed to target/subtarget    std::string FeaturesStr; @@ -748,42 +816,28 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    std::unique_ptr<const MCRegisterInfo> MRI(        TheTarget->createMCRegInfo(TripleName)); -  if (!MRI) { -    errs() << "error: no register info for target " << TripleName << "\n"; -    return; -  } +  if (!MRI) +    report_fatal_error("error: no register info for target " + TripleName);    // Set up disassembler.    std::unique_ptr<const MCAsmInfo> AsmInfo(        TheTarget->createMCAsmInfo(*MRI, TripleName)); -  if (!AsmInfo) { -    errs() << "error: no assembly info for target " << TripleName << "\n"; -    return; -  } - +  if (!AsmInfo) +    report_fatal_error("error: no assembly info for target " + TripleName);    std::unique_ptr<const MCSubtargetInfo> STI(        TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); -  if (!STI) { -    errs() << "error: no subtarget info for target " << TripleName << "\n"; -    return; -  } - +  if (!STI) +    report_fatal_error("error: no subtarget info for target " + TripleName);    std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); -  if (!MII) { -    errs() << "error: no instruction info for target " << TripleName << "\n"; -    return; -  } - +  if (!MII) +    report_fatal_error("error: no instruction info for target " + TripleName);    std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);    MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());    std::unique_ptr<MCDisassembler> DisAsm(      TheTarget->createMCDisassembler(*STI, Ctx)); - -  if (!DisAsm) { -    errs() << "error: no disassembler for target " << TripleName << "\n"; -    return; -  } +  if (!DisAsm) +    report_fatal_error("error: no disassembler for target " + TripleName);    std::unique_ptr<const MCInstrAnalysis> MIA(        TheTarget->createMCInstrAnalysis(MII.get())); @@ -791,11 +845,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    int AsmPrinterVariant = AsmInfo->getAssemblerDialect();    std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(        Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI)); -  if (!IP) { -    errs() << "error: no instruction printer for target " << TripleName -      << '\n'; -    return; -  } +  if (!IP) +    report_fatal_error("error: no instruction printer for target " + +                       TripleName);    IP->setPrintImmHex(PrintImmHex);    PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); @@ -806,38 +858,75 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    // in RelocSecs contain the relocations for section S.    std::error_code EC;    std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap; -  for (const SectionRef &Section : Obj->sections()) { +  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      section_iterator Sec2 = Section.getRelocatedSection();      if (Sec2 != Obj->section_end())        SectionRelocMap[*Sec2].push_back(Section);    }    // Create a mapping from virtual address to symbol name.  This is used to -  // pretty print the target of a call. -  std::vector<std::pair<uint64_t, StringRef>> AllSymbols; -  if (MIA) { -    for (const SymbolRef &Symbol : Obj->symbols()) { -      if (Symbol.getType() != SymbolRef::ST_Function) -        continue; +  // pretty print the symbols while disassembling. +  typedef std::vector<std::pair<uint64_t, StringRef>> SectionSymbolsTy; +  std::map<SectionRef, SectionSymbolsTy> AllSymbols; +  for (const SymbolRef &Symbol : Obj->symbols()) { +    ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress(); +    error(AddressOrErr.getError()); +    uint64_t Address = *AddressOrErr; + +    ErrorOr<StringRef> Name = Symbol.getName(); +    error(Name.getError()); +    if (Name->empty()) +      continue; -      ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress(); -      if (error(AddressOrErr.getError())) -        break; -      uint64_t Address = *AddressOrErr; +    ErrorOr<section_iterator> SectionOrErr = Symbol.getSection(); +    error(SectionOrErr.getError()); +    section_iterator SecI = *SectionOrErr; +    if (SecI == Obj->section_end()) +      continue; -      ErrorOr<StringRef> Name = Symbol.getName(); -      if (error(Name.getError())) -        break; -      if (Name->empty()) +    AllSymbols[*SecI].emplace_back(Address, *Name); +  } + +  // Create a mapping from virtual address to section. +  std::vector<std::pair<uint64_t, SectionRef>> SectionAddresses; +  for (SectionRef Sec : Obj->sections()) +    SectionAddresses.emplace_back(Sec.getAddress(), Sec); +  array_pod_sort(SectionAddresses.begin(), SectionAddresses.end()); + +  // Linked executables (.exe and .dll files) typically don't include a real +  // symbol table but they might contain an export table. +  if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) { +    for (const auto &ExportEntry : COFFObj->export_directories()) { +      StringRef Name; +      error(ExportEntry.getSymbolName(Name)); +      if (Name.empty())          continue; -      AllSymbols.push_back(std::make_pair(Address, *Name)); -    } +      uint32_t RVA; +      error(ExportEntry.getExportRVA(RVA)); + +      uint64_t VA = COFFObj->getImageBase() + RVA; +      auto Sec = std::upper_bound( +          SectionAddresses.begin(), SectionAddresses.end(), VA, +          [](uint64_t LHS, const std::pair<uint64_t, SectionRef> &RHS) { +            return LHS < RHS.first; +          }); +      if (Sec != SectionAddresses.begin()) +        --Sec; +      else +        Sec = SectionAddresses.end(); -    array_pod_sort(AllSymbols.begin(), AllSymbols.end()); +      if (Sec != SectionAddresses.end()) +        AllSymbols[Sec->second].emplace_back(VA, Name); +    }    } -  for (const SectionRef &Section : Obj->sections()) { -    if (!Section.isText() || Section.isVirtual()) +  // Sort all the symbols, this allows us to use a simple binary search to find +  // a symbol near an address. +  for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols) +    array_pod_sort(SecSyms.second.begin(), SecSyms.second.end()); + +  for (const SectionRef &Section : ToolSectionFilter(*Obj)) { +    if (!DisassembleAll && (!Section.isText() || Section.isVirtual()))        continue;      uint64_t SectionAddr = Section.getAddress(); @@ -845,27 +934,23 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      if (!SectSize)        continue; -    // Make a list of all the symbols in this section. -    std::vector<std::pair<uint64_t, StringRef>> Symbols; -    for (const SymbolRef &Symbol : Obj->symbols()) { -      if (Section.containsSymbol(Symbol)) { -        ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress(); -        if (error(AddressOrErr.getError())) -          break; -        uint64_t Address = *AddressOrErr; -        Address -= SectionAddr; -        if (Address >= SectSize) -          continue; - -        ErrorOr<StringRef> Name = Symbol.getName(); -        if (error(Name.getError())) -          break; -        Symbols.push_back(std::make_pair(Address, *Name)); +    // Get the list of all the symbols in this section. +    SectionSymbolsTy &Symbols = AllSymbols[Section]; +    std::vector<uint64_t> DataMappingSymsAddr; +    std::vector<uint64_t> TextMappingSymsAddr; +    if (Obj->isELF() && Obj->getArch() == Triple::aarch64) { +      for (const auto &Symb : Symbols) { +        uint64_t Address = Symb.first; +        StringRef Name = Symb.second; +        if (Name.startswith("$d")) +          DataMappingSymsAddr.push_back(Address - SectionAddr); +        if (Name.startswith("$x")) +          TextMappingSymsAddr.push_back(Address - SectionAddr);        }      } -    // Sort the symbols by address, just in case they didn't come in that way. -    array_pod_sort(Symbols.begin(), Symbols.end()); +    std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end()); +    std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());      // Make a list of all the relocations for this section.      std::vector<RelocationRef> Rels; @@ -886,8 +971,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {        SegmentName = MachO->getSectionFinalSegmentName(DR);      }      StringRef name; -    if (error(Section.getName(name))) -      break; +    error(Section.getName(name));      outs() << "Disassembly of section ";      if (!SegmentName.empty())        outs() << SegmentName << ","; @@ -895,14 +979,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      // If the section has no symbol at the start, just insert a dummy one.      if (Symbols.empty() || Symbols[0].first != 0) -      Symbols.insert(Symbols.begin(), std::make_pair(0, name)); +      Symbols.insert(Symbols.begin(), std::make_pair(SectionAddr, name));      SmallString<40> Comments;      raw_svector_ostream CommentStream(Comments);      StringRef BytesStr; -    if (error(Section.getContents(BytesStr))) -      break; +    error(Section.getContents(BytesStr));      ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),                              BytesStr.size()); @@ -914,11 +997,16 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      // Disassemble symbol by symbol.      for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { -      uint64_t Start = Symbols[si].first; -      // The end is either the section end or the beginning of the next symbol. -      uint64_t End = (si == se - 1) ? SectSize : Symbols[si + 1].first; +      uint64_t Start = Symbols[si].first - SectionAddr; +      // The end is either the section end or the beginning of the next +      // symbol. +      uint64_t End = +          (si == se - 1) ? SectSize : Symbols[si + 1].first - SectionAddr; +      // Don't try to disassemble beyond the end of section contents. +      if (End > SectSize) +        End = SectSize;        // If this symbol has the same address as the next symbol, then skip it. -      if (Start == End) +      if (Start >= End)          continue;        outs() << '\n' << Symbols[si].second << ":\n"; @@ -932,6 +1020,45 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {        for (Index = Start; Index < End; Index += Size) {          MCInst Inst; +        // AArch64 ELF binaries can interleave data and text in the +        // same section. We rely on the markers introduced to +        // understand what we need to dump. +        if (Obj->isELF() && Obj->getArch() == Triple::aarch64) { +          uint64_t Stride = 0; + +          auto DAI = std::lower_bound(DataMappingSymsAddr.begin(), +                                      DataMappingSymsAddr.end(), Index); +          if (DAI != DataMappingSymsAddr.end() && *DAI == Index) { +            // Switch to data. +            while (Index < End) { +              outs() << format("%8" PRIx64 ":", SectionAddr + Index); +              outs() << "\t"; +              if (Index + 4 <= End) { +                Stride = 4; +                dumpBytes(Bytes.slice(Index, 4), outs()); +                outs() << "\t.word"; +              } else if (Index + 2 <= End) { +                Stride = 2; +                dumpBytes(Bytes.slice(Index, 2), outs()); +                outs() << "\t.short"; +              } else { +                Stride = 1; +                dumpBytes(Bytes.slice(Index, 1), outs()); +                outs() << "\t.byte"; +              } +              Index += Stride; +              outs() << "\n"; +              auto TAI = std::lower_bound(TextMappingSymsAddr.begin(), +                                          TextMappingSymsAddr.end(), Index); +              if (TAI != TextMappingSymsAddr.end() && *TAI == Index) +                break; +            } +          } +        } + +        if (Index >= End) +          break; +          if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),                                     SectionAddr + Index, DebugOut,                                     CommentStream)) { @@ -940,26 +1067,55 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {                          SectionAddr + Index, outs(), "", *STI);            outs() << CommentStream.str();            Comments.clear(); + +          // Try to resolve the target of a call, tail call, etc. to a specific +          // symbol.            if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) ||                        MIA->isConditionalBranch(Inst))) {              uint64_t Target;              if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) { -              auto TargetSym = std::upper_bound( -                  AllSymbols.begin(), AllSymbols.end(), Target, -                  [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) { -                    return LHS < RHS.first; -                  }); -              if (TargetSym != AllSymbols.begin()) -                --TargetSym; -              else -                TargetSym = AllSymbols.end(); - -              if (TargetSym != AllSymbols.end()) { -                outs() << " <" << TargetSym->second; -                uint64_t Disp = Target - TargetSym->first; -                if (Disp) -                  outs() << '+' << utohexstr(Disp); -                outs() << '>'; +              // In a relocatable object, the target's section must reside in +              // the same section as the call instruction or it is accessed +              // through a relocation. +              // +              // In a non-relocatable object, the target may be in any section. +              // +              // N.B. We don't walk the relocations in the relocatable case yet. +              auto *TargetSectionSymbols = &Symbols; +              if (!Obj->isRelocatableObject()) { +                auto SectionAddress = std::upper_bound( +                    SectionAddresses.begin(), SectionAddresses.end(), Target, +                    [](uint64_t LHS, +                       const std::pair<uint64_t, SectionRef> &RHS) { +                      return LHS < RHS.first; +                    }); +                if (SectionAddress != SectionAddresses.begin()) { +                  --SectionAddress; +                  TargetSectionSymbols = &AllSymbols[SectionAddress->second]; +                } else { +                  TargetSectionSymbols = nullptr; +                } +              } + +              // Find the first symbol in the section whose offset is less than +              // or equal to the target. +              if (TargetSectionSymbols) { +                auto TargetSym = std::upper_bound( +                    TargetSectionSymbols->begin(), TargetSectionSymbols->end(), +                    Target, [](uint64_t LHS, +                               const std::pair<uint64_t, StringRef> &RHS) { +                      return LHS < RHS.first; +                    }); +                if (TargetSym != TargetSectionSymbols->begin()) { +                  --TargetSym; +                  uint64_t TargetAddress = std::get<0>(*TargetSym); +                  StringRef TargetName = std::get<1>(*TargetSym); +                  outs() << " <" << TargetName; +                  uint64_t Disp = Target - TargetAddress; +                  if (Disp) +                    outs() << '+' << utohexstr(Disp); +                  outs() << '>'; +                }                }              }            } @@ -983,8 +1139,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {            // Stop when rel_cur's address is past the current instruction.            if (addr >= Index + Size) break;            rel_cur->getTypeName(name); -          if (error(getRelocationValueString(*rel_cur, val))) -            goto skip_print_rel; +          error(getRelocationValueString(*rel_cur, val));            outs() << format(Fmt.data(), SectionAddr + addr) << name                   << "\t" << val << "\n"; @@ -1004,12 +1159,11 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {    if (!Obj->isRelocatableObject())      return; -  for (const SectionRef &Section : Obj->sections()) { +  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      if (Section.relocation_begin() == Section.relocation_end())        continue;      StringRef secname; -    if (error(Section.getName(secname))) -      continue; +    error(Section.getName(secname));      outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n";      for (const RelocationRef &Reloc : Section.relocations()) {        bool hidden = getHidden(Reloc); @@ -1019,8 +1173,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {        if (hidden)          continue;        Reloc.getTypeName(relocname); -      if (error(getRelocationValueString(Reloc, valuestr))) -        continue; +      error(getRelocationValueString(Reloc, valuestr));        outs() << format(Fmt.data(), address) << " " << relocname << " "               << valuestr << "\n";      } @@ -1032,10 +1185,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {    outs() << "Sections:\n"              "Idx Name          Size      Address          Type\n";    unsigned i = 0; -  for (const SectionRef &Section : Obj->sections()) { +  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      StringRef Name; -    if (error(Section.getName(Name))) -      return; +    error(Section.getName(Name));      uint64_t Address = Section.getAddress();      uint64_t Size = Section.getSize();      bool Text = Section.isText(); @@ -1051,11 +1203,10 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {  void llvm::PrintSectionContents(const ObjectFile *Obj) {    std::error_code EC; -  for (const SectionRef &Section : Obj->sections()) { +  for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      StringRef Name;      StringRef Contents; -    if (error(Section.getName(Name))) -      continue; +    error(Section.getName(Name));      uint64_t BaseAddr = Section.getAddress();      uint64_t Size = Section.getSize();      if (!Size) @@ -1069,8 +1220,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {        continue;      } -    if (error(Section.getContents(Contents))) -      continue; +    error(Section.getContents(Contents));      // Dump out the content as hex and printable ascii characters.      for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) { @@ -1098,84 +1248,28 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {    }  } -static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { -  for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) { -    ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI); -    StringRef Name; -    if (error(Symbol.getError())) -      return; - -    if (error(coff->getSymbolName(*Symbol, Name))) -      return; - -    outs() << "[" << format("%2d", SI) << "]" -           << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")" -           << "(fl 0x00)" // Flag bits, which COFF doesn't have. -           << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")" -           << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") " -           << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") " -           << "0x" << format("%08x", unsigned(Symbol->getValue())) << " " -           << Name << "\n"; - -    for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) { -      if (Symbol->isSectionDefinition()) { -        const coff_aux_section_definition *asd; -        if (error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd))) -          return; - -        int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); - -        outs() << "AUX " -               << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " -                         , unsigned(asd->Length) -                         , unsigned(asd->NumberOfRelocations) -                         , unsigned(asd->NumberOfLinenumbers) -                         , unsigned(asd->CheckSum)) -               << format("assoc %d comdat %d\n" -                         , unsigned(AuxNumber) -                         , unsigned(asd->Selection)); -      } else if (Symbol->isFileRecord()) { -        const char *FileName; -        if (error(coff->getAuxSymbol<char>(SI + 1, FileName))) -          return; - -        StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() * -                                     coff->getSymbolTableEntrySize()); -        outs() << "AUX " << Name.rtrim(StringRef("\0", 1))  << '\n'; - -        SI = SI + Symbol->getNumberOfAuxSymbols(); -        break; -      } else { -        outs() << "AUX Unknown\n"; -      } -    } -  } -} -  void llvm::PrintSymbolTable(const ObjectFile *o) {    outs() << "SYMBOL TABLE:\n";    if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) { -    PrintCOFFSymbolTable(coff); +    printCOFFSymbolTable(coff);      return;    }    for (const SymbolRef &Symbol : o->symbols()) {      ErrorOr<uint64_t> AddressOrError = Symbol.getAddress(); -    if (error(AddressOrError.getError())) -      continue; +    error(AddressOrError.getError());      uint64_t Address = *AddressOrError;      SymbolRef::Type Type = Symbol.getType();      uint32_t Flags = Symbol.getFlags(); -    section_iterator Section = o->section_end(); -    if (error(Symbol.getSection(Section))) -      continue; +    ErrorOr<section_iterator> SectionOrErr = Symbol.getSection(); +    error(SectionOrErr.getError()); +    section_iterator Section = *SectionOrErr;      StringRef Name;      if (Type == SymbolRef::ST_Debug && Section != o->section_end()) {        Section->getName(Name);      } else {        ErrorOr<StringRef> NameOrErr = Symbol.getName(); -      if (error(NameOrErr.getError())) -        continue; +      error(NameOrErr.getError());        Name = *NameOrErr;      } @@ -1222,8 +1316,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {          outs() << SegmentName << ",";        }        StringRef SectionName; -      if (error(Section->getName(SectionName))) -        SectionName = ""; +      error(Section->getName(SectionName));        outs() << SectionName;      } @@ -1329,7 +1422,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {    }    Optional<object::SectionRef> ClangASTSection; -  for (auto Sec : Obj->sections()) { +  for (auto Sec : ToolSectionFilter(*Obj)) {      StringRef Name;      Sec.getName(Name);      if (Name == ClangASTSectionName) { @@ -1341,11 +1434,7 @@ void llvm::printRawClangAST(const ObjectFile *Obj) {      return;    StringRef ClangASTContents; -  if (error(ClangASTSection.getValue().getContents(ClangASTContents))) { -    errs() << "Could not read the " << ClangASTSectionName << " section!\n"; -    return; -  } - +  error(ClangASTSection.getValue().getContents(ClangASTContents));    outs().write(ClangASTContents.data(), ClangASTContents.size());  } @@ -1364,7 +1453,7 @@ static void printFaultMaps(const ObjectFile *Obj) {    Optional<object::SectionRef> FaultMapSection; -  for (auto Sec : Obj->sections()) { +  for (auto Sec : ToolSectionFilter(*Obj)) {      StringRef Name;      Sec.getName(Name);      if (Name == FaultMapSectionName) { @@ -1381,10 +1470,7 @@ static void printFaultMaps(const ObjectFile *Obj) {    }    StringRef FaultMapContents; -  if (error(FaultMapSection.getValue().getContents(FaultMapContents))) { -    errs() << "Could not read the " << FaultMapContents << " section!\n"; -    return; -  } +  error(FaultMapSection.getValue().getContents(FaultMapContents));    FaultMapParser FMP(FaultMapContents.bytes_begin(),                       FaultMapContents.bytes_end()); @@ -1393,13 +1479,14 @@ static void printFaultMaps(const ObjectFile *Obj) {  }  static void printPrivateFileHeader(const ObjectFile *o) { -  if (o->isELF()) { +  if (o->isELF())      printELFFileHeader(o); -  } else if (o->isCOFF()) { +  else if (o->isCOFF())      printCOFFFileHeader(o); -  } else if (o->isMachO()) { +  else if (o->isMachO())      printMachOFileHeader(o); -  } +  else +    report_fatal_error("Invalid/Unsupported object file format");  }  static void DumpObject(const ObjectFile *o) { @@ -1442,15 +1529,14 @@ static void DumpObject(const ObjectFile *o) {  /// @brief Dump each object file in \a a;  static void DumpArchive(const Archive *a) { -  for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e; -       ++i) { -    ErrorOr<std::unique_ptr<Binary>> ChildOrErr = i->getAsBinary(); -    if (std::error_code EC = ChildOrErr.getError()) { -      // Ignore non-object files. +  for (auto &ErrorOrChild : a->children()) { +    if (std::error_code EC = ErrorOrChild.getError()) +      report_error(a->getFileName(), EC); +    const Archive::Child &C = *ErrorOrChild; +    ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); +    if (std::error_code EC = ChildOrErr.getError())        if (EC != object_error::invalid_file_type)          report_error(a->getFileName(), EC); -      continue; -    }      if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get()))        DumpObject(o);      else @@ -1460,11 +1546,6 @@ static void DumpArchive(const Archive *a) {  /// @brief Open file and figure out how to dump it.  static void DumpInput(StringRef file) { -  // If file isn't stdin, check that it exists. -  if (file != "-" && !sys::fs::exists(file)) { -    report_error(file, errc::no_such_file_or_directory); -    return; -  }    // If we are using the Mach-O specific object file parser, then let it parse    // the file and process the command line options.  So the -arch flags can @@ -1476,10 +1557,8 @@ static void DumpInput(StringRef file) {    // Attempt to open the binary.    ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file); -  if (std::error_code EC = BinaryOrErr.getError()) { +  if (std::error_code EC = BinaryOrErr.getError())      report_error(file, EC); -    return; -  }    Binary &Binary = *BinaryOrErr.get().getBinary();    if (Archive *a = dyn_cast<Archive>(&Binary)) @@ -1499,7 +1578,6 @@ int main(int argc, char **argv) {    // Initialize targets and assembly printers/parsers.    llvm::InitializeAllTargetInfos();    llvm::InitializeAllTargetMCs(); -  llvm::InitializeAllAsmParsers();    llvm::InitializeAllDisassemblers();    // Register the target printer for --version. @@ -1514,6 +1592,8 @@ int main(int argc, char **argv) {    if (InputFilenames.size() == 0)      InputFilenames.push_back("a.out"); +  if (DisassembleAll) +    Disassemble = true;    if (!Disassemble        && !Relocations        && !SectionHeaders @@ -1536,7 +1616,7 @@ int main(int argc, char **argv) {        && !(DylibsUsed && MachOOpt)        && !(DylibId && MachOOpt)        && !(ObjcMetaData && MachOOpt) -      && !(DumpSections.size() != 0 && MachOOpt) +      && !(FilterSections.size() != 0 && MachOOpt)        && !PrintFaultMaps) {      cl::PrintHelpMessage();      return 2; @@ -1545,5 +1625,5 @@ int main(int argc, char **argv) {    std::for_each(InputFilenames.begin(), InputFilenames.end(),                  DumpInput); -  return ReturnValue; +  return EXIT_SUCCESS;  }  | 
