diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump')
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/COFFDump.cpp | 4 | ||||
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/ELFDump.cpp | 91 | ||||
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/MachODump.cpp | 407 | ||||
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/WasmDump.cpp | 2 | ||||
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp | 1073 | ||||
| -rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.h | 7 | 
6 files changed, 974 insertions, 610 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp index 780d1e9e6111..7ca5d04593ff 100644 --- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp @@ -8,7 +8,7 @@  //===----------------------------------------------------------------------===//  ///  /// \file -/// \brief This file implements the COFF-specific dumper for llvm-objdump. +/// This file implements the COFF-specific dumper for llvm-objdump.  /// It outputs the Win64 EH data structures as plain text.  /// The encoding of the unwind codes is described in MSDN:  /// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx @@ -453,7 +453,7 @@ static bool getPDataSection(const COFFObjectFile *Obj,        Rels.push_back(Reloc);      // Sort relocations by address. -    std::sort(Rels.begin(), Rels.end(), RelocAddressLess); +    llvm::sort(Rels.begin(), Rels.end(), RelocAddressLess);      ArrayRef<uint8_t> Contents;      error(Obj->getSectionContents(Pdata, Contents)); diff --git a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp index 7f5fe5a9d3b8..f4d36656a6c4 100644 --- a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp @@ -8,7 +8,7 @@  //===----------------------------------------------------------------------===//  ///  /// \file -/// \brief This file implements the ELF-specific dumper for llvm-objdump. +/// This file implements the ELF-specific dumper for llvm-objdump.  ///  //===----------------------------------------------------------------------===// @@ -21,6 +21,77 @@  using namespace llvm;  using namespace llvm::object; +template <class ELFT> +Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) { +  typedef ELFFile<ELFT> ELFO; + +  auto DynamicEntriesOrError = Elf->dynamicEntries(); +  if (!DynamicEntriesOrError) +    return DynamicEntriesOrError.takeError(); + +  for (const typename ELFO::Elf_Dyn &Dyn : *DynamicEntriesOrError) { +    if (Dyn.d_tag == ELF::DT_STRTAB) { +      auto MappedAddrOrError = Elf->toMappedAddr(Dyn.getPtr()); +      if (!MappedAddrOrError) +        consumeError(MappedAddrOrError.takeError()); +      return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError)); +    } +  } + +  // If the dynamic segment is not present, we fall back on the sections. +  auto SectionsOrError = Elf->sections(); +  if (!SectionsOrError) +    return SectionsOrError.takeError(); + +  for (const typename ELFO::Elf_Shdr &Sec : *SectionsOrError) { +    if (Sec.sh_type == ELF::SHT_DYNSYM) +      return Elf->getStringTableForSymtab(Sec); +  } + +  return createError("dynamic string table not found"); +} + +template <class ELFT> +void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { +  auto ProgramHeaderOrError = Elf->program_headers(); +  if (!ProgramHeaderOrError) +    report_error(Filename, ProgramHeaderOrError.takeError()); + +  auto DynamicEntriesOrError = Elf->dynamicEntries(); +  if (!DynamicEntriesOrError) +    report_error(Filename, DynamicEntriesOrError.takeError()); + +  outs() << "Dynamic Section:\n"; +  for (const auto &Dyn : *DynamicEntriesOrError) { +    if (Dyn.d_tag == ELF::DT_NULL) +      continue; + +    StringRef Str = StringRef(Elf->getDynamicTagAsString(Dyn.d_tag)); + +    if (Str.empty()) { +      std::string HexStr = utohexstr(static_cast<uint64_t>(Dyn.d_tag), true); +      outs() << format("  0x%-19s", HexStr.c_str()); +    } else { +      // We use "-21" in order to match GNU objdump's output. +      outs() << format("  %-21s", Str.data()); +    } + +    const char *Fmt = +        ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; +    if (Dyn.d_tag == ELF::DT_NEEDED) { +      Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); +      if (StrTabOrErr) { +        const char *Data = StrTabOrErr.get().data(); +        outs() << (Data + Dyn.d_un.d_val) << "\n"; +        continue; +      } +      warn(errorToErrorCode(StrTabOrErr.takeError()).message()); +      consumeError(StrTabOrErr.takeError()); +    } +    outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); +  } +} +  template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) {    typedef ELFFile<ELFT> ELFO;    outs() << "Program Header:\n"; @@ -103,3 +174,21 @@ void llvm::printELFFileHeader(const object::ObjectFile *Obj) {    if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))      printProgramHeaders(ELFObj->getELFFile());  } + +void llvm::printELFDynamicSection(const object::ObjectFile *Obj) { +  // Little-endian 32-bit +  if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) +    printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + +  // Big-endian 32-bit +  if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) +    printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + +  // Little-endian 64-bit +  if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) +    printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); + +  // Big-endian 64-bit +  if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) +    printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); +} diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp index 9908c2f2d016..bdf80c73b999 100644 --- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp +++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp @@ -76,11 +76,6 @@ cl::opt<bool> llvm::UniversalHeaders("universal-headers",                                                "(requires -macho)"));  cl::opt<bool> -    llvm::ArchiveHeaders("archive-headers", -                         cl::desc("Print archive headers for Mach-O archives " -                                  "(requires -macho)")); - -cl::opt<bool>      ArchiveMemberOffsets("archive-member-offsets",                           cl::desc("Print the offset to each archive member for "                                    "Mach-O archives (requires -macho and " @@ -1284,14 +1279,35 @@ static void DumpLiteralPointerSection(MachOObjectFile *O,    }  } -static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, +static void DumpInitTermPointerSection(MachOObjectFile *O, +                                       const SectionRef &Section, +                                       const char *sect,                                         uint32_t sect_size, uint64_t sect_addr,                                         SymbolAddressMap *AddrMap,                                         bool verbose) {    uint32_t stride;    stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t); + +  // Collect the external relocation symbols for the pointers. +  std::vector<std::pair<uint64_t, SymbolRef>> Relocs; +  for (const RelocationRef &Reloc : Section.relocations()) { +    DataRefImpl Rel; +    MachO::any_relocation_info RE; +    bool isExtern = false; +    Rel = Reloc.getRawDataRefImpl(); +    RE = O->getRelocation(Rel); +    isExtern = O->getPlainRelocationExternal(RE); +    if (isExtern) { +      uint64_t RelocOffset = Reloc.getOffset(); +      symbol_iterator RelocSym = Reloc.getSymbol(); +      Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); +    } +  } +  array_pod_sort(Relocs.begin(), Relocs.end()); +    for (uint32_t i = 0; i < sect_size; i += stride) {      const char *SymbolName = nullptr; +    uint64_t p;      if (O->is64Bit()) {        outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";        uint64_t pointer_value; @@ -1299,8 +1315,7 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,        if (O->isLittleEndian() != sys::IsLittleEndianHost)          sys::swapByteOrder(pointer_value);        outs() << format("0x%016" PRIx64, pointer_value); -      if (verbose) -        SymbolName = GuessSymbolName(pointer_value, AddrMap); +      p = pointer_value;      } else {        outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";        uint32_t pointer_value; @@ -1308,11 +1323,25 @@ static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,        if (O->isLittleEndian() != sys::IsLittleEndianHost)          sys::swapByteOrder(pointer_value);        outs() << format("0x%08" PRIx32, pointer_value); -      if (verbose) -        SymbolName = GuessSymbolName(pointer_value, AddrMap); +      p = pointer_value; +    } +    if (verbose) { +      // First look for an external relocation entry for this pointer. +      auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) { +        return P.first == i; +      }); +      if (Reloc != Relocs.end()) { +        symbol_iterator RelocSym = Reloc->second; +        Expected<StringRef> SymName = RelocSym->getName(); +        if (!SymName) +          report_error(O->getFileName(), SymName.takeError()); +        outs() << " " << *SymName; +      } else { +        SymbolName = GuessSymbolName(p, AddrMap); +        if (SymbolName) +          outs() << " " << SymbolName; +      }      } -    if (SymbolName) -      outs() << " " << SymbolName;      outs() << "\n";    }  } @@ -1463,8 +1492,8 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,              break;            case MachO::S_MOD_INIT_FUNC_POINTERS:            case MachO::S_MOD_TERM_FUNC_POINTERS: -            DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap, -                                       verbose); +            DumpInitTermPointerSection(O, Section, sect, sect_size, sect_addr, +                                       &AddrMap, verbose);              break;            default:              outs() << "Unknown section type (" @@ -2149,19 +2178,22 @@ void llvm::ParseInputMachO(StringRef Filename) {  // The block of info used by the Symbolizer call backs.  struct DisassembleInfo { +  DisassembleInfo(MachOObjectFile *O, SymbolAddressMap *AddrMap, +                  std::vector<SectionRef> *Sections, bool verbose) +    : verbose(verbose), O(O), AddrMap(AddrMap), Sections(Sections) {}    bool verbose;    MachOObjectFile *O;    SectionRef S;    SymbolAddressMap *AddrMap;    std::vector<SectionRef> *Sections; -  const char *class_name; -  const char *selector_name; -  char *method; -  char *demangled_name; -  uint64_t adrp_addr; -  uint32_t adrp_inst; +  const char *class_name = nullptr; +  const char *selector_name = nullptr; +  std::unique_ptr<char[]> method = nullptr; +  char *demangled_name = nullptr; +  uint64_t adrp_addr = 0; +  uint32_t adrp_inst = 0;    std::unique_ptr<SymbolAddressMap> bindtable; -  uint32_t depth; +  uint32_t depth = 0;  };  // SymbolizerGetOpInfo() is the operand information call back function. @@ -2756,32 +2788,33 @@ static void method_reference(struct DisassembleInfo *info,    if (*ReferenceName != nullptr) {      if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {        if (info->selector_name != nullptr) { -        if (info->method != nullptr) -          free(info->method);          if (info->class_name != nullptr) { -          info->method = (char *)malloc(5 + strlen(info->class_name) + -                                        strlen(info->selector_name)); -          if (info->method != nullptr) { -            strcpy(info->method, "+["); -            strcat(info->method, info->class_name); -            strcat(info->method, " "); -            strcat(info->method, info->selector_name); -            strcat(info->method, "]"); -            *ReferenceName = info->method; +          info->method = llvm::make_unique<char[]>( +              5 + strlen(info->class_name) + strlen(info->selector_name)); +          char *method = info->method.get(); +          if (method != nullptr) { +            strcpy(method, "+["); +            strcat(method, info->class_name); +            strcat(method, " "); +            strcat(method, info->selector_name); +            strcat(method, "]"); +            *ReferenceName = method;              *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;            }          } else { -          info->method = (char *)malloc(9 + strlen(info->selector_name)); -          if (info->method != nullptr) { +          info->method = +              llvm::make_unique<char[]>(9 + strlen(info->selector_name)); +          char *method = info->method.get(); +          if (method != nullptr) {              if (Arch == Triple::x86_64) -              strcpy(info->method, "-[%rdi "); +              strcpy(method, "-[%rdi ");              else if (Arch == Triple::aarch64) -              strcpy(info->method, "-[x0 "); +              strcpy(method, "-[x0 ");              else -              strcpy(info->method, "-[r? "); -            strcat(info->method, info->selector_name); -            strcat(info->method, "]"); -            *ReferenceName = info->method; +              strcpy(method, "-[r? "); +            strcat(method, info->selector_name); +            strcat(method, "]"); +            *ReferenceName = method;              *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;            }          } @@ -2789,19 +2822,19 @@ static void method_reference(struct DisassembleInfo *info,        }      } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {        if (info->selector_name != nullptr) { -        if (info->method != nullptr) -          free(info->method); -        info->method = (char *)malloc(17 + strlen(info->selector_name)); -        if (info->method != nullptr) { +        info->method = +            llvm::make_unique<char[]>(17 + strlen(info->selector_name)); +        char *method = info->method.get(); +        if (method != nullptr) {            if (Arch == Triple::x86_64) -            strcpy(info->method, "-[[%rdi super] "); +            strcpy(method, "-[[%rdi super] ");            else if (Arch == Triple::aarch64) -            strcpy(info->method, "-[[x0 super] "); +            strcpy(method, "-[[x0 super] ");            else -            strcpy(info->method, "-[[r? super] "); -          strcat(info->method, info->selector_name); -          strcat(info->method, "]"); -          *ReferenceName = info->method; +            strcpy(method, "-[[r? super] "); +          strcat(method, info->selector_name); +          strcat(method, "]"); +          *ReferenceName = method;            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;          }          info->class_name = nullptr; @@ -3196,6 +3229,8 @@ struct imageInfo_t {  /* masks for objc_image_info.flags */  #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)  #define OBJC_IMAGE_SUPPORTS_GC (1 << 1) +#define OBJC_IMAGE_IS_SIMULATED (1 << 5) +#define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES (1 << 6)  struct message_ref64 {    uint64_t imp; /* IMP (64-bit pointer) */ @@ -5557,12 +5592,24 @@ static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {      outs() << " OBJC_IMAGE_IS_REPLACEMENT";    if (o.flags & OBJC_IMAGE_SUPPORTS_GC)      outs() << " OBJC_IMAGE_SUPPORTS_GC"; +  if (o.flags & OBJC_IMAGE_IS_SIMULATED) +    outs() << " OBJC_IMAGE_IS_SIMULATED"; +  if (o.flags & OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES) +    outs() << " OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES";    swift_version = (o.flags >> 8) & 0xff;    if (swift_version != 0) {      if (swift_version == 1)        outs() << " Swift 1.0";      else if (swift_version == 2)        outs() << " Swift 1.1"; +    else if(swift_version == 3) +      outs() << " Swift 2.0"; +    else if(swift_version == 4) +      outs() << " Swift 3.0"; +    else if(swift_version == 5) +      outs() << " Swift 4.0"; +    else if(swift_version == 6) +      outs() << " Swift 4.1";      else        outs() << " unknown future Swift version (" << swift_version << ")";    } @@ -5606,6 +5653,14 @@ static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {        outs() << " Swift 1.0";      else if (swift_version == 2)        outs() << " Swift 1.1"; +    else if(swift_version == 3) +      outs() << " Swift 2.0"; +    else if(swift_version == 4) +      outs() << " Swift 3.0"; +    else if(swift_version == 5) +      outs() << " Swift 4.0"; +    else if(swift_version == 6) +      outs() << " Swift 4.1";      else        outs() << " unknown future Swift version (" << swift_version << ")";    } @@ -5659,21 +5714,8 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {      Sections.push_back(Section);    } -  struct DisassembleInfo info; -  // Set up the block of info used by the Symbolizer call backs. -  info.verbose = verbose; -  info.O = O; -  info.AddrMap = &AddrMap; -  info.Sections = &Sections; -  info.class_name = nullptr; -  info.selector_name = nullptr; -  info.method = nullptr; -  info.demangled_name = nullptr; -  info.bindtable = nullptr; -  info.adrp_addr = 0; -  info.adrp_inst = 0; - -  info.depth = 0; +  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose); +    SectionRef CL = get_section(O, "__OBJC2", "__class_list");    if (CL == SectionRef())      CL = get_section(O, "__DATA", "__objc_classlist"); @@ -5757,19 +5799,7 @@ static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {      Sections.push_back(Section);    } -  struct DisassembleInfo info; -  // Set up the block of info used by the Symbolizer call backs. -  info.verbose = verbose; -  info.O = O; -  info.AddrMap = &AddrMap; -  info.Sections = &Sections; -  info.class_name = nullptr; -  info.selector_name = nullptr; -  info.method = nullptr; -  info.demangled_name = nullptr; -  info.bindtable = nullptr; -  info.adrp_addr = 0; -  info.adrp_inst = 0; +  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);    SectionRef CL = get_section(O, "__OBJC2", "__class_list");    if (CL == SectionRef()) @@ -5867,19 +5897,7 @@ static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {      Sections.push_back(Section);    } -  struct DisassembleInfo info; -  // Set up the block of info used by the Symbolizer call backs. -  info.verbose = verbose; -  info.O = O; -  info.AddrMap = &AddrMap; -  info.Sections = &Sections; -  info.class_name = nullptr; -  info.selector_name = nullptr; -  info.method = nullptr; -  info.demangled_name = nullptr; -  info.bindtable = nullptr; -  info.adrp_addr = 0; -  info.adrp_inst = 0; +  struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);    for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {      p = S.getAddress() + i; @@ -6040,19 +6058,7 @@ static void DumpProtocolSection(MachOObjectFile *O, const char *sect,      Sections.push_back(Section);    } -  struct DisassembleInfo info; -  // Set up the block of info used by the Symbolizer call backs. -  info.verbose = true; -  info.O = O; -  info.AddrMap = &AddrMap; -  info.Sections = &Sections; -  info.class_name = nullptr; -  info.selector_name = nullptr; -  info.method = nullptr; -  info.demangled_name = nullptr; -  info.bindtable = nullptr; -  info.adrp_addr = 0; -  info.adrp_inst = 0; +  struct DisassembleInfo info(O, &AddrMap, &Sections, true);    const char *p;    struct objc_protocol_t protocol; @@ -6748,7 +6754,7 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo,    return SymbolName;  } -/// \brief Emits the comments that are stored in the CommentStream. +/// Emits the comments that are stored in the CommentStream.  /// Each comment in the CommentStream must end with a newline.  static void emitComments(raw_svector_ostream &CommentStream,                           SmallString<128> &CommentsToEmit, @@ -6817,7 +6823,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,    std::unique_ptr<MCDisassembler> DisAsm(        TheTarget->createMCDisassembler(*STI, Ctx));    std::unique_ptr<MCSymbolizer> Symbolizer; -  struct DisassembleInfo SymbolizerInfo; +  struct DisassembleInfo SymbolizerInfo(nullptr, nullptr, nullptr, false);    std::unique_ptr<MCRelocationInfo> RelInfo(        TheTarget->createMCRelocationInfo(TripleName, Ctx));    if (RelInfo) { @@ -6855,7 +6861,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,    std::unique_ptr<MCInstPrinter> ThumbIP;    std::unique_ptr<MCContext> ThumbCtx;    std::unique_ptr<MCSymbolizer> ThumbSymbolizer; -  struct DisassembleInfo ThumbSymbolizerInfo; +  struct DisassembleInfo ThumbSymbolizerInfo(nullptr, nullptr, nullptr, false);    std::unique_ptr<MCRelocationInfo> ThumbRelInfo;    if (ThumbTarget) {      ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); @@ -6904,7 +6910,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,                          BaseSegmentAddress);    // Sort the symbols by address, just in case they didn't come in that way. -  std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); +  llvm::sort(Symbols.begin(), Symbols.end(), SymbolSorter());    // Build a data in code table that is sorted on by the address of each entry.    uint64_t BaseAddress = 0; @@ -6940,10 +6946,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,          errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';          return;        } -      DbgObj = -          ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()) -              .get() -              .release(); +      Expected<std::unique_ptr<MachOObjectFile>> DbgObjCheck = +          ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef()); + +      if (DbgObjCheck.takeError()) +        report_error(MachOOF->getFileName(), DbgObjCheck.takeError()); +      DbgObj = DbgObjCheck.get().release();      }      // Setup the DIContext @@ -7003,26 +7011,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,      SymbolizerInfo.S = Sections[SectIdx];      SymbolizerInfo.AddrMap = &AddrMap;      SymbolizerInfo.Sections = &Sections; -    SymbolizerInfo.class_name = nullptr; -    SymbolizerInfo.selector_name = nullptr; -    SymbolizerInfo.method = nullptr; -    SymbolizerInfo.demangled_name = nullptr; -    SymbolizerInfo.bindtable = nullptr; -    SymbolizerInfo.adrp_addr = 0; -    SymbolizerInfo.adrp_inst = 0;      // Same for the ThumbSymbolizer      ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;      ThumbSymbolizerInfo.O = MachOOF;      ThumbSymbolizerInfo.S = Sections[SectIdx];      ThumbSymbolizerInfo.AddrMap = &AddrMap;      ThumbSymbolizerInfo.Sections = &Sections; -    ThumbSymbolizerInfo.class_name = nullptr; -    ThumbSymbolizerInfo.selector_name = nullptr; -    ThumbSymbolizerInfo.method = nullptr; -    ThumbSymbolizerInfo.demangled_name = nullptr; -    ThumbSymbolizerInfo.bindtable = nullptr; -    ThumbSymbolizerInfo.adrp_addr = 0; -    ThumbSymbolizerInfo.adrp_inst = 0;      unsigned int Arch = MachOOF->getArch(); @@ -7293,12 +7287,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,      TripleName = "";      ThumbTripleName = ""; -    if (SymbolizerInfo.method != nullptr) -      free(SymbolizerInfo.method);      if (SymbolizerInfo.demangled_name != nullptr)        free(SymbolizerInfo.demangled_name); -    if (ThumbSymbolizerInfo.method != nullptr) -      free(ThumbSymbolizerInfo.method);      if (ThumbSymbolizerInfo.demangled_name != nullptr)        free(ThumbSymbolizerInfo.demangled_name);    } @@ -7310,12 +7300,25 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,  namespace { -template <typename T> static uint64_t readNext(const char *&Buf) { +template <typename T> +static uint64_t read(StringRef Contents, ptrdiff_t Offset) {    using llvm::support::little;    using llvm::support::unaligned; -  uint64_t Val = support::endian::read<T, little, unaligned>(Buf); -  Buf += sizeof(T); +  if (Offset + sizeof(T) > Contents.size()) { +    outs() << "warning: attempt to read past end of buffer\n"; +    return T(); +  } + +  uint64_t Val = +      support::endian::read<T, little, unaligned>(Contents.data() + Offset); +  return Val; +} + +template <typename T> +static uint64_t readNext(StringRef Contents, ptrdiff_t &Offset) { +  T Val = read<T>(Contents, Offset); +  Offset += sizeof(T);    return Val;  } @@ -7335,18 +7338,18 @@ struct CompactUnwindEntry {    CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)        : OffsetInSection(Offset) {      if (Is64) -      read<uint64_t>(Contents.data() + Offset); +      read<uint64_t>(Contents, Offset);      else -      read<uint32_t>(Contents.data() + Offset); +      read<uint32_t>(Contents, Offset);    }  private: -  template <typename UIntPtr> void read(const char *Buf) { -    FunctionAddr = readNext<UIntPtr>(Buf); -    Length = readNext<uint32_t>(Buf); -    CompactEncoding = readNext<uint32_t>(Buf); -    PersonalityAddr = readNext<UIntPtr>(Buf); -    LSDAAddr = readNext<UIntPtr>(Buf); +  template <typename UIntPtr> void read(StringRef Contents, ptrdiff_t Offset) { +    FunctionAddr = readNext<UIntPtr>(Contents, Offset); +    Length = readNext<uint32_t>(Contents, Offset); +    CompactEncoding = readNext<uint32_t>(Contents, Offset); +    PersonalityAddr = readNext<UIntPtr>(Contents, Offset); +    LSDAAddr = readNext<UIntPtr>(Contents, Offset);    }  };  } @@ -7448,7 +7451,7 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,    // First populate the initial raw offsets, encodings and so on from the entry.    for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) { -    CompactUnwindEntry Entry(Contents.data(), Offset, Is64); +    CompactUnwindEntry Entry(Contents, Offset, Is64);      CompactUnwinds.push_back(Entry);    } @@ -7515,19 +7518,19 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj,  // __unwind_info section dumping  //===----------------------------------------------------------------------===// -static void printRegularSecondLevelUnwindPage(const char *PageStart) { -  const char *Pos = PageStart; -  uint32_t Kind = readNext<uint32_t>(Pos); +static void printRegularSecondLevelUnwindPage(StringRef PageData) { +  ptrdiff_t Pos = 0; +  uint32_t Kind = readNext<uint32_t>(PageData, Pos);    (void)Kind;    assert(Kind == 2 && "kind for a regular 2nd level index should be 2"); -  uint16_t EntriesStart = readNext<uint16_t>(Pos); -  uint16_t NumEntries = readNext<uint16_t>(Pos); +  uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); +  uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); -  Pos = PageStart + EntriesStart; +  Pos = EntriesStart;    for (unsigned i = 0; i < NumEntries; ++i) { -    uint32_t FunctionOffset = readNext<uint32_t>(Pos); -    uint32_t Encoding = readNext<uint32_t>(Pos); +    uint32_t FunctionOffset = readNext<uint32_t>(PageData, Pos); +    uint32_t Encoding = readNext<uint32_t>(PageData, Pos);      outs() << "      [" << i << "]: "             << "function offset=" << format("0x%08" PRIx32, FunctionOffset) @@ -7537,24 +7540,23 @@ static void printRegularSecondLevelUnwindPage(const char *PageStart) {  }  static void printCompressedSecondLevelUnwindPage( -    const char *PageStart, uint32_t FunctionBase, +    StringRef PageData, uint32_t FunctionBase,      const SmallVectorImpl<uint32_t> &CommonEncodings) { -  const char *Pos = PageStart; -  uint32_t Kind = readNext<uint32_t>(Pos); +  ptrdiff_t Pos = 0; +  uint32_t Kind = readNext<uint32_t>(PageData, Pos);    (void)Kind;    assert(Kind == 3 && "kind for a compressed 2nd level index should be 3"); -  uint16_t EntriesStart = readNext<uint16_t>(Pos); -  uint16_t NumEntries = readNext<uint16_t>(Pos); +  uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos); +  uint16_t NumEntries = readNext<uint16_t>(PageData, Pos); -  uint16_t EncodingsStart = readNext<uint16_t>(Pos); -  readNext<uint16_t>(Pos); -  const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>( -      PageStart + EncodingsStart); +  uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos); +  readNext<uint16_t>(PageData, Pos); +  StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos); -  Pos = PageStart + EntriesStart; +  Pos = EntriesStart;    for (unsigned i = 0; i < NumEntries; ++i) { -    uint32_t Entry = readNext<uint32_t>(Pos); +    uint32_t Entry = readNext<uint32_t>(PageData, Pos);      uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);      uint32_t EncodingIdx = Entry >> 24; @@ -7562,7 +7564,9 @@ static void printCompressedSecondLevelUnwindPage(      if (EncodingIdx < CommonEncodings.size())        Encoding = CommonEncodings[EncodingIdx];      else -      Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()]; +      Encoding = read<uint32_t>(PageEncodings, +                                sizeof(uint32_t) * +                                    (EncodingIdx - CommonEncodings.size()));      outs() << "      [" << i << "]: "             << "function offset=" << format("0x%08" PRIx32, FunctionOffset) @@ -7585,13 +7589,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,    StringRef Contents;    UnwindInfo.getContents(Contents); -  const char *Pos = Contents.data(); +  ptrdiff_t Pos = 0;    //===----------------------------------    // Section header    //===---------------------------------- -  uint32_t Version = readNext<uint32_t>(Pos); +  uint32_t Version = readNext<uint32_t>(Contents, Pos);    outs() << "  Version:                                   "           << format("0x%" PRIx32, Version) << '\n';    if (Version != 1) { @@ -7599,24 +7603,24 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,      return;    } -  uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos); +  uint32_t CommonEncodingsStart = readNext<uint32_t>(Contents, Pos);    outs() << "  Common encodings array section offset:     "           << format("0x%" PRIx32, CommonEncodingsStart) << '\n'; -  uint32_t NumCommonEncodings = readNext<uint32_t>(Pos); +  uint32_t NumCommonEncodings = readNext<uint32_t>(Contents, Pos);    outs() << "  Number of common encodings in array:       "           << format("0x%" PRIx32, NumCommonEncodings) << '\n'; -  uint32_t PersonalitiesStart = readNext<uint32_t>(Pos); +  uint32_t PersonalitiesStart = readNext<uint32_t>(Contents, Pos);    outs() << "  Personality function array section offset: "           << format("0x%" PRIx32, PersonalitiesStart) << '\n'; -  uint32_t NumPersonalities = readNext<uint32_t>(Pos); +  uint32_t NumPersonalities = readNext<uint32_t>(Contents, Pos);    outs() << "  Number of personality functions in array:  "           << format("0x%" PRIx32, NumPersonalities) << '\n'; -  uint32_t IndicesStart = readNext<uint32_t>(Pos); +  uint32_t IndicesStart = readNext<uint32_t>(Contents, Pos);    outs() << "  Index array section offset:                "           << format("0x%" PRIx32, IndicesStart) << '\n'; -  uint32_t NumIndices = readNext<uint32_t>(Pos); +  uint32_t NumIndices = readNext<uint32_t>(Contents, Pos);    outs() << "  Number of indices in array:                "           << format("0x%" PRIx32, NumIndices) << '\n'; @@ -7631,9 +7635,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,    SmallVector<uint32_t, 64> CommonEncodings;    outs() << "  Common encodings: (count = " << NumCommonEncodings << ")\n"; -  Pos = Contents.data() + CommonEncodingsStart; +  Pos = CommonEncodingsStart;    for (unsigned i = 0; i < NumCommonEncodings; ++i) { -    uint32_t Encoding = readNext<uint32_t>(Pos); +    uint32_t Encoding = readNext<uint32_t>(Contents, Pos);      CommonEncodings.push_back(Encoding);      outs() << "    encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding) @@ -7648,9 +7652,9 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,    // roughly). Particularly since they only get 2 bits in the compact encoding.    outs() << "  Personality functions: (count = " << NumPersonalities << ")\n"; -  Pos = Contents.data() + PersonalitiesStart; +  Pos = PersonalitiesStart;    for (unsigned i = 0; i < NumPersonalities; ++i) { -    uint32_t PersonalityFn = readNext<uint32_t>(Pos); +    uint32_t PersonalityFn = readNext<uint32_t>(Contents, Pos);      outs() << "    personality[" << i + 1             << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';    } @@ -7671,13 +7675,13 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,    SmallVector<IndexEntry, 4> IndexEntries;    outs() << "  Top level indices: (count = " << NumIndices << ")\n"; -  Pos = Contents.data() + IndicesStart; +  Pos = IndicesStart;    for (unsigned i = 0; i < NumIndices; ++i) {      IndexEntry Entry; -    Entry.FunctionOffset = readNext<uint32_t>(Pos); -    Entry.SecondLevelPageStart = readNext<uint32_t>(Pos); -    Entry.LSDAStart = readNext<uint32_t>(Pos); +    Entry.FunctionOffset = readNext<uint32_t>(Contents, Pos); +    Entry.SecondLevelPageStart = readNext<uint32_t>(Contents, Pos); +    Entry.LSDAStart = readNext<uint32_t>(Contents, Pos);      IndexEntries.push_back(Entry);      outs() << "    [" << i << "]: " @@ -7696,12 +7700,14 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,    // the first top-level index's LSDAOffset to the last (sentinel).    outs() << "  LSDA descriptors:\n"; -  Pos = Contents.data() + IndexEntries[0].LSDAStart; -  int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / -                 (2 * sizeof(uint32_t)); +  Pos = IndexEntries[0].LSDAStart; +  const uint32_t LSDASize = 2 * sizeof(uint32_t); +  int NumLSDAs = +      (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) / LSDASize; +    for (int i = 0; i < NumLSDAs; ++i) { -    uint32_t FunctionOffset = readNext<uint32_t>(Pos); -    uint32_t LSDAOffset = readNext<uint32_t>(Pos); +    uint32_t FunctionOffset = readNext<uint32_t>(Contents, Pos); +    uint32_t LSDAOffset = readNext<uint32_t>(Contents, Pos);      outs() << "    [" << i << "]: "             << "function offset=" << format("0x%08" PRIx32, FunctionOffset)             << ", " @@ -7729,12 +7735,19 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,             << "base function offset="             << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n'; -    Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart; -    uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos); +    Pos = IndexEntries[i].SecondLevelPageStart; +    if (Pos + sizeof(uint32_t) > Contents.size()) { +      outs() << "warning: invalid offset for second level page: " << Pos << '\n'; +      continue; +    } + +    uint32_t Kind = +        *reinterpret_cast<const support::ulittle32_t *>(Contents.data() + Pos);      if (Kind == 2) -      printRegularSecondLevelUnwindPage(Pos); +      printRegularSecondLevelUnwindPage(Contents.substr(Pos, 4096));      else if (Kind == 3) -      printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset, +      printCompressedSecondLevelUnwindPage(Contents.substr(Pos, 4096), +                                           IndexEntries[i].FunctionOffset,                                             CommonEncodings);      else        outs() << "    Skipping 2nd level page with unknown kind " << Kind @@ -9352,6 +9365,26 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,            outs() << "\t    esh.flavor " << es.esh.flavor << "  esh.count "                   << es.esh.count << "\n";          } +      } else if (flavor == MachO::x86_EXCEPTION_STATE64) { +        outs() << "     flavor x86_EXCEPTION_STATE64\n"; +        if (count == MachO::x86_EXCEPTION_STATE64_COUNT) +          outs() << "      count x86_EXCEPTION_STATE64_COUNT\n"; +        else +          outs() << "      count " << count +                 << " (not x86_EXCEPTION_STATE64_COUNT)\n"; +        struct MachO::x86_exception_state64_t es64; +        left = end - begin; +        if (left >= sizeof(MachO::x86_exception_state64_t)) { +          memcpy(&es64, begin, sizeof(MachO::x86_exception_state64_t)); +          begin += sizeof(MachO::x86_exception_state64_t); +        } else { +          memset(&es64, '\0', sizeof(MachO::x86_exception_state64_t)); +          memcpy(&es64, begin, left); +          begin += left; +        } +        if (isLittleEndian != sys::IsLittleEndianHost) +          swapStruct(es64); +        Print_x86_exception_state_t(es64);        } else {          outs() << "     flavor " << flavor << " (unknown)\n";          outs() << "      count " << count << "\n"; diff --git a/contrib/llvm/tools/llvm-objdump/WasmDump.cpp b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp index 0d8ffba6ba45..045002cd4b34 100644 --- a/contrib/llvm/tools/llvm-objdump/WasmDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp @@ -8,7 +8,7 @@  //===----------------------------------------------------------------------===//  ///  /// \file -/// \brief This file implements the wasm-specific dumper for llvm-objdump. +/// This file implements the wasm-specific dumper for llvm-objdump.  ///  //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp index 3a9112423cff..8041e6f59940 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -20,10 +20,12 @@  #include "llvm/ADT/Optional.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h"  #include "llvm/ADT/Triple.h"  #include "llvm/CodeGen/FaultMaps.h"  #include "llvm/DebugInfo/DWARF/DWARFContext.h"  #include "llvm/DebugInfo/Symbolize/Symbolize.h" +#include "llvm/Demangle/Demangle.h"  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCContext.h"  #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -50,10 +52,8 @@  #include "llvm/Support/Format.h"  #include "llvm/Support/GraphWriter.h"  #include "llvm/Support/Host.h" -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/InitLLVM.h"  #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h"  #include "llvm/Support/SourceMgr.h"  #include "llvm/Support/TargetRegistry.h"  #include "llvm/Support/TargetSelect.h" @@ -68,6 +68,12 @@  using namespace llvm;  using namespace object; +cl::opt<bool> +    llvm::AllHeaders("all-headers", +                     cl::desc("Display all available header information")); +static cl::alias AllHeadersShort("x", cl::desc("Alias for --all-headers"), +                                 cl::aliasopt(AllHeaders)); +  static cl::list<std::string>  InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore); @@ -85,10 +91,30 @@ static cl::alias  DisassembleAlld("D", cl::desc("Alias for --disassemble-all"),               cl::aliasopt(DisassembleAll)); +cl::opt<std::string> llvm::Demangle("demangle", +                                    cl::desc("Demangle symbols names"), +                                    cl::ValueOptional, cl::init("none")); + +static cl::alias DemangleShort("C", cl::desc("Alias for --demangle"), +                               cl::aliasopt(Demangle)); + +static cl::list<std::string> +DisassembleFunctions("df", +                     cl::CommaSeparated, +                     cl::desc("List of functions to disassemble")); +static StringSet<> DisasmFuncsSet; +  cl::opt<bool>  llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));  cl::opt<bool> +llvm::DynamicRelocations("dynamic-reloc", +  cl::desc("Display the dynamic relocation entries in the file")); +static cl::alias +DynamicRelocationsd("R", cl::desc("Alias for --dynamic-reloc"), +             cl::aliasopt(DynamicRelocations)); + +cl::opt<bool>  llvm::SectionContents("s", cl::desc("Display the content of each section"));  cl::opt<bool> @@ -182,6 +208,21 @@ static cl::alias  PrivateHeadersShort("p", cl::desc("Alias for --private-headers"),                      cl::aliasopt(PrivateHeaders)); +cl::opt<bool> llvm::FileHeaders( +    "file-headers", +    cl::desc("Display the contents of the overall file header")); + +static cl::alias FileHeadersShort("f", cl::desc("Alias for --file-headers"), +                                  cl::aliasopt(FileHeaders)); + +cl::opt<bool> +    llvm::ArchiveHeaders("archive-headers", +                         cl::desc("Display archive header information")); + +cl::alias +ArchiveHeadersShort("a", cl::desc("Alias for --archive-headers"), +                    cl::aliasopt(ArchiveHeaders)); +  cl::opt<bool>      llvm::PrintImmHex("print-imm-hex",                        cl::desc("Use hex format for immediate values")); @@ -196,7 +237,7 @@ cl::opt<DIDumpType> llvm::DwarfDumpType(  cl::opt<bool> PrintSource(      "source",      cl::desc( -        "Display source inlined with disassembly. Implies disassmble object")); +        "Display source inlined with disassembly. Implies disassemble object"));  cl::alias PrintSourceShort("S", cl::desc("Alias for -source"),                             cl::aliasopt(PrintSource)); @@ -297,6 +338,11 @@ LLVM_ATTRIBUTE_NORETURN void llvm::error(Twine Message) {    exit(1);  } +void llvm::warn(StringRef Message) { +  errs() << ToolName << ": warning: " << Message << ".\n"; +  errs().flush(); +} +  LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File,                                                  Twine Message) {    errs() << ToolName << ": '" << File << "': " << Message << ".\n"; @@ -396,252 +442,6 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {    return a.getOffset() < b.getOffset();  } -namespace { -class SourcePrinter { -protected: -  DILineInfo OldLineInfo; -  const ObjectFile *Obj = nullptr; -  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer; -  // File name to file contents of source -  std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache; -  // Mark the line endings of the cached source -  std::unordered_map<std::string, std::vector<StringRef>> LineCache; - -private: -  bool cacheSource(const std::string& File); - -public: -  SourcePrinter() = default; -  SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) { -    symbolize::LLVMSymbolizer::Options SymbolizerOpts( -        DILineInfoSpecifier::FunctionNameKind::None, true, false, false, -        DefaultArch); -    Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); -  } -  virtual ~SourcePrinter() = default; -  virtual void printSourceLine(raw_ostream &OS, uint64_t Address, -                               StringRef Delimiter = "; "); -}; - -bool SourcePrinter::cacheSource(const std::string& File) { -  auto BufferOrError = MemoryBuffer::getFile(File); -  if (!BufferOrError) -    return false; -  // Chomp the file to get lines -  size_t BufferSize = (*BufferOrError)->getBufferSize(); -  const char *BufferStart = (*BufferOrError)->getBufferStart(); -  for (const char *Start = BufferStart, *End = BufferStart; -       End < BufferStart + BufferSize; End++) -    if (*End == '\n' || End == BufferStart + BufferSize - 1 || -        (*End == '\r' && *(End + 1) == '\n')) { -      LineCache[File].push_back(StringRef(Start, End - Start)); -      if (*End == '\r') -        End++; -      Start = End + 1; -    } -  SourceCache[File] = std::move(*BufferOrError); -  return true; -} - -void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, -                                    StringRef Delimiter) { -  if (!Symbolizer) -    return; -  DILineInfo LineInfo = DILineInfo(); -  auto ExpectecLineInfo = -      Symbolizer->symbolizeCode(Obj->getFileName(), Address); -  if (!ExpectecLineInfo) -    consumeError(ExpectecLineInfo.takeError()); -  else -    LineInfo = *ExpectecLineInfo; - -  if ((LineInfo.FileName == "<invalid>") || OldLineInfo.Line == LineInfo.Line || -      LineInfo.Line == 0) -    return; - -  if (PrintLines) -    OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; -  if (PrintSource) { -    if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) -      if (!cacheSource(LineInfo.FileName)) -        return; -    auto FileBuffer = SourceCache.find(LineInfo.FileName); -    if (FileBuffer != SourceCache.end()) { -      auto LineBuffer = LineCache.find(LineInfo.FileName); -      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; -} - -static bool isArmElf(const ObjectFile *Obj) { -  return (Obj->isELF() && -          (Obj->getArch() == Triple::aarch64 || -           Obj->getArch() == Triple::aarch64_be || -           Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb || -           Obj->getArch() == Triple::thumb || -           Obj->getArch() == Triple::thumbeb)); -} - -class PrettyPrinter { -public: -  virtual ~PrettyPrinter() = default; -  virtual void printInst(MCInstPrinter &IP, const MCInst *MI, -                         ArrayRef<uint8_t> Bytes, uint64_t Address, -                         raw_ostream &OS, StringRef Annot, -                         MCSubtargetInfo const &STI, SourcePrinter *SP) { -    if (SP && (PrintSource || PrintLines)) -      SP->printSourceLine(OS, Address); -    if (!NoLeadingAddr) -      OS << format("%8" PRIx64 ":", Address); -    if (!NoShowRawInsn) { -      OS << "\t"; -      dumpBytes(Bytes, OS); -    } -    if (MI) -      IP.printInst(MI, OS, "", STI); -    else -      OS << " <unknown>"; -  } -}; -PrettyPrinter PrettyPrinterInst; -class HexagonPrettyPrinter : public PrettyPrinter { -public: -  void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address, -                 raw_ostream &OS) { -    uint32_t opcode = -      (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0]; -    if (!NoLeadingAddr) -      OS << format("%8" PRIx64 ":", Address); -    if (!NoShowRawInsn) { -      OS << "\t"; -      dumpBytes(Bytes.slice(0, 4), OS); -      OS << format("%08" PRIx32, opcode); -    } -  } -  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) { -      printLead(Bytes, Address, OS); -      OS << " <unknown>"; -      return; -    } -    std::string Buffer; -    { -      raw_string_ostream TempStream(Buffer); -      IP.printInst(MI, TempStream, "", STI); -    } -    StringRef Contents(Buffer); -    // Split off bundle attributes -    auto PacketBundle = Contents.rsplit('\n'); -    // Split off first instruction from the rest -    auto HeadTail = PacketBundle.first.split('\n'); -    auto Preamble = " { "; -    auto Separator = ""; -    while(!HeadTail.first.empty()) { -      OS << Separator; -      Separator = "\n"; -      if (SP && (PrintSource || PrintLines)) -        SP->printSourceLine(OS, Address, ""); -      printLead(Bytes, Address, OS); -      OS << Preamble; -      Preamble = "   "; -      StringRef Inst; -      auto Duplex = HeadTail.first.split('\v'); -      if(!Duplex.second.empty()){ -        OS << Duplex.first; -        OS << "; "; -        Inst = Duplex.second; -      } -      else -        Inst = HeadTail.first; -      OS << Inst; -      Bytes = Bytes.slice(4); -      Address += 4; -      HeadTail = HeadTail.second.split('\n'); -    } -    OS << " } " << PacketBundle.second; -  } -}; -HexagonPrettyPrinter HexagonPrettyPrinterInst; - -class AMDGCNPrettyPrinter : public PrettyPrinter { -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; -    } - -    SmallString<40> InstStr; -    raw_svector_ostream IS(InstStr); - -    IP.printInst(MI, IS, "", STI); - -    OS << left_justify(IS.str(), 60) << format("// %012" PRIX64 ": ", Address); -    typedef support::ulittle32_t U32; -    for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()), -                               Bytes.size() / sizeof(U32))) -      // D should be explicitly casted to uint32_t here as it is passed -      // by format to snprintf as vararg. -      OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D)); - -    if (!Annot.empty()) -      OS << "// " << Annot; -  } -}; -AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst; - -class BPFPrettyPrinter : public PrettyPrinter { -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 (!NoLeadingAddr) -      OS << format("%8" PRId64 ":", Address / 8); -    if (!NoShowRawInsn) { -      OS << "\t"; -      dumpBytes(Bytes, OS); -    } -    if (MI) -      IP.printInst(MI, OS, "", STI); -    else -      OS << " <unknown>"; -  } -}; -BPFPrettyPrinter BPFPrettyPrinterInst; - -PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { -  switch(Triple.getArch()) { -  default: -    return PrettyPrinterInst; -  case Triple::hexagon: -    return HexagonPrettyPrinterInst; -  case Triple::amdgcn: -    return AMDGCNPrettyPrinterInst; -  case Triple::bpfel: -  case Triple::bpfeb: -    return BPFPrettyPrinterInst; -  } -} -} -  template <class ELFT>  static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,                                                  const RelocationRef &RelRef, @@ -671,9 +471,11 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,    if (!StrTabOrErr)      return errorToErrorCode(StrTabOrErr.takeError());    StringRef StrTab = *StrTabOrErr; -  uint8_t type = RelRef.getType(); -  StringRef res;    int64_t addend = 0; +  // If there is no Symbol associated with the relocation, we set the undef +  // boolean value to 'true'. This will prevent us from calling functions that +  // requires the relocation to be associated with a symbol. +  bool undef = false;    switch (Sec->sh_type) {    default:      return object_error::parse_failed; @@ -684,97 +486,41 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj,    case ELF::SHT_RELA: {      const Elf_Rela *ERela = Obj->getRela(Rel);      addend = ERela->r_addend; +    undef = ERela->getSymbol(false) == 0;      break;    }    } -  symbol_iterator SI = RelRef.getSymbol(); -  const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl());    StringRef Target; -  if (symb->getType() == ELF::STT_SECTION) { -    Expected<section_iterator> SymSI = SI->getSection(); -    if (!SymSI) -      return errorToErrorCode(SymSI.takeError()); -    const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); -    auto SecName = EF.getSectionName(SymSec); -    if (!SecName) -      return errorToErrorCode(SecName.takeError()); -    Target = *SecName; -  } else { -    Expected<StringRef> SymName = symb->getName(StrTab); -    if (!SymName) -      return errorToErrorCode(SymName.takeError()); -    Target = *SymName; -  } -  switch (EF.getHeader()->e_machine) { -  case ELF::EM_X86_64: -    switch (type) { -    case ELF::R_X86_64_PC8: -    case ELF::R_X86_64_PC16: -    case ELF::R_X86_64_PC32: { -      std::string fmtbuf; -      raw_string_ostream fmt(fmtbuf); -      fmt << Target << (addend < 0 ? "" : "+") << addend << "-P"; -      fmt.flush(); -      Result.append(fmtbuf.begin(), fmtbuf.end()); -    } break; -    case ELF::R_X86_64_8: -    case ELF::R_X86_64_16: -    case ELF::R_X86_64_32: -    case ELF::R_X86_64_32S: -    case ELF::R_X86_64_64: { -      std::string fmtbuf; -      raw_string_ostream fmt(fmtbuf); -      fmt << Target << (addend < 0 ? "" : "+") << addend; -      fmt.flush(); -      Result.append(fmtbuf.begin(), fmtbuf.end()); -    } break; -    default: -      res = "Unknown"; -    } -    break; -  case ELF::EM_LANAI: -  case ELF::EM_AVR: -  case ELF::EM_AARCH64: { -    std::string fmtbuf; -    raw_string_ostream fmt(fmtbuf); -    fmt << Target; -    if (addend != 0) -      fmt << (addend < 0 ? "" : "+") << addend; -    fmt.flush(); -    Result.append(fmtbuf.begin(), fmtbuf.end()); -    break; -  } -  case ELF::EM_386: -  case ELF::EM_IAMCU: -  case ELF::EM_ARM: -  case ELF::EM_HEXAGON: -  case ELF::EM_MIPS: -  case ELF::EM_BPF: -  case ELF::EM_RISCV: -    res = Target; -    break; -  case ELF::EM_WEBASSEMBLY: -    switch (type) { -    case ELF::R_WEBASSEMBLY_DATA: { -      std::string fmtbuf; -      raw_string_ostream fmt(fmtbuf); -      fmt << Target << (addend < 0 ? "" : "+") << addend; -      fmt.flush(); -      Result.append(fmtbuf.begin(), fmtbuf.end()); -      break; -    } -    case ELF::R_WEBASSEMBLY_FUNCTION: -      res = Target; -      break; -    default: -      res = "Unknown"; +  if (!undef) { +    symbol_iterator SI = RelRef.getSymbol(); +    const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); +    if (symb->getType() == ELF::STT_SECTION) { +      Expected<section_iterator> SymSI = SI->getSection(); +      if (!SymSI) +        return errorToErrorCode(SymSI.takeError()); +      const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); +      auto SecName = EF.getSectionName(SymSec); +      if (!SecName) +        return errorToErrorCode(SecName.takeError()); +      Target = *SecName; +    } else { +      Expected<StringRef> SymName = symb->getName(StrTab); +      if (!SymName) +        return errorToErrorCode(SymName.takeError()); +      Target = *SymName;      } -    break; -  default: -    res = "Unknown"; -  } -  if (Result.empty()) -    Result.append(res.begin(), res.end()); +  } else +    Target = "*ABS*"; + +  // Default scheme is to print Target, as well as "+ <addend>" for nonzero +  // addend. Should be acceptable for all normal purposes. +  std::string fmtbuf; +  raw_string_ostream fmt(fmtbuf); +  fmt << Target; +  if (addend != 0) +    fmt << (addend < 0 ? "" : "+") << addend; +  fmt.flush(); +  Result.append(fmtbuf.begin(), fmtbuf.end());    return std::error_code();  } @@ -887,9 +633,21 @@ static std::error_code getRelocationValueString(const WasmObjectFile *Obj,                                                  const RelocationRef &RelRef,                                                  SmallVectorImpl<char> &Result) {    const wasm::WasmRelocation& Rel = Obj->getWasmRelocation(RelRef); +  symbol_iterator SI = RelRef.getSymbol();    std::string fmtbuf;    raw_string_ostream fmt(fmtbuf); -  fmt << Rel.Index << (Rel.Addend < 0 ? "" : "+") << Rel.Addend; +  if (SI == Obj->symbol_end()) { +    // Not all wasm relocations have symbols associated with them. +    // In particular R_WEBASSEMBLY_TYPE_INDEX_LEB. +    fmt << Rel.Index; +  } else { +    Expected<StringRef> SymNameOrErr = SI->getName(); +    if (!SymNameOrErr) +      return errorToErrorCode(SymNameOrErr.takeError()); +    StringRef SymName = *SymNameOrErr; +    Result.append(SymName.begin(), SymName.end()); +  } +  fmt << (Rel.Addend < 0 ? "" : "+") << Rel.Addend;    fmt.flush();    Result.append(fmtbuf.begin(), fmtbuf.end());    return std::error_code(); @@ -1087,7 +845,7 @@ static std::error_code getRelocationValueString(const RelocationRef &Rel,    llvm_unreachable("unknown object file format");  } -/// @brief Indicates whether this relocation should hidden when listing +/// Indicates whether this relocation should hidden when listing  /// relocations, usually because it is the trailing part of a multipart  /// relocation that will be printed as part of the leading relocation.  static bool getHidden(RelocationRef RelRef) { @@ -1120,6 +878,304 @@ static bool getHidden(RelocationRef RelRef) {    return false;  } +namespace { +class SourcePrinter { +protected: +  DILineInfo OldLineInfo; +  const ObjectFile *Obj = nullptr; +  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer; +  // File name to file contents of source +  std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache; +  // Mark the line endings of the cached source +  std::unordered_map<std::string, std::vector<StringRef>> LineCache; + +private: +  bool cacheSource(const DILineInfo& LineInfoFile); + +public: +  SourcePrinter() = default; +  SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) { +    symbolize::LLVMSymbolizer::Options SymbolizerOpts( +        DILineInfoSpecifier::FunctionNameKind::None, true, false, false, +        DefaultArch); +    Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts)); +  } +  virtual ~SourcePrinter() = default; +  virtual void printSourceLine(raw_ostream &OS, uint64_t Address, +                               StringRef Delimiter = "; "); +}; + +bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) { +  std::unique_ptr<MemoryBuffer> Buffer; +  if (LineInfo.Source) { +    Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source); +  } else { +    auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName); +    if (!BufferOrError) +      return false; +    Buffer = std::move(*BufferOrError); +  } +  // Chomp the file to get lines +  size_t BufferSize = Buffer->getBufferSize(); +  const char *BufferStart = Buffer->getBufferStart(); +  for (const char *Start = BufferStart, *End = BufferStart; +       End < BufferStart + BufferSize; End++) +    if (*End == '\n' || End == BufferStart + BufferSize - 1 || +        (*End == '\r' && *(End + 1) == '\n')) { +      LineCache[LineInfo.FileName].push_back(StringRef(Start, End - Start)); +      if (*End == '\r') +        End++; +      Start = End + 1; +    } +  SourceCache[LineInfo.FileName] = std::move(Buffer); +  return true; +} + +void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address, +                                    StringRef Delimiter) { +  if (!Symbolizer) +    return; +  DILineInfo LineInfo = DILineInfo(); +  auto ExpectecLineInfo = +      Symbolizer->symbolizeCode(Obj->getFileName(), Address); +  if (!ExpectecLineInfo) +    consumeError(ExpectecLineInfo.takeError()); +  else +    LineInfo = *ExpectecLineInfo; + +  if ((LineInfo.FileName == "<invalid>") || OldLineInfo.Line == LineInfo.Line || +      LineInfo.Line == 0) +    return; + +  if (PrintLines) +    OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; +  if (PrintSource) { +    if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) +      if (!cacheSource(LineInfo)) +        return; +    auto FileBuffer = SourceCache.find(LineInfo.FileName); +    if (FileBuffer != SourceCache.end()) { +      auto LineBuffer = LineCache.find(LineInfo.FileName); +      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; +} + +static bool isArmElf(const ObjectFile *Obj) { +  return (Obj->isELF() && +          (Obj->getArch() == Triple::aarch64 || +           Obj->getArch() == Triple::aarch64_be || +           Obj->getArch() == Triple::arm || Obj->getArch() == Triple::armeb || +           Obj->getArch() == Triple::thumb || +           Obj->getArch() == Triple::thumbeb)); +} + +class PrettyPrinter { +public: +  virtual ~PrettyPrinter() = default; +  virtual void printInst(MCInstPrinter &IP, const MCInst *MI, +                         ArrayRef<uint8_t> Bytes, uint64_t Address, +                         raw_ostream &OS, StringRef Annot, +                         MCSubtargetInfo const &STI, SourcePrinter *SP, +                         std::vector<RelocationRef> *Rels = nullptr) { +    if (SP && (PrintSource || PrintLines)) +      SP->printSourceLine(OS, Address); +    if (!NoLeadingAddr) +      OS << format("%8" PRIx64 ":", Address); +    if (!NoShowRawInsn) { +      OS << "\t"; +      dumpBytes(Bytes, OS); +    } +    if (MI) +      IP.printInst(MI, OS, "", STI); +    else +      OS << " <unknown>"; +  } +}; +PrettyPrinter PrettyPrinterInst; +class HexagonPrettyPrinter : public PrettyPrinter { +public: +  void printLead(ArrayRef<uint8_t> Bytes, uint64_t Address, +                 raw_ostream &OS) { +    uint32_t opcode = +      (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0]; +    if (!NoLeadingAddr) +      OS << format("%8" PRIx64 ":", Address); +    if (!NoShowRawInsn) { +      OS << "\t"; +      dumpBytes(Bytes.slice(0, 4), OS); +      OS << format("%08" PRIx32, opcode); +    } +  } +  void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes, +                 uint64_t Address, raw_ostream &OS, StringRef Annot, +                 MCSubtargetInfo const &STI, SourcePrinter *SP, +                 std::vector<RelocationRef> *Rels) override { +    if (SP && (PrintSource || PrintLines)) +      SP->printSourceLine(OS, Address, ""); +    if (!MI) { +      printLead(Bytes, Address, OS); +      OS << " <unknown>"; +      return; +    } +    std::string Buffer; +    { +      raw_string_ostream TempStream(Buffer); +      IP.printInst(MI, TempStream, "", STI); +    } +    StringRef Contents(Buffer); +    // Split off bundle attributes +    auto PacketBundle = Contents.rsplit('\n'); +    // Split off first instruction from the rest +    auto HeadTail = PacketBundle.first.split('\n'); +    auto Preamble = " { "; +    auto Separator = ""; +    StringRef Fmt = "\t\t\t%08" PRIx64 ":  "; +    std::vector<RelocationRef>::const_iterator rel_cur = Rels->begin(); +    std::vector<RelocationRef>::const_iterator rel_end = Rels->end(); + +    // Hexagon's packets require relocations to be inline rather than +    // clustered at the end of the packet. +    auto PrintReloc = [&]() -> void { +      while ((rel_cur != rel_end) && (rel_cur->getOffset() <= Address)) { +        if (rel_cur->getOffset() == Address) { +          SmallString<16> name; +          SmallString<32> val; +          rel_cur->getTypeName(name); +          error(getRelocationValueString(*rel_cur, val)); +          OS << Separator << format(Fmt.data(), Address) << name << "\t" << val +                << "\n"; +          return; +        } +        rel_cur++; +      } +    }; + +    while(!HeadTail.first.empty()) { +      OS << Separator; +      Separator = "\n"; +      if (SP && (PrintSource || PrintLines)) +        SP->printSourceLine(OS, Address, ""); +      printLead(Bytes, Address, OS); +      OS << Preamble; +      Preamble = "   "; +      StringRef Inst; +      auto Duplex = HeadTail.first.split('\v'); +      if(!Duplex.second.empty()){ +        OS << Duplex.first; +        OS << "; "; +        Inst = Duplex.second; +      } +      else +        Inst = HeadTail.first; +      OS << Inst; +      HeadTail = HeadTail.second.split('\n'); +      if (HeadTail.first.empty()) +        OS << " } " << PacketBundle.second; +      PrintReloc(); +      Bytes = Bytes.slice(4); +      Address += 4; +    } +  } +}; +HexagonPrettyPrinter HexagonPrettyPrinterInst; + +class AMDGCNPrettyPrinter : public PrettyPrinter { +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, +                 std::vector<RelocationRef> *Rels) override { +    if (SP && (PrintSource || PrintLines)) +      SP->printSourceLine(OS, Address); + +    typedef support::ulittle32_t U32; + +    if (MI) { +      SmallString<40> InstStr; +      raw_svector_ostream IS(InstStr); + +      IP.printInst(MI, IS, "", STI); + +      OS << left_justify(IS.str(), 60); +    } else { +      // an unrecognized encoding - this is probably data so represent it +      // using the .long directive, or .byte directive if fewer than 4 bytes +      // remaining +      if (Bytes.size() >= 4) { +        OS << format("\t.long 0x%08" PRIx32 " ", +                     static_cast<uint32_t>(*reinterpret_cast<const U32*>(Bytes.data()))); +        OS.indent(42); +      } else { +          OS << format("\t.byte 0x%02" PRIx8, Bytes[0]); +          for (unsigned int i = 1; i < Bytes.size(); i++) +            OS << format(", 0x%02" PRIx8, Bytes[i]); +          OS.indent(55 - (6 * Bytes.size())); +      } +    } + +    OS << format("// %012" PRIX64 ": ", Address); +    if (Bytes.size() >=4) { +      for (auto D : makeArrayRef(reinterpret_cast<const U32*>(Bytes.data()), +                                 Bytes.size() / sizeof(U32))) +        // D should be explicitly casted to uint32_t here as it is passed +        // by format to snprintf as vararg. +        OS << format("%08" PRIX32 " ", static_cast<uint32_t>(D)); +    } else { +      for (unsigned int i = 0; i < Bytes.size(); i++) +        OS << format("%02" PRIX8 " ", Bytes[i]); +    } + +    if (!Annot.empty()) +      OS << "// " << Annot; +  } +}; +AMDGCNPrettyPrinter AMDGCNPrettyPrinterInst; + +class BPFPrettyPrinter : public PrettyPrinter { +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, +                 std::vector<RelocationRef> *Rels) override { +    if (SP && (PrintSource || PrintLines)) +      SP->printSourceLine(OS, Address); +    if (!NoLeadingAddr) +      OS << format("%8" PRId64 ":", Address / 8); +    if (!NoShowRawInsn) { +      OS << "\t"; +      dumpBytes(Bytes, OS); +    } +    if (MI) +      IP.printInst(MI, OS, "", STI); +    else +      OS << " <unknown>"; +  } +}; +BPFPrettyPrinter BPFPrettyPrinterInst; + +PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { +  switch(Triple.getArch()) { +  default: +    return PrettyPrinterInst; +  case Triple::hexagon: +    return HexagonPrettyPrinterInst; +  case Triple::amdgcn: +    return AMDGCNPrettyPrinterInst; +  case Triple::bpfel: +  case Triple::bpfeb: +    return BPFPrettyPrinterInst; +  } +} +} +  static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) {    assert(Obj->isELF());    if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj)) @@ -1254,6 +1310,7 @@ 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.    std::map<SectionRef, SectionSymbolsTy> AllSymbols; +  SectionSymbolsTy AbsoluteSymbols;    for (const SymbolRef &Symbol : Obj->symbols()) {      Expected<uint64_t> AddressOrErr = Symbol.getAddress();      if (!AddressOrErr) @@ -1269,15 +1326,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      Expected<section_iterator> SectionOrErr = Symbol.getSection();      if (!SectionOrErr)        report_error(Obj->getFileName(), SectionOrErr.takeError()); -    section_iterator SecI = *SectionOrErr; -    if (SecI == Obj->section_end()) -      continue;      uint8_t SymbolType = ELF::STT_NOTYPE;      if (Obj->isELF())        SymbolType = getElfSymbolType(Obj, Symbol); -    AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); +    section_iterator SecI = *SectionOrErr; +    if (SecI != Obj->section_end()) +      AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); +    else +      AbsoluteSymbols.emplace_back(Address, *Name, SymbolType); +    }    if (AllSymbols.empty() && Obj->isELF()) @@ -1313,6 +1372,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {        if (Sec != SectionAddresses.end())          AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE); +      else +        AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE);      }    } @@ -1320,6 +1381,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {    // a symbol near an address.    for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)      array_pod_sort(SecSyms.second.begin(), SecSyms.second.end()); +  array_pod_sort(AbsoluteSymbols.begin(), AbsoluteSymbols.end());    for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      if (!DisassembleAll && (!Section.isText() || Section.isVirtual())) @@ -1349,8 +1411,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {        }      } -    std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end()); -    std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end()); +    llvm::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end()); +    llvm::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());      if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {        // AMDGPU disassembler uses symbolizer for printing labels @@ -1375,30 +1437,22 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      }      // Sort relocations by address. -    std::sort(Rels.begin(), Rels.end(), RelocAddressLess); +    llvm::sort(Rels.begin(), Rels.end(), RelocAddressLess);      StringRef SegmentName = "";      if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {        DataRefImpl DR = Section.getRawDataRefImpl();        SegmentName = MachO->getSectionFinalSegmentName(DR);      } -    StringRef name; -    error(Section.getName(name)); - -    if ((SectionAddr <= StopAddress) && -        (SectionAddr + SectSize) >= StartAddress) { -    outs() << "Disassembly of section "; -    if (!SegmentName.empty()) -      outs() << SegmentName << ","; -    outs() << name << ':'; -    } +    StringRef SectionName; +    error(Section.getName(SectionName));      // If the section has no symbol at the start, just insert a dummy one.      if (Symbols.empty() || std::get<0>(Symbols[0]) != 0) { -      Symbols.insert(Symbols.begin(), -                     std::make_tuple(SectionAddr, name, Section.isText() -                                                            ? ELF::STT_FUNC -                                                            : ELF::STT_OBJECT)); +      Symbols.insert( +          Symbols.begin(), +          std::make_tuple(SectionAddr, SectionName, +                          Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT));      }      SmallString<40> Comments; @@ -1411,6 +1465,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {      uint64_t Size;      uint64_t Index; +    bool PrintedSection = false;      std::vector<RelocationRef>::const_iterator rel_cur = Rels.begin();      std::vector<RelocationRef>::const_iterator rel_end = Rels.end(); @@ -1435,13 +1490,24 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {          continue;        } +      /// Skip if user requested specific symbols and this is not in the list +      if (!DisasmFuncsSet.empty() && +          !DisasmFuncsSet.count(std::get<1>(Symbols[si]))) +        continue; + +      if (!PrintedSection) { +        PrintedSection = true; +        outs() << "Disassembly of section "; +        if (!SegmentName.empty()) +          outs() << SegmentName << ","; +        outs() << SectionName << ':'; +      } +        // Stop disassembly at the stop address specified        if (End + SectionAddr > StopAddress)          End = StopAddress - SectionAddr;        if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) { -        // make size 4 bytes folded -        End = Start + ((End - Start) & ~0x3ull);          if (std::get<2>(Symbols[si]) == ELF::STT_AMDGPU_HSA_KERNEL) {            // skip amd_kernel_code_t at the begining of kernel symbol (256 bytes)            Start += 256; @@ -1458,7 +1524,32 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {          }        } -      outs() << '\n' << std::get<1>(Symbols[si]) << ":\n"; +      auto PrintSymbol = [](StringRef Name) { +        outs() << '\n' << Name << ":\n"; +      }; +      StringRef SymbolName = std::get<1>(Symbols[si]); +      if (Demangle.getValue() == "" || Demangle.getValue() == "itanium") { +        char *DemangledSymbol = nullptr; +        size_t Size = 0; +        int Status; +        DemangledSymbol = +            itaniumDemangle(SymbolName.data(), DemangledSymbol, &Size, &Status); +        if (Status == 0) +          PrintSymbol(StringRef(DemangledSymbol)); +        else +          PrintSymbol(SymbolName); + +        if (Size != 0) +          free(DemangledSymbol); +      } else +        PrintSymbol(SymbolName); + +      // Don't print raw contents of a virtual section. A virtual section +      // doesn't have any contents in the file. +      if (Section.isVirtual()) { +        outs() << "...\n"; +        continue; +      }  #ifndef NDEBUG        raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); @@ -1560,7 +1651,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {              }              Byte = Bytes.slice(Index)[0];              outs() << format(" %02x", Byte); -            AsciiData[NumBytes] = isprint(Byte) ? Byte : '.'; +            AsciiData[NumBytes] = isPrint(Byte) ? Byte : '.';              uint8_t IndentOffset = 0;              NumBytes++; @@ -1594,7 +1685,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {          PIP.printInst(*IP, Disassembled ? &Inst : nullptr,                        Bytes.slice(Index, Size), SectionAddr + Index, outs(), "", -                      *STI, &SP); +                      *STI, &SP, &Rels);          outs() << CommentStream.str();          Comments.clear(); @@ -1623,55 +1714,65 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {                  --SectionAddress;                  TargetSectionSymbols = &AllSymbols[SectionAddress->second];                } else { -                TargetSectionSymbols = nullptr; +                TargetSectionSymbols = &AbsoluteSymbols;                }              }              // 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(), +            // or equal to the target. If there isn't a section that contains +            // the target, find the nearest preceding absolute symbol. +            auto TargetSym = std::upper_bound( +                TargetSectionSymbols->begin(), TargetSectionSymbols->end(), +                Target, [](uint64_t LHS, +                           const std::tuple<uint64_t, StringRef, uint8_t> &RHS) { +                  return LHS < std::get<0>(RHS); +                }); +            if (TargetSym == TargetSectionSymbols->begin()) { +              TargetSectionSymbols = &AbsoluteSymbols; +              TargetSym = std::upper_bound( +                  AbsoluteSymbols.begin(), AbsoluteSymbols.end(),                    Target, [](uint64_t LHS,                               const std::tuple<uint64_t, StringRef, uint8_t> &RHS) { -                    return LHS < std::get<0>(RHS); -                  }); -              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() << "+0x" << Twine::utohexstr(Disp); -                outs() << '>'; -              } +                            return LHS < std::get<0>(RHS); +                          }); +            } +            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() << "+0x" << Twine::utohexstr(Disp); +              outs() << '>';              }            }          }          outs() << "\n"; -        // Print relocation for instruction. -        while (rel_cur != rel_end) { -          bool hidden = getHidden(*rel_cur); -          uint64_t addr = rel_cur->getOffset(); -          SmallString<16> name; -          SmallString<32> val; +        // Hexagon does this in pretty printer +        if (Obj->getArch() != Triple::hexagon) +          // Print relocation for instruction. +          while (rel_cur != rel_end) { +            bool hidden = getHidden(*rel_cur); +            uint64_t addr = rel_cur->getOffset(); +            SmallString<16> name; +            SmallString<32> val; + +            // If this relocation is hidden, skip it. +            if (hidden || ((SectionAddr + addr) < StartAddress)) { +              ++rel_cur; +              continue; +            } -          // If this relocation is hidden, skip it. -          if (hidden || ((SectionAddr + addr) < StartAddress)) { +            // Stop when rel_cur's address is past the current instruction. +            if (addr >= Index + Size) break; +            rel_cur->getTypeName(name); +            error(getRelocationValueString(*rel_cur, val)); +            outs() << format(Fmt.data(), SectionAddr + addr) << name +                   << "\t" << val << "\n";              ++rel_cur; -            continue;            } - -          // Stop when rel_cur's address is past the current instruction. -          if (addr >= Index + Size) break; -          rel_cur->getTypeName(name); -          error(getRelocationValueString(*rel_cur, val)); -          outs() << format(Fmt.data(), SectionAddr + addr) << name -                 << "\t" << val << "\n"; -          ++rel_cur; -        }        }      }    } @@ -1707,10 +1808,44 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {    }  } +void llvm::PrintDynamicRelocations(const ObjectFile *Obj) { + +  // For the moment, this option is for ELF only +  if (!Obj->isELF()) +    return; + +  const auto *Elf = dyn_cast<ELFObjectFileBase>(Obj); + +  if (!Elf || Elf->getEType() != ELF::ET_DYN) { +    error("not a dynamic object"); +    return; +  } + +  StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64; + +  std::vector<SectionRef> DynRelSec = Obj->dynamic_relocation_sections(); +  if (DynRelSec.empty()) +    return; + +  outs() << "DYNAMIC RELOCATION RECORDS\n"; +  for (const SectionRef &Section : DynRelSec) { +    if (Section.relocation_begin() == Section.relocation_end()) +      continue; +    for (const RelocationRef &Reloc : Section.relocations()) { +      uint64_t address = Reloc.getOffset(); +      SmallString<32> relocname; +      SmallString<32> valuestr; +      Reloc.getTypeName(relocname); +      error(getRelocationValueString(Reloc, valuestr)); +      outs() << format(Fmt.data(), address) << " " << relocname << " " +             << valuestr << "\n"; +    } +  } +} +  void llvm::PrintSectionHeaders(const ObjectFile *Obj) {    outs() << "Sections:\n"              "Idx Name          Size      Address          Type\n"; -  unsigned i = 0;    for (const SectionRef &Section : ToolSectionFilter(*Obj)) {      StringRef Name;      error(Section.getName(Name)); @@ -1721,9 +1856,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) {      bool BSS = Section.isBSS();      std::string Type = (std::string(Text ? "TEXT " : "") +                          (Data ? "DATA " : "") + (BSS ? "BSS" : "")); -    outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i, -                     Name.str().c_str(), Size, Address, Type.c_str()); -    ++i; +    outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", +                     (unsigned)Section.getIndex(), Name.str().c_str(), Size, +                     Address, Type.c_str());    }  } @@ -1764,7 +1899,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) {        // Print ascii.        outs() << "  ";        for (std::size_t i = 0; i < 16 && addr + i < end; ++i) { -        if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF)) +        if (isPrint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))            outs() << Contents[addr + i];          else            outs() << "."; @@ -2018,8 +2153,10 @@ static void printFaultMaps(const ObjectFile *Obj) {  }  static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) { -  if (o->isELF()) -    return printELFFileHeader(o); +  if (o->isELF()) { +    printELFFileHeader(o); +    return printELFDynamicSection(o); +  }    if (o->isCOFF())      return printCOFFFileHeader(o);    if (o->isWasm()) @@ -2033,7 +2170,86 @@ static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) {    report_error(o->getFileName(), "Invalid/Unsupported object file format");  } -static void DumpObject(ObjectFile *o, const Archive *a = nullptr) { +static void printFileHeaders(const ObjectFile *o) { +  if (!o->isELF() && !o->isCOFF()) +    report_error(o->getFileName(), "Invalid/Unsupported object file format"); + +  Triple::ArchType AT = o->getArch(); +  outs() << "architecture: " << Triple::getArchTypeName(AT) << "\n"; +  Expected<uint64_t> StartAddrOrErr = o->getStartAddress(); +  if (!StartAddrOrErr) +    report_error(o->getFileName(), StartAddrOrErr.takeError()); +  outs() << "start address: " +         << format("0x%0*x", o->getBytesInAddress(), StartAddrOrErr.get()) +         << "\n"; +} + +static void printArchiveChild(StringRef Filename, const Archive::Child &C) { +  Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); +  if (!ModeOrErr) { +    errs() << "ill-formed archive entry.\n"; +    consumeError(ModeOrErr.takeError()); +    return; +  } +  sys::fs::perms Mode = ModeOrErr.get(); +  outs() << ((Mode & sys::fs::owner_read) ? "r" : "-"); +  outs() << ((Mode & sys::fs::owner_write) ? "w" : "-"); +  outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-"); +  outs() << ((Mode & sys::fs::group_read) ? "r" : "-"); +  outs() << ((Mode & sys::fs::group_write) ? "w" : "-"); +  outs() << ((Mode & sys::fs::group_exe) ? "x" : "-"); +  outs() << ((Mode & sys::fs::others_read) ? "r" : "-"); +  outs() << ((Mode & sys::fs::others_write) ? "w" : "-"); +  outs() << ((Mode & sys::fs::others_exe) ? "x" : "-"); + +  outs() << " "; + +  Expected<unsigned> UIDOrErr = C.getUID(); +  if (!UIDOrErr) +    report_error(Filename, UIDOrErr.takeError()); +  unsigned UID = UIDOrErr.get(); +  outs() << format("%d/", UID); + +  Expected<unsigned> GIDOrErr = C.getGID(); +  if (!GIDOrErr) +    report_error(Filename, GIDOrErr.takeError()); +  unsigned GID = GIDOrErr.get(); +  outs() << format("%-d ", GID); + +  Expected<uint64_t> Size = C.getRawSize(); +  if (!Size) +    report_error(Filename, Size.takeError()); +  outs() << format("%6" PRId64, Size.get()) << " "; + +  StringRef RawLastModified = C.getRawLastModified(); +  unsigned Seconds; +  if (RawLastModified.getAsInteger(10, Seconds)) +    outs() << "(date: \"" << RawLastModified +           << "\" contains non-decimal chars) "; +  else { +    // Since ctime(3) returns a 26 character string of the form: +    // "Sun Sep 16 01:03:52 1973\n\0" +    // just print 24 characters. +    time_t t = Seconds; +    outs() << format("%.24s ", ctime(&t)); +  } + +  StringRef Name = ""; +  Expected<StringRef> NameOrErr = C.getName(); +  if (!NameOrErr) { +    consumeError(NameOrErr.takeError()); +    Expected<StringRef> RawNameOrErr = C.getRawName(); +    if (!RawNameOrErr) +      report_error(Filename, NameOrErr.takeError()); +    Name = RawNameOrErr.get(); +  } else { +    Name = NameOrErr.get(); +  } +  outs() << Name << "\n"; +} + +static void DumpObject(ObjectFile *o, const Archive *a = nullptr, +                       const Archive::Child *c = nullptr) {    StringRef ArchiveName = a != nullptr ? a->getFileName() : "";    // Avoid other output when using a raw option.    if (!RawClangAST) { @@ -2045,10 +2261,14 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {      outs() << ":\tfile format " << o->getFileFormatName() << "\n\n";    } +  if (ArchiveHeaders && !MachOOpt) +    printArchiveChild(a->getFileName(), *c);    if (Disassemble)      DisassembleObject(o, Relocations);    if (Relocations && !Disassemble)      PrintRelocations(o); +  if (DynamicRelocations) +    PrintDynamicRelocations(o);    if (SectionHeaders)      PrintSectionHeaders(o);    if (SectionContents) @@ -2059,6 +2279,8 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {      PrintUnwindInfo(o);    if (PrivateHeaders || FirstPrivateHeader)      printPrivateFileHeaders(o, FirstPrivateHeader); +  if (FileHeaders) +    printFileHeaders(o);    if (ExportsTrie)      printExportsTrie(o);    if (Rebase) @@ -2082,7 +2304,8 @@ static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {    }  } -static void DumpObject(const COFFImportFile *I, const Archive *A) { +static void DumpObject(const COFFImportFile *I, const Archive *A, +                       const Archive::Child *C = nullptr) {    StringRef ArchiveName = A ? A->getFileName() : "";    // Avoid other output when using a raw option. @@ -2092,11 +2315,13 @@ static void DumpObject(const COFFImportFile *I, const Archive *A) {             << ":\tfile format COFF-import-file"             << "\n\n"; +  if (ArchiveHeaders && !MachOOpt) +    printArchiveChild(A->getFileName(), *C);    if (SymbolTable)      printCOFFSymbolTable(I);  } -/// @brief Dump each object file in \a a; +/// Dump each object file in \a a;  static void DumpArchive(const Archive *a) {    Error Err = Error::success();    for (auto &C : a->children(Err)) { @@ -2107,9 +2332,9 @@ static void DumpArchive(const Archive *a) {        continue;      }      if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) -      DumpObject(o, a); +      DumpObject(o, a, &C);      else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get())) -      DumpObject(I, a); +      DumpObject(I, a, &C);      else        report_error(a->getFileName(), object_error::invalid_file_type);    } @@ -2117,7 +2342,7 @@ static void DumpArchive(const Archive *a) {      report_error(a->getFileName(), std::move(Err));  } -/// @brief Open file and figure out how to dump it. +/// Open file and figure out how to dump it.  static void DumpInput(StringRef file) {    // If we are using the Mach-O specific object file parser, then let it parse @@ -2143,10 +2368,7 @@ static void DumpInput(StringRef file) {  }  int main(int argc, char **argv) { -  // Print a stack trace if we signal out. -  sys::PrintStackTraceOnErrorSignal(argv[0]); -  PrettyStackTraceProgram X(argc, argv); -  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit. +  InitLLVM X(argc, argv);    // Initialize targets and assembly printers/parsers.    llvm::InitializeAllTargetInfos(); @@ -2165,15 +2387,25 @@ int main(int argc, char **argv) {    if (InputFilenames.size() == 0)      InputFilenames.push_back("a.out"); +  if (AllHeaders) +    PrivateHeaders = Relocations = SectionHeaders = SymbolTable = true; +    if (DisassembleAll || PrintSource || PrintLines)      Disassemble = true; + +  if (Demangle.getValue() != "none" && Demangle.getValue() != "" && +      Demangle.getValue() != "itanium") +    warn("Unsupported demangling style"); +    if (!Disassemble        && !Relocations +      && !DynamicRelocations        && !SectionHeaders        && !SectionContents        && !SymbolTable        && !UnwindInfo        && !PrivateHeaders +      && !FileHeaders        && !FirstPrivateHeader        && !ExportsTrie        && !Rebase @@ -2182,7 +2414,7 @@ int main(int argc, char **argv) {        && !WeakBind        && !RawClangAST        && !(UniversalHeaders && MachOOpt) -      && !(ArchiveHeaders && MachOOpt) +      && !ArchiveHeaders        && !(IndirectSymbols && MachOOpt)        && !(DataInCode && MachOOpt)        && !(LinkOptHints && MachOOpt) @@ -2197,6 +2429,9 @@ int main(int argc, char **argv) {      return 2;    } +  DisasmFuncsSet.insert(DisassembleFunctions.begin(), +                        DisassembleFunctions.end()); +    llvm::for_each(InputFilenames, DumpInput);    return EXIT_SUCCESS; diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h index 2fcd506884b1..b2eb6e9d7771 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h @@ -30,13 +30,16 @@ namespace object {  extern cl::opt<std::string> TripleName;  extern cl::opt<std::string> ArchName;  extern cl::opt<std::string> MCPU; +extern cl::opt<std::string> Demangle;  extern cl::list<std::string> MAttrs;  extern cl::list<std::string> FilterSections; +extern cl::opt<bool> AllHeaders;  extern cl::opt<bool> Disassemble;  extern cl::opt<bool> DisassembleAll;  extern cl::opt<bool> NoShowRawInsn;  extern cl::opt<bool> NoLeadingAddr;  extern cl::opt<bool> PrivateHeaders; +extern cl::opt<bool> FileHeaders;  extern cl::opt<bool> FirstPrivateHeader;  extern cl::opt<bool> ExportsTrie;  extern cl::opt<bool> Rebase; @@ -56,6 +59,7 @@ extern cl::opt<bool> ObjcMetaData;  extern cl::opt<std::string> DisSymName;  extern cl::opt<bool> NonVerbose;  extern cl::opt<bool> Relocations; +extern cl::opt<bool> DynamicRelocations;  extern cl::opt<bool> SectionHeaders;  extern cl::opt<bool> SectionContents;  extern cl::opt<bool> SymbolTable; @@ -75,6 +79,7 @@ void printMachOBindTable(object::MachOObjectFile* o);  void printMachOLazyBindTable(object::MachOObjectFile* o);  void printMachOWeakBindTable(object::MachOObjectFile* o);  void printELFFileHeader(const object::ObjectFile *o); +void printELFDynamicSection(const object::ObjectFile *Obj);  void printCOFFFileHeader(const object::ObjectFile *o);  void printCOFFSymbolTable(const object::COFFImportFile *i);  void printCOFFSymbolTable(const object::COFFObjectFile *o); @@ -88,10 +93,12 @@ void printLazyBindTable(object::ObjectFile *o);  void printWeakBindTable(object::ObjectFile *o);  void printRawClangAST(const object::ObjectFile *o);  void PrintRelocations(const object::ObjectFile *o); +void PrintDynamicRelocations(const object::ObjectFile *o);  void PrintSectionHeaders(const object::ObjectFile *o);  void PrintSectionContents(const object::ObjectFile *o);  void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName,                        StringRef ArchitectureName = StringRef()); +void warn(StringRef Message);  LLVM_ATTRIBUTE_NORETURN void error(Twine Message);  LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, Twine Message);  LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, std::error_code EC);  | 
