diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump')
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/COFFDump.cpp | 34 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/ELFDump.cpp | 35 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MachODump.cpp | 680 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/WasmDump.cpp | 28 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp | 594 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.h | 4 |
6 files changed, 901 insertions, 474 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp index 3ec6a1f..db549bb 100644 --- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp @@ -17,6 +17,7 @@ #include "llvm-objdump.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Format.h" #include "llvm/Support/SourceMgr.h" @@ -176,12 +177,10 @@ resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym, // the function returns the symbol used for the relocation at the offset. static std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels, uint64_t Offset, SymbolRef &Sym) { - for (std::vector<RelocationRef>::const_iterator I = Rels.begin(), - E = Rels.end(); - I != E; ++I) { - uint64_t Ofs = I->getOffset(); + for (auto &R : Rels) { + uint64_t Ofs = R.getOffset(); if (Ofs == Offset) { - Sym = *I->getSymbol(); + Sym = *R.getSymbol(); return std::error_code(); } } @@ -353,7 +352,7 @@ static void printImportTables(const COFFObjectFile *Obj) { return; outs() << "The Import Tables:\n"; for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) { - const import_directory_table_entry *Dir; + const coff_import_directory_table_entry *Dir; StringRef Name; if (DirRef.getImportTableEntry(Dir)) return; if (DirRef.getName(Name)) return; @@ -617,6 +616,29 @@ void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) { printExportTable(file); } +void llvm::printCOFFSymbolTable(const object::COFFImportFile *i) { + unsigned Index = 0; + bool IsCode = i->getCOFFImportHeader()->getType() == COFF::IMPORT_CODE; + + for (const object::BasicSymbolRef &Sym : i->symbols()) { + std::string Name; + raw_string_ostream NS(Name); + + Sym.printName(NS); + NS.flush(); + + outs() << "[" << format("%2d", Index) << "]" + << "(sec " << format("%2d", 0) << ")" + << "(fl 0x00)" // Flag bits, which COFF doesn't have. + << "(ty " << format("%3x", (IsCode && Index) ? 32 : 0) << ")" + << "(scl " << format("%3x", 0) << ") " + << "(nx " << 0 << ") " + << "0x" << format("%08x", 0) << " " << Name << '\n'; + + ++Index; + } +} + void llvm::printCOFFSymbolTable(const COFFObjectFile *coff) { for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) { ErrorOr<COFFSymbolRef> Symbol = coff->getSymbol(SI); diff --git a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp index 7b44e39..7f5fe5a 100644 --- a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp @@ -24,22 +24,41 @@ using namespace llvm::object; template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { typedef ELFFile<ELFT> ELFO; outs() << "Program Header:\n"; - for (const typename ELFO::Elf_Phdr &Phdr : o->program_headers()) { + auto ProgramHeaderOrError = o->program_headers(); + if (!ProgramHeaderOrError) + report_fatal_error( + errorToErrorCode(ProgramHeaderOrError.takeError()).message()); + for (const typename ELFO::Elf_Phdr &Phdr : *ProgramHeaderOrError) { switch (Phdr.p_type) { - case ELF::PT_LOAD: - outs() << " LOAD "; - break; - case ELF::PT_GNU_STACK: - outs() << " STACK "; + case ELF::PT_DYNAMIC: + outs() << " DYNAMIC "; break; case ELF::PT_GNU_EH_FRAME: outs() << "EH_FRAME "; break; + case ELF::PT_GNU_RELRO: + outs() << " RELRO "; + break; + case ELF::PT_GNU_STACK: + outs() << " STACK "; + break; case ELF::PT_INTERP: outs() << " INTERP "; break; - case ELF::PT_DYNAMIC: - outs() << " DYNAMIC "; + case ELF::PT_LOAD: + outs() << " LOAD "; + break; + case ELF::PT_NOTE: + outs() << " NOTE "; + break; + case ELF::PT_OPENBSD_BOOTDATA: + outs() << " OPENBSD_BOOTDATA "; + break; + case ELF::PT_OPENBSD_RANDOMIZE: + outs() << " OPENBSD_RANDOMIZE "; + break; + case ELF::PT_OPENBSD_WXNEEDED: + outs() << " OPENBSD_WXNEEDED "; break; case ELF::PT_PHDR: outs() << " PHDR "; diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp index 4d950f1..5630848 100644 --- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp +++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp @@ -20,6 +20,7 @@ #include "llvm/Config/config.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -48,10 +49,6 @@ #include <cstring> #include <system_error> -#if HAVE_CXXABI_H -#include <cxxabi.h> -#endif - #ifdef HAVE_LIBXAR extern "C" { #include <xar/xar.h> @@ -74,6 +71,9 @@ static cl::opt<bool> FullLeadingAddr("full-leading-addr", static cl::opt<bool> NoLeadingAddr("no-leading-addr", cl::desc("Print no leading address")); +static cl::opt<bool> NoLeadingHeaders("no-leading-headers", + cl::desc("Print no leading headers")); + cl::opt<bool> llvm::UniversalHeaders("universal-headers", cl::desc("Print Mach-O universal headers " "(requires -macho)")); @@ -131,7 +131,7 @@ cl::opt<bool> cl::opt<std::string> llvm::DisSymName( "dis-symname", - cl::desc("disassemble just this symbol's instructions (requires -macho")); + cl::desc("disassemble just this symbol's instructions (requires -macho)")); static cl::opt<bool> NoSymbolicOperands( "no-symbolic-operands", @@ -186,22 +186,12 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj, struct SymbolSorter { bool operator()(const SymbolRef &A, const SymbolRef &B) { Expected<SymbolRef::Type> ATypeOrErr = A.getType(); - if (!ATypeOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(ATypeOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!ATypeOrErr) + report_error(A.getObject()->getFileName(), ATypeOrErr.takeError()); SymbolRef::Type AType = *ATypeOrErr; Expected<SymbolRef::Type> BTypeOrErr = B.getType(); - if (!BTypeOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(BTypeOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!BTypeOrErr) + report_error(B.getObject()->getFileName(), BTypeOrErr.takeError()); SymbolRef::Type BType = *BTypeOrErr; uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue(); uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue(); @@ -298,13 +288,8 @@ static void getSectionsAndSymbols(MachOObjectFile *MachOObj, uint64_t &BaseSegmentAddress) { for (const SymbolRef &Symbol : MachOObj->symbols()) { Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(MachOObj->getFileName(), SymName.takeError()); if (!SymName->startswith("ltmp")) Symbols.push_back(Symbol); } @@ -383,13 +368,8 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose, symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol); SymbolRef Symbol = *Sym; Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(O->getFileName(), SymName.takeError()); outs() << *SymName; } else { outs() << "?"; @@ -615,25 +595,15 @@ static void CreateSymbolAddressMap(MachOObjectFile *O, // Create a map of symbol addresses to symbol names. for (const SymbolRef &Symbol : O->symbols()) { Expected<SymbolRef::Type> STOrErr = Symbol.getType(); - if (!STOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(STOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!STOrErr) + report_error(O->getFileName(), STOrErr.takeError()); SymbolRef::Type ST = *STOrErr; if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || ST == SymbolRef::ST_Other) { uint64_t Address = Symbol.getValue(); Expected<StringRef> SymNameOrErr = Symbol.getName(); - if (!SymNameOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymNameOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymNameOrErr) + report_error(O->getFileName(), SymNameOrErr.takeError()); StringRef SymName = *SymNameOrErr; if (!SymName.startswith(".objc")) (*AddrMap)[Address] = SymName; @@ -862,29 +832,22 @@ static void DumpLiteralPointerSection(MachOObjectFile *O, } // First look for an external relocation entry for this literal pointer. - auto Reloc = std::find_if( - Relocs.begin(), Relocs.end(), - [&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; }); + 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) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(O->getFileName(), SymName.takeError()); outs() << "external relocation entry for symbol:" << *SymName << "\n"; continue; } // For local references see what the section the literal pointer points to. - auto Sect = std::find_if(LiteralSections.begin(), LiteralSections.end(), - [&](const SectionRef &R) { - return lp >= R.getAddress() && - lp < R.getAddress() + R.getSize(); - }); + auto Sect = find_if(LiteralSections, [&](const SectionRef &R) { + return lp >= R.getAddress() && lp < R.getAddress() + R.getSize(); + }); if (Sect == LiteralSections.end()) { outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; continue; @@ -1191,30 +1154,30 @@ static void DumpInfoPlistSectionContents(StringRef Filename, // architectures were specified. If not then an error is generated and this // routine returns false. Else it returns true. static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) { - if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) { - MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O); - bool ArchFound = false; - MachO::mach_header H; - MachO::mach_header_64 H_64; - Triple T; - if (MachO->is64Bit()) { - H_64 = MachO->MachOObjectFile::getHeader64(); - T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype); - } else { - H = MachO->MachOObjectFile::getHeader(); - T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype); - } - unsigned i; - for (i = 0; i < ArchFlags.size(); ++i) { - if (ArchFlags[i] == T.getArchName()) - ArchFound = true; - break; - } - if (!ArchFound) { - errs() << "llvm-objdump: file: " + Filename + " does not contain " - << "architecture: " + ArchFlags[i] + "\n"; - return false; - } + auto *MachO = dyn_cast<MachOObjectFile>(O); + + if (!MachO || ArchAll || ArchFlags.empty()) + return true; + + MachO::mach_header H; + MachO::mach_header_64 H_64; + Triple T; + const char *McpuDefault, *ArchFlag; + if (MachO->is64Bit()) { + H_64 = MachO->MachOObjectFile::getHeader64(); + T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, + &McpuDefault, &ArchFlag); + } else { + H = MachO->MachOObjectFile::getHeader(); + T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, + &McpuDefault, &ArchFlag); + } + const std::string ArchFlagName(ArchFlag); + if (none_of(ArchFlags, [&](const std::string &Name) { + return Name == ArchFlagName; + })) { + errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n"; + return false; } return true; } @@ -1225,7 +1188,7 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose); // archive member and or in a slice of a universal file. It prints the // the file name and header info and then processes it according to the // command line options. -static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, +static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF, StringRef ArchiveMemberName = StringRef(), StringRef ArchitectureName = StringRef()) { // If we are doing some processing here on the Mach-O file print the header @@ -1234,16 +1197,37 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) { - outs() << Filename; - if (!ArchiveMemberName.empty()) - outs() << '(' << ArchiveMemberName << ')'; - if (!ArchitectureName.empty()) - outs() << " (architecture " << ArchitectureName << ")"; - outs() << ":\n"; + if (!NoLeadingHeaders) { + outs() << Name; + if (!ArchiveMemberName.empty()) + outs() << '(' << ArchiveMemberName << ')'; + if (!ArchitectureName.empty()) + outs() << " (architecture " << ArchitectureName << ")"; + outs() << ":\n"; + } + } + // To use the report_error() form with an ArchiveName and FileName set + // these up based on what is passed for Name and ArchiveMemberName. + StringRef ArchiveName; + StringRef FileName; + if (!ArchiveMemberName.empty()) { + ArchiveName = Name; + FileName = ArchiveMemberName; + } else { + ArchiveName = StringRef(); + FileName = Name; } + // If we need the symbol table to do the operation then check it here to + // produce a good error message as to where the Mach-O file comes from in + // the error message. + if (Disassemble || IndirectSymbols || FilterSections.size() != 0 || + UnwindInfo) + if (Error Err = MachOOF->checkSymbolTable()) + report_error(ArchiveName, FileName, std::move(Err), ArchitectureName); + if (Disassemble) - DisassembleMachO(Filename, MachOOF, "__TEXT", "__text"); + DisassembleMachO(FileName, MachOOF, "__TEXT", "__text"); if (IndirectSymbols) PrintIndirectSymbols(MachOOF, !NonVerbose); if (DataInCode) @@ -1257,17 +1241,15 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, if (SectionContents) PrintSectionContents(MachOOF); if (FilterSections.size() != 0) - DumpSectionContents(Filename, MachOOF, !NonVerbose); + DumpSectionContents(FileName, MachOOF, !NonVerbose); if (InfoPlist) - DumpInfoPlistSectionContents(Filename, MachOOF); + DumpInfoPlistSectionContents(FileName, MachOOF); if (DylibsUsed) PrintDylibs(MachOOF, false); if (DylibId) PrintDylibs(MachOOF, true); - if (SymbolTable) { - StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename; + if (SymbolTable) PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName); - } if (UnwindInfo) printMachOUnwindInfo(MachOOF); if (PrivateHeaders) { @@ -1441,7 +1423,7 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, } } if (verbose) { - outs() << OFA.getArchTypeName() << "\n"; + outs() << OFA.getArchFlagName() << "\n"; printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK); } else { outs() << i << "\n"; @@ -1472,11 +1454,15 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB, } } -static void printArchiveChild(const Archive::Child &C, bool verbose, - bool print_offset) { +static void printArchiveChild(StringRef Filename, const Archive::Child &C, + bool verbose, bool print_offset, + StringRef ArchitectureName = StringRef()) { if (print_offset) outs() << C.getChildOffset() << "\t"; - sys::fs::perms Mode = C.getAccessMode(); + Expected<sys::fs::perms> ModeOrErr = C.getAccessMode(); + if (!ModeOrErr) + report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName); + sys::fs::perms Mode = ModeOrErr.get(); if (verbose) { // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG. // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG. @@ -1494,20 +1480,27 @@ static void printArchiveChild(const Archive::Child &C, bool verbose, outs() << format("0%o ", Mode); } - unsigned UID = C.getUID(); + Expected<unsigned> UIDOrErr = C.getUID(); + if (!UIDOrErr) + report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName); + unsigned UID = UIDOrErr.get(); outs() << format("%3d/", UID); - unsigned GID = C.getGID(); + Expected<unsigned> GIDOrErr = C.getGID(); + if (!GIDOrErr) + report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName); + unsigned GID = GIDOrErr.get(); outs() << format("%-3d ", GID); - ErrorOr<uint64_t> Size = C.getRawSize(); - if (std::error_code EC = Size.getError()) - report_fatal_error(EC.message()); + Expected<uint64_t> Size = C.getRawSize(); + if (!Size) + report_error(Filename, C, Size.takeError(), ArchitectureName); outs() << format("%5" PRId64, Size.get()) << " "; StringRef RawLastModified = C.getRawLastModified(); if (verbose) { unsigned Seconds; if (RawLastModified.getAsInteger(10, Seconds)) - outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified; + outs() << "(date: \"" << RawLastModified + << "\" contains non-decimal chars) "; else { // Since cime(3) returns a 26 character string of the form: // "Sun Sep 16 01:03:52 1973\n\0" @@ -1520,26 +1513,37 @@ static void printArchiveChild(const Archive::Child &C, bool verbose, } if (verbose) { - ErrorOr<StringRef> NameOrErr = C.getName(); - if (NameOrErr.getError()) { - StringRef RawName = C.getRawName(); + Expected<StringRef> NameOrErr = C.getName(); + if (!NameOrErr) { + consumeError(NameOrErr.takeError()); + Expected<StringRef> NameOrErr = C.getRawName(); + if (!NameOrErr) + report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); + StringRef RawName = NameOrErr.get(); outs() << RawName << "\n"; } else { StringRef Name = NameOrErr.get(); outs() << Name << "\n"; } } else { - StringRef RawName = C.getRawName(); + Expected<StringRef> NameOrErr = C.getRawName(); + if (!NameOrErr) + report_error(Filename, C, NameOrErr.takeError(), ArchitectureName); + StringRef RawName = NameOrErr.get(); outs() << RawName << "\n"; } } -static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) { - Error Err; +static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose, + bool print_offset, + StringRef ArchitectureName = StringRef()) { + Error Err = Error::success(); + ; for (const auto &C : A->children(Err, false)) - printArchiveChild(C, verbose, print_offset); + printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName); + if (Err) - report_fatal_error(std::move(Err)); + report_error(StringRef(), Filename, std::move(Err), ArchitectureName); } // ParseInputMachO() parses the named Mach-O file in Filename and handles the @@ -1569,8 +1573,9 @@ void llvm::ParseInputMachO(StringRef Filename) { if (Archive *A = dyn_cast<Archive>(&Bin)) { outs() << "Archive : " << Filename << "\n"; if (ArchiveHeaders) - printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets); - Error Err; + printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets); + + Error Err = Error::success(); for (auto &C : A->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); if (!ChildOrErr) { @@ -1602,13 +1607,13 @@ void llvm::ParseInputMachO(StringRef Filename) { for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), E = UB->end_objects(); I != E; ++I) { - if (ArchFlags[i] == I->getArchTypeName()) { + if (ArchFlags[i] == I->getArchFlagName()) { ArchFound = true; Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); std::string ArchitectureName = ""; if (ArchFlags.size() > 1) - ArchitectureName = I->getArchTypeName(); + ArchitectureName = I->getArchFlagName(); if (ObjOrErr) { ObjectFile &O = *ObjOrErr.get(); if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O)) @@ -1626,8 +1631,9 @@ void llvm::ParseInputMachO(StringRef Filename) { outs() << " (architecture " << ArchitectureName << ")"; outs() << "\n"; if (ArchiveHeaders) - printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); - Error Err; + printArchiveHeaders(Filename, A.get(), !NonVerbose, + ArchiveMemberOffsets, ArchitectureName); + Error Err = Error::success(); for (auto &C : A->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); if (!ChildOrErr) { @@ -1644,7 +1650,7 @@ void llvm::ParseInputMachO(StringRef Filename) { } else { consumeError(AOrErr.takeError()); error("Mach-O universal file: " + Filename + " for " + - "architecture " + StringRef(I->getArchTypeName()) + + "architecture " + StringRef(I->getArchFlagName()) + " is not a Mach-O file or an archive file"); } } @@ -1664,7 +1670,7 @@ void llvm::ParseInputMachO(StringRef Filename) { E = UB->end_objects(); I != E; ++I) { if (MachOObjectFile::getHostArch().getArchName() == - I->getArchTypeName()) { + I->getArchFlagName()) { Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); std::string ArchiveName; ArchiveName.clear(); @@ -1681,8 +1687,9 @@ void llvm::ParseInputMachO(StringRef Filename) { std::unique_ptr<Archive> &A = *AOrErr; outs() << "Archive : " << Filename << "\n"; if (ArchiveHeaders) - printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); - Error Err; + printArchiveHeaders(Filename, A.get(), !NonVerbose, + ArchiveMemberOffsets); + Error Err = Error::success(); for (auto &C : A->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); if (!ChildOrErr) { @@ -1699,7 +1706,7 @@ void llvm::ParseInputMachO(StringRef Filename) { } else { consumeError(AOrErr.takeError()); error("Mach-O universal file: " + Filename + " for architecture " + - StringRef(I->getArchTypeName()) + + StringRef(I->getArchFlagName()) + " is not a Mach-O file or an archive file"); } return; @@ -1715,7 +1722,7 @@ void llvm::ParseInputMachO(StringRef Filename) { Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); std::string ArchitectureName = ""; if (moreThanOneArch) - ArchitectureName = I->getArchTypeName(); + ArchitectureName = I->getArchFlagName(); if (ObjOrErr) { ObjectFile &Obj = *ObjOrErr.get(); if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj)) @@ -1732,8 +1739,9 @@ void llvm::ParseInputMachO(StringRef Filename) { outs() << " (architecture " << ArchitectureName << ")"; outs() << "\n"; if (ArchiveHeaders) - printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); - Error Err; + printArchiveHeaders(Filename, A.get(), !NonVerbose, + ArchiveMemberOffsets, ArchitectureName); + Error Err = Error::success(); for (auto &C : A->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); if (!ChildOrErr) { @@ -1753,7 +1761,7 @@ void llvm::ParseInputMachO(StringRef Filename) { } else { consumeError(AOrErr.takeError()); error("Mach-O universal file: " + Filename + " for architecture " + - StringRef(I->getArchTypeName()) + + StringRef(I->getArchFlagName()) + " is not a Mach-O file or an archive file"); } } @@ -1772,10 +1780,6 @@ void llvm::ParseInputMachO(StringRef Filename) { llvm_unreachable("Input object can't be invalid at this point"); } -typedef std::pair<uint64_t, const char *> BindInfoEntry; -typedef std::vector<BindInfoEntry> BindTable; -typedef BindTable::iterator bind_table_iterator; - // The block of info used by the Symbolizer call backs. struct DisassembleInfo { bool verbose; @@ -1789,7 +1793,7 @@ struct DisassembleInfo { char *demangled_name; uint64_t adrp_addr; uint32_t adrp_inst; - BindTable *bindtable; + std::unique_ptr<SymbolAddressMap> bindtable; uint32_t depth; }; @@ -1879,13 +1883,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, } if (reloc_found && isExtern) { Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); op_info->AddSymbol.Present = 1; op_info->AddSymbol.Name = name; @@ -1954,13 +1953,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (info->O->getAnyRelocationPCRel(RE)) op_info->Value -= Pc + Offset + Size; Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); unsigned Type = info->O->getAnyRelocationType(RE); if (Type == MachO::X86_64_RELOC_SUBTRACTOR) { @@ -1976,13 +1970,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum); Symbol = *RelocSymNext; Expected<StringRef> SymNameNext = Symbol.getName(); - if (!SymNameNext) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymNameNext.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymNameNext) + report_error(info->O->getFileName(), SymNameNext.takeError()); name = SymNameNext->data(); } } @@ -2015,11 +2004,10 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, bool r_scattered = false; uint32_t r_value, pair_r_value, r_type, r_length, other_half; auto Reloc = - std::find_if(info->S.relocations().begin(), info->S.relocations().end(), - [&](const RelocationRef &Reloc) { - uint64_t RelocOffset = Reloc.getOffset(); - return RelocOffset == sect_offset; - }); + find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { + uint64_t RelocOffset = Reloc.getOffset(); + return RelocOffset == sect_offset; + }); if (Reloc == info->S.relocations().end()) return 0; @@ -2054,13 +2042,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (isExtern) { Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); op_info->AddSymbol.Present = 1; op_info->AddSymbol.Name = name; @@ -2082,7 +2065,7 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, // If we have a branch that is not an external relocation entry then // return 0 so the code in tryAddingSymbolicOperand() can use the // SymbolLookUp call back with the branch target address to look up the - // symbol and possiblity add an annotation for a symbol stub. + // symbol and possibility add an annotation for a symbol stub. if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 || r_type == MachO::ARM_THUMB_RELOC_BR22)) return 0; @@ -2154,11 +2137,10 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, uint64_t sect_addr = info->S.getAddress(); uint64_t sect_offset = (Pc + Offset) - sect_addr; auto Reloc = - std::find_if(info->S.relocations().begin(), info->S.relocations().end(), - [&](const RelocationRef &Reloc) { - uint64_t RelocOffset = Reloc.getOffset(); - return RelocOffset == sect_offset; - }); + find_if(info->S.relocations(), [&](const RelocationRef &Reloc) { + uint64_t RelocOffset = Reloc.getOffset(); + return RelocOffset == sect_offset; + }); if (Reloc == info->S.relocations().end()) return 0; @@ -2179,13 +2161,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset, if (!info->O->getPlainRelocationExternal(RE)) return 0; Expected<StringRef> SymName = Reloc->getSymbol()->getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); op_info->AddSymbol.Present = 1; op_info->AddSymbol.Name = name; @@ -2314,13 +2291,8 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue, symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); SymbolRef Symbol = *Sym; Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); return name; } @@ -2354,13 +2326,8 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue, symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol); SymbolRef Symbol = *Sym; Expected<StringRef> SymName = Symbol.getName(); - if (!SymName) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymName.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymName) + report_error(info->O->getFileName(), SymName.takeError()); const char *name = SymName->data(); return name; } @@ -2588,13 +2555,8 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S, if (reloc_found && isExtern) { n_value = Symbol.getValue(); Expected<StringRef> NameOrError = Symbol.getName(); - if (!NameOrError) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(NameOrError.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!NameOrError) + report_error(info->O->getFileName(), NameOrError.takeError()); StringRef Name = *NameOrError; if (!Name.empty()) { SymbolName = Name.data(); @@ -4391,12 +4353,7 @@ static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info, r = get_pointer_64(p, offset, left, S, info); if (r == nullptr || left < sizeof(struct class_ro64_t)) return false; - memset(&cro, '\0', sizeof(struct class_ro64_t)); - if (left < sizeof(struct class_ro64_t)) { - memcpy(&cro, r, left); - outs() << " (class_ro_t entends past the end of the section)\n"; - } else - memcpy(&cro, r, sizeof(struct class_ro64_t)); + memcpy(&cro, r, sizeof(struct class_ro64_t)); if (info->O->isLittleEndian() != sys::IsLittleEndianHost) swapStruct(cro); outs() << " flags " << format("0x%" PRIx32, cro.flags); @@ -4593,12 +4550,7 @@ static void print_class64_t(uint64_t p, struct DisassembleInfo *info) { r = get_pointer_64(p, offset, left, S, info); if (r == nullptr || left < sizeof(struct class64_t)) return; - memset(&c, '\0', sizeof(struct class64_t)); - if (left < sizeof(struct class64_t)) { - memcpy(&c, r, left); - outs() << " (class_t entends past the end of the section)\n"; - } else - memcpy(&c, r, sizeof(struct class64_t)); + memcpy(&c, r, sizeof(struct class64_t)); if (info->O->isLittleEndian() != sys::IsLittleEndianHost) swapStruct(c); @@ -5355,9 +5307,6 @@ static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) { II = get_section(O, "__DATA", "__objc_imageinfo"); info.S = II; print_image_info64(II, &info); - - if (info.bindtable != nullptr) - delete info.bindtable; } static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) { @@ -6214,11 +6163,9 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue, // Out type and the ReferenceName will also be set which is added as a comment // to the disassembled instruction. // -#if HAVE_CXXABI_H // If the symbol name is a C++ mangled name then the demangled name is // returned through ReferenceName and ReferenceType is set to // LLVMDisassembler_ReferenceType_DeMangled_Name . -#endif // // When this is called to get a symbol name for a branch target then the // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then @@ -6253,21 +6200,18 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo, method_reference(info, ReferenceType, ReferenceName); if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message) *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub; - } else -#if HAVE_CXXABI_H - if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { + } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { if (info->demangled_name != nullptr) free(info->demangled_name); int status; info->demangled_name = - abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); + itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); if (info->demangled_name != nullptr) { *ReferenceName = info->demangled_name; *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; } else *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; } else -#endif *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) { *ReferenceName = @@ -6356,20 +6300,17 @@ static const char *SymbolizerSymbolLookUp(void *DisInfo, GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info); if (*ReferenceName == nullptr) *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; - } -#if HAVE_CXXABI_H - else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { + } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) { if (info->demangled_name != nullptr) free(info->demangled_name); int status; info->demangled_name = - abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status); + itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status); if (info->demangled_name != nullptr) { *ReferenceName = info->demangled_name; *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; } } -#endif else { *ReferenceName = nullptr; *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; @@ -6387,7 +6328,7 @@ static void emitComments(raw_svector_ostream &CommentStream, // Flush the stream before taking its content. StringRef Comments = CommentsToEmit.str(); // Get the default information for printing a comment. - const char *CommentBegin = MAI.getCommentString(); + StringRef CommentBegin = MAI.getCommentString(); unsigned CommentColumn = MAI.getCommentColumn(); bool IsFirst = true; while (!Comments.empty()) { @@ -6604,25 +6545,15 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, bool DisSymNameFound = false; for (const SymbolRef &Symbol : MachOOF->symbols()) { Expected<SymbolRef::Type> STOrErr = Symbol.getType(); - if (!STOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(STOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!STOrErr) + report_error(MachOOF->getFileName(), STOrErr.takeError()); SymbolRef::Type ST = *STOrErr; if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data || ST == SymbolRef::ST_Other) { uint64_t Address = Symbol.getValue(); Expected<StringRef> SymNameOrErr = Symbol.getName(); - if (!SymNameOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymNameOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymNameOrErr) + report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); StringRef SymName = *SymNameOrErr; AddrMap[Address] = SymName; if (!DisSymName.empty() && DisSymName == SymName) @@ -6669,23 +6600,13 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, // Disassemble symbol by symbol. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName(); - if (!SymNameOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SymNameOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SymNameOrErr) + report_error(MachOOF->getFileName(), SymNameOrErr.takeError()); StringRef SymName = *SymNameOrErr; Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType(); - if (!STOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(STOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!STOrErr) + report_error(MachOOF->getFileName(), STOrErr.takeError()); SymbolRef::Type ST = *STOrErr; if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data) continue; @@ -6740,13 +6661,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, uint64_t NextSymIdx = SymIdx + 1; while (Symbols.size() > NextSymIdx) { Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType(); - if (!STOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(STOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!STOrErr) + report_error(MachOOF->getFileName(), STOrErr.takeError()); SymbolRef::Type NextSymType = *STOrErr; if (NextSymType == SymbolRef::ST_Function) { containsNextSym = @@ -6918,14 +6834,10 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, free(SymbolizerInfo.method); if (SymbolizerInfo.demangled_name != nullptr) free(SymbolizerInfo.demangled_name); - if (SymbolizerInfo.bindtable != nullptr) - delete SymbolizerInfo.bindtable; if (ThumbSymbolizerInfo.method != nullptr) free(ThumbSymbolizerInfo.method); if (ThumbSymbolizerInfo.demangled_name != nullptr) free(ThumbSymbolizerInfo.demangled_name); - if (ThumbSymbolizerInfo.bindtable != nullptr) - delete ThumbSymbolizerInfo.bindtable; } } @@ -6992,13 +6904,8 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, StringRef &Name, uint64_t &Addend) { if (Reloc.getSymbol() != Obj->symbol_end()) { Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName(); - if (!NameOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(NameOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!NameOrErr) + report_error(Obj->getFileName(), NameOrErr.takeError()); Name = *NameOrErr; Addend = Addr; return; @@ -7022,24 +6929,14 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj, --Sym; auto SectOrErr = Sym->second.getSection(); - if (!SectOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(SectOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!SectOrErr) + report_error(Obj->getFileName(), SectOrErr.takeError()); section_iterator SymSection = *SectOrErr; if (RelocSection == *SymSection) { // There's a valid symbol in the same section before this reference. Expected<StringRef> NameOrErr = Sym->second.getName(); - if (!NameOrErr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(NameOrErr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!NameOrErr) + report_error(Obj->getFileName(), NameOrErr.takeError()); Name = *NameOrErr; Addend = Addr - Sym->first; return; @@ -7072,8 +6969,10 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj, std::map<uint64_t, SymbolRef> &Symbols, const SectionRef &CompactUnwind) { - assert(Obj->isLittleEndian() && - "There should not be a big-endian .o with __compact_unwind"); + if (!Obj->isLittleEndian()) { + outs() << "Skipping big-endian __compact_unwind section\n"; + return; + } bool Is64 = Obj->is64Bit(); uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t); @@ -7105,8 +7004,10 @@ printMachOCompactUnwindSection(const MachOObjectFile *Obj, Entry.PersonalityReloc = Reloc; else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t)) Entry.LSDAReloc = Reloc; - else - llvm_unreachable("Unexpected relocation in __compact_unwind section"); + else { + outs() << "Invalid relocation in __compact_unwind section\n"; + return; + } } // Finally, we're ready to print the data we've gathered. @@ -7212,8 +7113,10 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, std::map<uint64_t, SymbolRef> &Symbols, const SectionRef &UnwindInfo) { - assert(Obj->isLittleEndian() && - "There should not be a big-endian .o with __unwind_info"); + if (!Obj->isLittleEndian()) { + outs() << "Skipping big-endian __unwind_info section\n"; + return; + } outs() << "Contents of __unwind_info section:\n"; @@ -7228,7 +7131,10 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, uint32_t Version = readNext<uint32_t>(Pos); outs() << " Version: " << format("0x%" PRIx32, Version) << '\n'; - assert(Version == 1 && "only understand version 1"); + if (Version != 1) { + outs() << " Skipping section with unknown version\n"; + return; + } uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos); outs() << " Common encodings array section offset: " @@ -7368,7 +7274,8 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset, CommonEncodings); else - llvm_unreachable("Do not know how to print this kind of 2nd level page"); + outs() << " Skipping 2nd level page with unknown kind " << Kind + << '\n'; } } @@ -7735,9 +7642,9 @@ static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize, if ((initprot & ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE)) != 0) - outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; + outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n"; else { - outs() << " initprot "; + outs() << " initprot "; outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-"); outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-"); outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n"); @@ -8630,6 +8537,63 @@ static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) { outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n"; } +static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) { + outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]); + outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]); + outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]); + outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n"; + outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]); + outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]); + outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]); + outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n"; + outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]); + outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]); + outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]); + outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n"; + outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]); + outs() << " sp " << format("0x%08" PRIx32, cpu32.sp); + outs() << " lr " << format("0x%08" PRIx32, cpu32.lr); + outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n"; + outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n"; +} + +static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) { + outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]); + outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]); + outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n"; + outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]); + outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]); + outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n"; + outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]); + outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]); + outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n"; + outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]); + outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]); + outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n"; + outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]); + outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]); + outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n"; + outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]); + outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]); + outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n"; + outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]); + outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]); + outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n"; + outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]); + outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]); + outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n"; + outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]); + outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]); + outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n"; + outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]); + outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]); + outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n"; + outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr); + outs() << " sp " << format("0x%016" PRIx64, cpu64.sp); + outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n"; + outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n"; +} + static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, bool isLittleEndian, uint32_t cputype) { if (t.cmd == MachO::LC_THREAD) @@ -8786,6 +8750,100 @@ static void PrintThreadCommand(MachO::thread_command t, const char *Ptr, begin += count * sizeof(uint32_t); } } + } else if (cputype == MachO::CPU_TYPE_ARM) { + while (begin < end) { + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&flavor, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + flavor = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(flavor); + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&count, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + count = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(count); + if (flavor == MachO::ARM_THREAD_STATE) { + outs() << " flavor ARM_THREAD_STATE\n"; + if (count == MachO::ARM_THREAD_STATE_COUNT) + outs() << " count ARM_THREAD_STATE_COUNT\n"; + else + outs() << " count " << count + << " (not ARM_THREAD_STATE_COUNT)\n"; + MachO::arm_thread_state32_t cpu32; + left = end - begin; + if (left >= sizeof(MachO::arm_thread_state32_t)) { + memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t)); + begin += sizeof(MachO::arm_thread_state32_t); + } else { + memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t)); + memcpy(&cpu32, begin, left); + begin += left; + } + if (isLittleEndian != sys::IsLittleEndianHost) + swapStruct(cpu32); + Print_arm_thread_state32_t(cpu32); + } else { + outs() << " flavor " << flavor << " (unknown)\n"; + outs() << " count " << count << "\n"; + outs() << " state (unknown)\n"; + begin += count * sizeof(uint32_t); + } + } + } else if (cputype == MachO::CPU_TYPE_ARM64) { + while (begin < end) { + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&flavor, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + flavor = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(flavor); + if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { + memcpy((char *)&count, begin, sizeof(uint32_t)); + begin += sizeof(uint32_t); + } else { + count = 0; + begin = end; + } + if (isLittleEndian != sys::IsLittleEndianHost) + sys::swapByteOrder(count); + if (flavor == MachO::ARM_THREAD_STATE64) { + outs() << " flavor ARM_THREAD_STATE64\n"; + if (count == MachO::ARM_THREAD_STATE64_COUNT) + outs() << " count ARM_THREAD_STATE64_COUNT\n"; + else + outs() << " count " << count + << " (not ARM_THREAD_STATE64_COUNT)\n"; + MachO::arm_thread_state64_t cpu64; + left = end - begin; + if (left >= sizeof(MachO::arm_thread_state64_t)) { + memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t)); + begin += sizeof(MachO::arm_thread_state64_t); + } else { + memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t)); + memcpy(&cpu64, begin, left); + begin += left; + } + if (isLittleEndian != sys::IsLittleEndianHost) + swapStruct(cpu64); + Print_arm_thread_state64_t(cpu64); + } else { + outs() << " flavor " << flavor << " (unknown)\n"; + outs() << " count " << count << "\n"; + outs() << " state (unknown)\n"; + begin += count * sizeof(uint32_t); + } + } } else { while (begin < end) { if (end - begin > (ptrdiff_t)sizeof(uint32_t)) { @@ -9358,7 +9416,7 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) { static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, struct DisassembleInfo *info) { if (info->bindtable == nullptr) { - info->bindtable = new (BindTable); + info->bindtable = llvm::make_unique<SymbolAddressMap>(); SegInfo sectionTable(info->O); for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) { uint32_t SegIndex = Entry.segmentIndex(); @@ -9366,21 +9424,11 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue, if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) continue; uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg); - const char *SymbolName = nullptr; StringRef name = Entry.symbolName(); if (!name.empty()) - SymbolName = name.data(); - info->bindtable->push_back(std::make_pair(Address, SymbolName)); + (*info->bindtable)[Address] = name; } } - for (bind_table_iterator BI = info->bindtable->begin(), - BE = info->bindtable->end(); - BI != BE; ++BI) { - uint64_t Address = BI->first; - if (ReferenceValue == Address) { - const char *SymbolName = BI->second; - return SymbolName; - } - } - return nullptr; + auto name = info->bindtable->lookup(ReferenceValue); + return !name.empty() ? name.data() : nullptr; } diff --git a/contrib/llvm/tools/llvm-objdump/WasmDump.cpp b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp new file mode 100644 index 0000000..0d8ffba --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/WasmDump.cpp @@ -0,0 +1,28 @@ +//===-- WasmDump.cpp - wasm-specific dumper ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements the wasm-specific dumper for llvm-objdump. +/// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" +#include "llvm/Object/Wasm.h" + +using namespace llvm; +using namespace object; + +void llvm::printWasmFileHeader(const object::ObjectFile *Obj) { + const WasmObjectFile *File = dyn_cast<const WasmObjectFile>(Obj); + + outs() << "Program Header:\n"; + outs() << "Version: 0x"; + outs().write_hex(File->getHeader().Version); + outs() << "\n"; +} diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp index ed55c91..8373f0c 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/FaultMaps.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" @@ -36,6 +37,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" @@ -60,6 +62,7 @@ #include <cstring> #include <system_error> #include <utility> +#include <unordered_map> using namespace llvm; using namespace object; @@ -185,9 +188,29 @@ cl::opt<bool> PrintFaultMaps("fault-map-section", cl::opt<DIDumpType> llvm::DwarfDumpType( "dwarf", cl::init(DIDT_Null), cl::desc("Dump of dwarf debug sections:"), - cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"), - clEnumValEnd)); + cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"))); +cl::opt<bool> PrintSource( + "source", + cl::desc( + "Display source inlined with disassembly. Implies disassmble object")); + +cl::alias PrintSourceShort("S", cl::desc("Alias for -source"), + cl::aliasopt(PrintSource)); + +cl::opt<bool> PrintLines("line-numbers", + cl::desc("Display source line numbers with " + "disassembly. Implies disassemble object")); + +cl::alias PrintLinesShort("l", cl::desc("Alias for -line-numbers"), + cl::aliasopt(PrintLines)); + +cl::opt<unsigned long long> + StartAddress("start-address", cl::desc("Disassemble beginning at address"), + cl::value_desc("address"), cl::init(0)); +cl::opt<unsigned long long> + StopAddress("stop-address", cl::desc("Stop disassembly at address"), + cl::value_desc("address"), cl::init(UINT64_MAX)); static StringRef ToolName; namespace { @@ -240,18 +263,17 @@ private: 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); + 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 is_contained(FilterSections, String); + }, + O); } } @@ -271,6 +293,12 @@ LLVM_ATTRIBUTE_NORETURN void llvm::error(Twine Message) { } LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, + Twine Message) { + errs() << ToolName << ": '" << File << "': " << Message << ".\n"; + exit(1); +} + +LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, std::error_code EC) { assert(EC); errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n"; @@ -297,14 +325,14 @@ LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName, if (ArchiveName != "") errs() << ArchiveName << "(" << FileName << ")"; else - errs() << FileName; + errs() << "'" << FileName << "'"; if (!ArchitectureName.empty()) errs() << " (for architecture " << ArchitectureName << ")"; std::string Buf; raw_string_ostream OS(Buf); logAllUnhandledErrors(std::move(E), OS, ""); OS.flush(); - errs() << " " << Buf; + errs() << ": " << Buf; exit(1); } @@ -312,13 +340,14 @@ LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef ArchiveName, const object::Archive::Child &C, llvm::Error E, StringRef ArchitectureName) { - ErrorOr<StringRef> NameOrErr = C.getName(); + Expected<StringRef> NameOrErr = C.getName(); // TODO: if we have a error getting the name then it would be nice to print // the index of which archive member this is and or its offset in the // archive instead of "???" as the name. - if (NameOrErr.getError()) + if (!NameOrErr) { + consumeError(NameOrErr.takeError()); llvm::report_error(ArchiveName, "???", std::move(E), ArchitectureName); - else + } else llvm::report_error(ArchiveName, NameOrErr.get(), std::move(E), ArchitectureName); } @@ -347,8 +376,12 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple, Error); - if (!TheTarget) - report_fatal_error("can't find target: " + Error); + if (!TheTarget) { + if (Obj) + report_error(Obj->getFileName(), "can't find target: " + Error); + else + error("can't find target: " + Error); + } // Update the triple name and return the found target. TripleName = TheTriple.getTriple(); @@ -360,13 +393,104 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { } namespace { +class SourcePrinter { +protected: + DILineInfo OldLineInfo; + const ObjectFile *Obj; + 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(std::string File); + +public: + virtual ~SourcePrinter() {} + SourcePrinter() : Obj(nullptr), Symbolizer(nullptr) {} + 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 void printSourceLine(raw_ostream &OS, uint64_t Address, + StringRef Delimiter = "; "); +}; + +bool SourcePrinter::cacheSource(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()) + // 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(){} virtual void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes, uint64_t Address, raw_ostream &OS, StringRef Annot, - MCSubtargetInfo const &STI) { + MCSubtargetInfo const &STI, SourcePrinter *SP) { + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address); OS << format("%8" PRIx64 ":", Address); if (!NoShowRawInsn) { OS << "\t"; @@ -392,10 +516,11 @@ public: 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) override { + 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>"; @@ -416,6 +541,8 @@ public: while(!HeadTail.first.empty()) { OS << Separator; Separator = "\n"; + if (SP && (PrintSource || PrintLines)) + SP->printSourceLine(OS, Address, ""); printLead(Bytes, Address, OS); OS << Preamble; Preamble = " "; @@ -440,13 +567,9 @@ 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) override { + 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 (!MI) { OS << " <unknown>"; return; @@ -471,6 +594,26 @@ public: }; 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); + 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: @@ -479,6 +622,9 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { return HexagonPrettyPrinterInst; case Triple::amdgcn: return AMDGCNPrettyPrinterInst; + case Triple::bpfel: + case Triple::bpfeb: + return BPFPrettyPrinterInst; } } } @@ -495,22 +641,22 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, const ELFFile<ELFT> &EF = *Obj->getELFFile(); - ErrorOr<const Elf_Shdr *> SecOrErr = EF.getSection(Rel.d.a); - if (std::error_code EC = SecOrErr.getError()) - return EC; + auto SecOrErr = EF.getSection(Rel.d.a); + if (!SecOrErr) + return errorToErrorCode(SecOrErr.takeError()); const Elf_Shdr *Sec = *SecOrErr; - ErrorOr<const Elf_Shdr *> SymTabOrErr = EF.getSection(Sec->sh_link); - if (std::error_code EC = SymTabOrErr.getError()) - return EC; + auto SymTabOrErr = EF.getSection(Sec->sh_link); + if (!SymTabOrErr) + return errorToErrorCode(SymTabOrErr.takeError()); const Elf_Shdr *SymTab = *SymTabOrErr; assert(SymTab->sh_type == ELF::SHT_SYMTAB || SymTab->sh_type == ELF::SHT_DYNSYM); - ErrorOr<const Elf_Shdr *> StrTabSec = EF.getSection(SymTab->sh_link); - if (std::error_code EC = StrTabSec.getError()) - return EC; - ErrorOr<StringRef> StrTabOrErr = EF.getStringTable(*StrTabSec); - if (std::error_code EC = StrTabOrErr.getError()) - return EC; + auto StrTabSec = EF.getSection(SymTab->sh_link); + if (!StrTabSec) + return errorToErrorCode(StrTabSec.takeError()); + auto StrTabOrErr = EF.getStringTable(*StrTabSec); + if (!StrTabOrErr) + return errorToErrorCode(StrTabOrErr.takeError()); StringRef StrTab = *StrTabOrErr; uint8_t type = RelRef.getType(); StringRef res; @@ -536,9 +682,9 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, if (!SymSI) return errorToErrorCode(SymSI.takeError()); const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); - ErrorOr<StringRef> SecName = EF.getSectionName(SymSec); - if (std::error_code EC = SecName.getError()) - return EC; + auto SecName = EF.getSectionName(SymSec); + if (!SecName) + return errorToErrorCode(SecName.takeError()); Target = *SecName; } else { Expected<StringRef> SymName = symb->getName(StrTab); @@ -574,6 +720,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, } break; case ELF::EM_LANAI: + case ELF::EM_AVR: case ELF::EM_AARCH64: { std::string fmtbuf; raw_string_ostream fmt(fmtbuf); @@ -590,6 +737,7 @@ static std::error_code getRelocationValueString(const ELFObjectFile<ELFT> *Obj, case ELF::EM_HEXAGON: case ELF::EM_MIPS: case ELF::EM_BPF: + case ELF::EM_RISCV: res = Target; break; case ELF::EM_WEBASSEMBLY: @@ -657,23 +805,13 @@ static void printRelocationTargetName(const MachOObjectFile *O, for (const SymbolRef &Symbol : O->symbols()) { std::error_code ec; Expected<uint64_t> Addr = Symbol.getAddress(); - if (!Addr) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(Addr.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!Addr) + report_error(O->getFileName(), Addr.takeError()); if (*Addr != Val) continue; Expected<StringRef> Name = Symbol.getName(); - if (!Name) { - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(Name.takeError(), OS, ""); - OS.flush(); - report_fatal_error(Buf); - } + if (!Name) + report_error(O->getFileName(), Name.takeError()); fmt << *Name; return; } @@ -688,7 +826,7 @@ static void printRelocationTargetName(const MachOObjectFile *O, if (Addr != Val) continue; if ((ec = Section.getName(Name))) - report_fatal_error(ec.message()); + report_error(O->getFileName(), ec); fmt << Name; return; } @@ -705,7 +843,8 @@ static void printRelocationTargetName(const MachOObjectFile *O, symbol_iterator SI = O->symbol_begin(); advance(SI, Val); Expected<StringRef> SOrErr = SI->getName(); - error(errorToErrorCode(SOrErr.takeError())); + if (!SOrErr) + report_error(O->getFileName(), SOrErr.takeError()); S = *SOrErr; } else { section_iterator SI = O->section_begin(); @@ -756,8 +895,8 @@ static std::error_code getRelocationValueString(const MachOObjectFile *Obj, // NOTE: Scattered relocations don't exist on x86_64. unsigned RType = Obj->getAnyRelocationType(RENext); if (RType != MachO::X86_64_RELOC_UNSIGNED) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); + report_error(Obj->getFileName(), "Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); // The X86_64_RELOC_UNSIGNED contains the minuend symbol; // X86_64_RELOC_SUBTRACTOR contains the subtrahend. @@ -805,8 +944,8 @@ static std::error_code getRelocationValueString(const MachOObjectFile *Obj, unsigned RType = Obj->getAnyRelocationType(RENext); if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); + report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); printRelocationTargetName(Obj, RE, fmt); fmt << "-"; @@ -826,8 +965,8 @@ static std::error_code getRelocationValueString(const MachOObjectFile *Obj, // GENERIC_RELOC_PAIR. unsigned RType = Obj->getAnyRelocationType(RENext); if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); + report_error(Obj->getFileName(), "Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); printRelocationTargetName(Obj, RE, fmt); fmt << "-"; @@ -866,8 +1005,8 @@ static std::error_code getRelocationValueString(const MachOObjectFile *Obj, // ARM_RELOC_PAIR. unsigned RType = Obj->getAnyRelocationType(RENext); if (RType != MachO::ARM_RELOC_PAIR) - report_fatal_error("Expected ARM_RELOC_PAIR after " - "ARM_RELOC_HALF"); + report_error(Obj->getFileName(), "Expected ARM_RELOC_PAIR after " + "ARM_RELOC_HALF"); // NOTE: The half of the target virtual address is stashed in the // address field of the secondary relocation, but we can't reverse @@ -939,7 +1078,23 @@ static bool getHidden(RelocationRef RelRef) { return false; } +static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) { + assert(Obj->isELF()); + if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj)) + return Elf32LEObj->getSymbol(Sym.getRawDataRefImpl())->getType(); + if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return Elf64LEObj->getSymbol(Sym.getRawDataRefImpl())->getType(); + if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj)) + return Elf32BEObj->getSymbol(Sym.getRawDataRefImpl())->getType(); + if (auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj)) + return Elf64BEObj->getSymbol(Sym.getRawDataRefImpl())->getType(); + llvm_unreachable("Unsupported binary format"); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { + if (StartAddress > StopAddress) + error("Start address should be less than stop address"); + const Target *TheTarget = getTarget(Obj); // Package up features to be passed to target/subtarget @@ -952,27 +1107,34 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::unique_ptr<const MCRegisterInfo> MRI( TheTarget->createMCRegInfo(TripleName)); if (!MRI) - report_fatal_error("error: no register info for target " + TripleName); + report_error(Obj->getFileName(), "no register info for target " + + TripleName); // Set up disassembler. std::unique_ptr<const MCAsmInfo> AsmInfo( TheTarget->createMCAsmInfo(*MRI, TripleName)); if (!AsmInfo) - report_fatal_error("error: no assembly info for target " + TripleName); + report_error(Obj->getFileName(), "no assembly info for target " + + TripleName); std::unique_ptr<const MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); if (!STI) - report_fatal_error("error: no subtarget info for target " + TripleName); + report_error(Obj->getFileName(), "no subtarget info for target " + + TripleName); std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); 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()); + report_error(Obj->getFileName(), "no instruction info for target " + + TripleName); + MCObjectFileInfo MOFI; + MCContext Ctx(AsmInfo.get(), MRI.get(), &MOFI); + // FIXME: for now initialize MCObjectFileInfo with default values + MOFI.InitMCObjectFileInfo(Triple(TripleName), false, CodeModel::Default, Ctx); std::unique_ptr<MCDisassembler> DisAsm( TheTarget->createMCDisassembler(*STI, Ctx)); if (!DisAsm) - report_fatal_error("error: no disassembler for target " + TripleName); + report_error(Obj->getFileName(), "no disassembler for target " + + TripleName); std::unique_ptr<const MCInstrAnalysis> MIA( TheTarget->createMCInstrAnalysis(MII.get())); @@ -981,14 +1143,16 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI)); if (!IP) - report_fatal_error("error: no instruction printer for target " + - TripleName); + report_error(Obj->getFileName(), "no instruction printer for target " + + TripleName); IP->setPrintImmHex(PrintImmHex); PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; + SourcePrinter SP(Obj, TheTarget->getName()); + // Create a mapping, RelocSecs = SectionRelocMap[S], where sections // in RelocSecs contain the relocations for section S. std::error_code EC; @@ -1001,25 +1165,33 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Create a mapping from virtual address to symbol name. This is used to // pretty print the symbols while disassembling. - typedef std::vector<std::pair<uint64_t, StringRef>> SectionSymbolsTy; + typedef std::vector<std::tuple<uint64_t, StringRef, uint8_t>> SectionSymbolsTy; std::map<SectionRef, SectionSymbolsTy> AllSymbols; for (const SymbolRef &Symbol : Obj->symbols()) { Expected<uint64_t> AddressOrErr = Symbol.getAddress(); - error(errorToErrorCode(AddressOrErr.takeError())); + if (!AddressOrErr) + report_error(Obj->getFileName(), AddressOrErr.takeError()); uint64_t Address = *AddressOrErr; Expected<StringRef> Name = Symbol.getName(); - error(errorToErrorCode(Name.takeError())); + if (!Name) + report_error(Obj->getFileName(), Name.takeError()); if (Name->empty()) continue; Expected<section_iterator> SectionOrErr = Symbol.getSection(); - error(errorToErrorCode(SectionOrErr.takeError())); + if (!SectionOrErr) + report_error(Obj->getFileName(), SectionOrErr.takeError()); section_iterator SecI = *SectionOrErr; if (SecI == Obj->section_end()) continue; - AllSymbols[*SecI].emplace_back(Address, *Name); + uint8_t SymbolType = ELF::STT_NOTYPE; + if (Obj->isELF()) + SymbolType = getElfSymbolType(Obj, Symbol); + + AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); + } // Create a mapping from virtual address to section. @@ -1051,7 +1223,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { Sec = SectionAddresses.end(); if (Sec != SectionAddresses.end()) - AllSymbols[Sec->second].emplace_back(VA, Name); + AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE); } } @@ -1073,20 +1245,36 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SectionSymbolsTy &Symbols = AllSymbols[Section]; std::vector<uint64_t> DataMappingSymsAddr; std::vector<uint64_t> TextMappingSymsAddr; - if (Obj->isELF() && Obj->getArch() == Triple::aarch64) { + if (isArmElf(Obj)) { for (const auto &Symb : Symbols) { - uint64_t Address = Symb.first; - StringRef Name = Symb.second; + uint64_t Address = std::get<0>(Symb); + StringRef Name = std::get<1>(Symb); if (Name.startswith("$d")) DataMappingSymsAddr.push_back(Address - SectionAddr); if (Name.startswith("$x")) TextMappingSymsAddr.push_back(Address - SectionAddr); + if (Name.startswith("$a")) + TextMappingSymsAddr.push_back(Address - SectionAddr); + if (Name.startswith("$t")) + TextMappingSymsAddr.push_back(Address - SectionAddr); } } std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end()); std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end()); + if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) { + // AMDGPU disassembler uses symbolizer for printing labels + std::unique_ptr<MCRelocationInfo> RelInfo( + TheTarget->createMCRelocationInfo(TripleName, Ctx)); + if (RelInfo) { + std::unique_ptr<MCSymbolizer> Symbolizer( + TheTarget->createMCSymbolizer( + TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo))); + DisAsm->setSymbolizer(std::move(Symbolizer)); + } + } + // Make a list of all the relocations for this section. std::vector<RelocationRef> Rels; if (InlineRelocs) { @@ -1107,14 +1295,22 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } StringRef name; error(Section.getName(name)); + + if ((SectionAddr <= StopAddress) && + (SectionAddr + SectSize) >= StartAddress) { outs() << "Disassembly of section "; if (!SegmentName.empty()) outs() << SegmentName << ","; outs() << name << ':'; + } // 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(SectionAddr, name)); + 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)); + } SmallString<40> Comments; raw_svector_ostream CommentStream(Comments); @@ -1131,12 +1327,11 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::vector<RelocationRef>::const_iterator rel_end = Rels.end(); // Disassemble symbol by symbol. for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { - - uint64_t Start = Symbols[si].first - SectionAddr; + uint64_t Start = std::get<0>(Symbols[si]) - 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; + (si == se - 1) ? SectSize : std::get<0>(Symbols[si + 1]) - SectionAddr; // Don't try to disassemble beyond the end of section contents. if (End > SectSize) End = SectSize; @@ -1144,19 +1339,37 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (Start >= End) continue; + // Check if we need to skip symbol + // Skip if the symbol's data is not between StartAddress and StopAddress + if (End + SectionAddr < StartAddress || + Start + SectionAddr > StopAddress) { + continue; + } + + // 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); - Start += 256; // add sizeof(amd_kernel_code_t) - // cut trailing zeroes - up to 256 bytes (align) - const uint64_t EndAlign = 256; - const auto Limit = End - (std::min)(EndAlign, End - Start); - while (End > Limit && - *reinterpret_cast<const support::ulittle32_t*>(&Bytes[End - 4]) == 0) - End -= 4; + 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; + } + if (si == se - 1 || + std::get<2>(Symbols[si + 1]) == ELF::STT_AMDGPU_HSA_KERNEL) { + // cut trailing zeroes at the end of kernel + // cut up to 256 bytes + const uint64_t EndAlign = 256; + const auto Limit = End - (std::min)(EndAlign, End - Start); + while (End > Limit && + *reinterpret_cast<const support::ulittle32_t*>(&Bytes[End - 4]) == 0) + End -= 4; + } } - outs() << '\n' << Symbols[si].second << ":\n"; + outs() << '\n' << std::get<1>(Symbols[si]) << ":\n"; #ifndef NDEBUG raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); @@ -1167,10 +1380,18 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { for (Index = Start; Index < End; Index += Size) { MCInst Inst; + if (Index + SectionAddr < StartAddress || + Index + SectionAddr > StopAddress) { + // skip byte by byte till StartAddress is reached + Size = 1; + continue; + } // 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) { + // understand what we need to dump. If the data marker is within a + // function, it is denoted as a word/short etc + if (isArmElf(Obj) && std::get<2>(Symbols[si]) != ELF::STT_OBJECT && + !DisassembleAll) { uint64_t Stride = 0; auto DAI = std::lower_bound(DataMappingSymsAddr.begin(), @@ -1183,15 +1404,41 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (Index + 4 <= End) { Stride = 4; dumpBytes(Bytes.slice(Index, 4), outs()); - outs() << "\t.word"; + outs() << "\t.word\t"; + uint32_t Data = 0; + if (Obj->isLittleEndian()) { + const auto Word = + reinterpret_cast<const support::ulittle32_t *>( + Bytes.data() + Index); + Data = *Word; + } else { + const auto Word = reinterpret_cast<const support::ubig32_t *>( + Bytes.data() + Index); + Data = *Word; + } + outs() << "0x" << format("%08" PRIx32, Data); } else if (Index + 2 <= End) { Stride = 2; dumpBytes(Bytes.slice(Index, 2), outs()); - outs() << "\t.short"; + outs() << "\t\t.short\t"; + uint16_t Data = 0; + if (Obj->isLittleEndian()) { + const auto Short = + reinterpret_cast<const support::ulittle16_t *>( + Bytes.data() + Index); + Data = *Short; + } else { + const auto Short = + reinterpret_cast<const support::ubig16_t *>(Bytes.data() + + Index); + Data = *Short; + } + outs() << "0x" << format("%04" PRIx16, Data); } else { Stride = 1; dumpBytes(Bytes.slice(Index, 1), outs()); - outs() << "\t.byte"; + outs() << "\t\t.byte\t"; + outs() << "0x" << format("%02" PRIx8, Bytes.slice(Index, 1)[0]); } Index += Stride; outs() << "\n"; @@ -1203,17 +1450,62 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } } + // If there is a data symbol inside an ELF text section and we are only + // disassembling text (applicable all architectures), + // we are in a situation where we must print the data and not + // disassemble it. + if (Obj->isELF() && std::get<2>(Symbols[si]) == ELF::STT_OBJECT && + !DisassembleAll && Section.isText()) { + // print out data up to 8 bytes at a time in hex and ascii + uint8_t AsciiData[9] = {'\0'}; + uint8_t Byte; + int NumBytes = 0; + + for (Index = Start; Index < End; Index += 1) { + if (((SectionAddr + Index) < StartAddress) || + ((SectionAddr + Index) > StopAddress)) + continue; + if (NumBytes == 0) { + outs() << format("%8" PRIx64 ":", SectionAddr + Index); + outs() << "\t"; + } + Byte = Bytes.slice(Index)[0]; + outs() << format(" %02x", Byte); + AsciiData[NumBytes] = isprint(Byte) ? Byte : '.'; + + uint8_t IndentOffset = 0; + NumBytes++; + if (Index == End - 1 || NumBytes > 8) { + // Indent the space for less than 8 bytes data. + // 2 spaces for byte and one for space between bytes + IndentOffset = 3 * (8 - NumBytes); + for (int Excess = 8 - NumBytes; Excess < 8; Excess++) + AsciiData[Excess] = '\0'; + NumBytes = 8; + } + if (NumBytes == 8) { + AsciiData[8] = '\0'; + outs() << std::string(IndentOffset, ' ') << " "; + outs() << reinterpret_cast<char *>(AsciiData); + outs() << '\n'; + NumBytes = 0; + } + } + } if (Index >= End) break; + // Disassemble a real instruction or a data when disassemble all is + // provided bool Disassembled = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), SectionAddr + Index, DebugOut, CommentStream); if (Size == 0) Size = 1; + PIP.printInst(*IP, Disassembled ? &Inst : nullptr, - Bytes.slice(Index, Size), - SectionAddr + Index, outs(), "", *STI); + Bytes.slice(Index, Size), SectionAddr + Index, outs(), "", + *STI, &SP); outs() << CommentStream.str(); Comments.clear(); @@ -1252,8 +1544,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { auto TargetSym = std::upper_bound( TargetSectionSymbols->begin(), TargetSectionSymbols->end(), Target, [](uint64_t LHS, - const std::pair<uint64_t, StringRef> &RHS) { - return LHS < RHS.first; + const std::tuple<uint64_t, StringRef, uint8_t> &RHS) { + return LHS < std::get<0>(RHS); }); if (TargetSym != TargetSectionSymbols->begin()) { --TargetSym; @@ -1278,7 +1570,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SmallString<32> val; // If this relocation is hidden, skip it. - if (hidden) goto skip_print_rel; + if (hidden || ((SectionAddr + addr) < StartAddress)) { + ++rel_cur; + continue; + } // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; @@ -1286,8 +1581,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { error(getRelocationValueString(*rel_cur, val)); outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; - - skip_print_rel: ++rel_cur; } } @@ -1314,7 +1607,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { uint64_t address = Reloc.getOffset(); SmallString<32> relocname; SmallString<32> valuestr; - if (hidden) + if (address < StartAddress || address > StopAddress || hidden) continue; Reloc.getTypeName(relocname); error(getRelocationValueString(Reloc, valuestr)); @@ -1403,15 +1696,21 @@ void llvm::PrintSymbolTable(const ObjectFile *o, StringRef ArchiveName, for (const SymbolRef &Symbol : o->symbols()) { Expected<uint64_t> AddressOrError = Symbol.getAddress(); if (!AddressOrError) - report_error(ArchiveName, o->getFileName(), AddressOrError.takeError()); + report_error(ArchiveName, o->getFileName(), AddressOrError.takeError(), + ArchitectureName); uint64_t Address = *AddressOrError; + if ((Address < StartAddress) || (Address > StopAddress)) + continue; Expected<SymbolRef::Type> TypeOrError = Symbol.getType(); if (!TypeOrError) - report_error(ArchiveName, o->getFileName(), TypeOrError.takeError()); + report_error(ArchiveName, o->getFileName(), TypeOrError.takeError(), + ArchitectureName); SymbolRef::Type Type = *TypeOrError; uint32_t Flags = Symbol.getFlags(); Expected<section_iterator> SectionOrErr = Symbol.getSection(); - error(errorToErrorCode(SectionOrErr.takeError())); + if (!SectionOrErr) + report_error(ArchiveName, o->getFileName(), SectionOrErr.takeError(), + ArchitectureName); section_iterator Section = *SectionOrErr; StringRef Name; if (Type == SymbolRef::ST_Debug && Section != o->section_end()) { @@ -1629,27 +1928,20 @@ static void printFaultMaps(const ObjectFile *Obj) { outs() << FMP; } -static void printPrivateFileHeaders(const ObjectFile *o) { - if (o->isELF()) - printELFFileHeader(o); - else if (o->isCOFF()) - printCOFFFileHeader(o); - else if (o->isMachO()) { - printMachOFileHeader(o); - printMachOLoadCommands(o); - } else - report_fatal_error("Invalid/Unsupported object file format"); -} - -static void printFirstPrivateFileHeader(const ObjectFile *o) { +static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) { if (o->isELF()) - printELFFileHeader(o); - else if (o->isCOFF()) - printCOFFFileHeader(o); - else if (o->isMachO()) + return printELFFileHeader(o); + if (o->isCOFF()) + return printCOFFFileHeader(o); + if (o->isWasm()) + return printWasmFileHeader(o); + if (o->isMachO()) { printMachOFileHeader(o); - else - report_fatal_error("Invalid/Unsupported object file format"); + if (!onlyFirst) + printMachOLoadCommands(o); + return; + } + report_error(o->getFileName(), "Invalid/Unsupported object file format"); } static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) { @@ -1676,10 +1968,8 @@ static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) { PrintSymbolTable(o, ArchiveName); if (UnwindInfo) PrintUnwindInfo(o); - if (PrivateHeaders) - printPrivateFileHeaders(o); - if (FirstPrivateHeader) - printFirstPrivateFileHeader(o); + if (PrivateHeaders || FirstPrivateHeader) + printPrivateFileHeaders(o, FirstPrivateHeader); if (ExportsTrie) printExportsTrie(o); if (Rebase) @@ -1701,9 +1991,23 @@ static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) { } } +static void DumpObject(const COFFImportFile *I, const Archive *A) { + StringRef ArchiveName = A ? A->getFileName() : ""; + + // Avoid other output when using a raw option. + if (!RawClangAST) + outs() << '\n' + << ArchiveName << "(" << I->getFileName() << ")" + << ":\tfile format COFF-import-file" + << "\n\n"; + + if (SymbolTable) + printCOFFSymbolTable(I); +} + /// @brief Dump each object file in \a a; static void DumpArchive(const Archive *a) { - Error Err; + Error Err = Error::success(); for (auto &C : a->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(); if (!ChildOrErr) { @@ -1713,6 +2017,8 @@ static void DumpArchive(const Archive *a) { } if (ObjectFile *o = dyn_cast<ObjectFile>(&*ChildOrErr.get())) DumpObject(o, a); + else if (COFFImportFile *I = dyn_cast<COFFImportFile>(&*ChildOrErr.get())) + DumpObject(I, a); else report_error(a->getFileName(), object_error::invalid_file_type); } @@ -1768,7 +2074,7 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); - if (DisassembleAll) + if (DisassembleAll || PrintSource || PrintLines) Disassemble = true; if (!Disassemble && !Relocations diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h index 5b10ee8..dace82a 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h @@ -20,6 +20,7 @@ class StringRef; namespace object { class COFFObjectFile; + class COFFImportFile; class MachOObjectFile; class ObjectFile; class Archive; @@ -74,9 +75,11 @@ void printMachOLazyBindTable(const object::MachOObjectFile* o); void printMachOWeakBindTable(const object::MachOObjectFile* o); void printELFFileHeader(const object::ObjectFile *o); void printCOFFFileHeader(const object::ObjectFile *o); +void printCOFFSymbolTable(const object::COFFImportFile *i); void printCOFFSymbolTable(const object::COFFObjectFile *o); void printMachOFileHeader(const object::ObjectFile *o); void printMachOLoadCommands(const object::ObjectFile *o); +void printWasmFileHeader(const object::ObjectFile *o); void printExportsTrie(const object::ObjectFile *o); void printRebaseTable(const object::ObjectFile *o); void printBindTable(const object::ObjectFile *o); @@ -89,6 +92,7 @@ void PrintSectionContents(const object::ObjectFile *o); void PrintSymbolTable(const object::ObjectFile *o, StringRef ArchiveName, StringRef ArchitectureName = StringRef()); 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); LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, llvm::Error E); LLVM_ATTRIBUTE_NORETURN void report_error(StringRef FileName, |