X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-objdump%2Fllvm-objdump.cpp;h=d5ae5de4b5a33390235c65583bbce579d1876a94;hb=f3e6026b5b25b0c6e9a7f7f0df7f4df3dbccc5d9;hp=39eb45a6d85a5ec156ebf4be64c14a0824d83871;hpb=5954faae4d39312566bb926c8678f13018cefdcb;p=oota-llvm.git diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 39eb45a6d85..d5ae5de4b5a 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -72,6 +72,13 @@ static cl::alias Disassembled("d", cl::desc("Alias for --disassemble"), cl::aliasopt(Disassemble)); +cl::opt +llvm::DisassembleAll("disassemble-all", + cl::desc("Display assembler mnemonics for the machine instructions")); +static cl::alias +DisassembleAlld("D", cl::desc("Alias for --disassemble-all"), + cl::aliasopt(DisassembleAll)); + cl::opt llvm::Relocations("r", cl::desc("Display the relocation entries in the file")); @@ -96,6 +103,10 @@ llvm::LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info")); cl::opt llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info")); +cl::opt +llvm::RawClangAST("raw-clang-ast", + cl::desc("Dump the raw binary contents of the clang AST section")); + static cl::opt MachOOpt("macho", cl::desc("Use MachO specific object file parser")); static cl::alias @@ -125,6 +136,13 @@ static cl::alias SectionHeadersShorter("h", cl::desc("Alias for --section-headers"), cl::aliasopt(SectionHeaders)); +cl::list +llvm::FilterSections("section", cl::desc("Operate on the specified sections only. " + "With -macho dump segment,section")); +cl::alias +static FilterSectionsj("j", cl::desc("Alias for --section"), + cl::aliasopt(llvm::FilterSections)); + cl::list llvm::MAttrs("mattr", cl::CommaSeparated, @@ -147,6 +165,11 @@ cl::opt llvm::PrivateHeaders("private-headers", cl::desc("Display format specific file headers")); +cl::opt +llvm::FirstPrivateHeader("private-header", + cl::desc("Display only the first format specific file " + "header")); + static cl::alias PrivateHeadersShort("p", cl::desc("Alias for --private-headers"), cl::aliasopt(PrivateHeaders)); @@ -159,22 +182,86 @@ cl::opt PrintFaultMaps("fault-map-section", cl::desc("Display contents of faultmap section")); static StringRef ToolName; -static int ReturnValue = EXIT_SUCCESS; -bool llvm::error(std::error_code EC) { +namespace { +typedef std::function FilterPredicate; + +class SectionFilterIterator { +public: + SectionFilterIterator(FilterPredicate P, + llvm::object::section_iterator const &I, + llvm::object::section_iterator const &E) + : Predicate(P), Iterator(I), End(E) { + ScanPredicate(); + } + const llvm::object::SectionRef &operator*() const { return *Iterator; } + SectionFilterIterator &operator++() { + ++Iterator; + ScanPredicate(); + return *this; + } + bool operator!=(SectionFilterIterator const &Other) const { + return Iterator != Other.Iterator; + } + +private: + void ScanPredicate() { + while (Iterator != End && !Predicate(*Iterator)) { + ++Iterator; + } + } + FilterPredicate Predicate; + llvm::object::section_iterator Iterator; + llvm::object::section_iterator End; +}; + +class SectionFilter { +public: + SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O) + : Predicate(P), Object(O) {} + SectionFilterIterator begin() { + return SectionFilterIterator(Predicate, Object.section_begin(), + Object.section_end()); + } + SectionFilterIterator end() { + return SectionFilterIterator(Predicate, Object.section_end(), + Object.section_end()); + } + +private: + FilterPredicate Predicate; + llvm::object::ObjectFile const &Object; +}; +SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) { + return SectionFilter([](llvm::object::SectionRef const &S) { + if(FilterSections.empty()) + return true; + llvm::StringRef String; + std::error_code error = S.getName(String); + if (error) + return false; + return std::find(FilterSections.begin(), + FilterSections.end(), + String) != FilterSections.end(); + }, + O); +} +} + +void llvm::error(std::error_code EC) { if (!EC) - return false; + return; - outs() << ToolName << ": error reading file: " << EC.message() << ".\n"; - outs().flush(); - ReturnValue = EXIT_FAILURE; - return true; + errs() << ToolName << ": error reading file: " << EC.message() << ".\n"; + errs().flush(); + exit(1); } -static void report_error(StringRef File, std::error_code EC) { +LLVM_ATTRIBUTE_NORETURN void llvm::report_error(StringRef File, + std::error_code EC) { assert(EC); errs() << ToolName << ": '" << File << "': " << EC.message() << ".\n"; - ReturnValue = EXIT_FAILURE; + exit(1); } static const Target *getTarget(const ObjectFile *Obj = nullptr) { @@ -201,10 +288,8 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(ArchName, TheTriple, Error); - if (!TheTarget) { - errs() << ToolName << ": " << Error; - return nullptr; - } + if (!TheTarget) + report_fatal_error("can't find target: " + Error); // Update the triple name and return the found target. TripleName = TheTriple.getTriple(); @@ -212,9 +297,7 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) { } bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { - uint64_t a_addr = a.getOffset(); - uint64_t b_addr = b.getOffset(); - return a_addr < b_addr; + return a.getOffset() < b.getOffset(); } namespace { @@ -299,11 +382,12 @@ PrettyPrinter &selectPrettyPrinter(Triple const &Triple) { template static std::error_code getRelocationValueString(const ELFObjectFile *Obj, - DataRefImpl Rel, + const RelocationRef &RelRef, SmallVectorImpl &Result) { + DataRefImpl Rel = RelRef.getRawDataRefImpl(); + typedef typename ELFObjectFile::Elf_Sym Elf_Sym; typedef typename ELFObjectFile::Elf_Shdr Elf_Shdr; - typedef typename ELFObjectFile::Elf_Rel Elf_Rel; typedef typename ELFObjectFile::Elf_Rela Elf_Rela; const ELFFile &EF = *Obj->getELFFile(); @@ -325,36 +409,31 @@ static std::error_code getRelocationValueString(const ELFObjectFile *Obj, if (std::error_code EC = StrTabOrErr.getError()) return EC; StringRef StrTab = *StrTabOrErr; - uint8_t type; + uint8_t type = RelRef.getType(); StringRef res; int64_t addend = 0; - uint16_t symbol_index = 0; switch (Sec->sh_type) { default: return object_error::parse_failed; case ELF::SHT_REL: { - const Elf_Rel *ERel = Obj->getRel(Rel); - type = ERel->getType(EF.isMips64EL()); - symbol_index = ERel->getSymbol(EF.isMips64EL()); // TODO: Read implicit addend from section data. break; } case ELF::SHT_RELA: { const Elf_Rela *ERela = Obj->getRela(Rel); - type = ERela->getType(EF.isMips64EL()); - symbol_index = ERela->getSymbol(EF.isMips64EL()); addend = ERela->r_addend; break; } } - const Elf_Sym *symb = - EF.template getEntry(Sec->sh_link, symbol_index); + symbol_iterator SI = RelRef.getSymbol(); + const Elf_Sym *symb = Obj->getSymbol(SI->getRawDataRefImpl()); StringRef Target; - ErrorOr SymSec = EF.getSection(symb); - if (std::error_code EC = SymSec.getError()) - return EC; if (symb->getType() == ELF::STT_SECTION) { - ErrorOr SecName = EF.getSectionName(*SymSec); + ErrorOr SymSI = SI->getSection(); + if (std::error_code EC = SymSI.getError()) + return EC; + const Elf_Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); + ErrorOr SecName = EF.getSectionName(SymSec); if (std::error_code EC = SecName.getError()) return EC; Target = *SecName; @@ -402,11 +481,29 @@ static std::error_code getRelocationValueString(const ELFObjectFile *Obj, break; } case ELF::EM_386: + case ELF::EM_IAMCU: case ELF::EM_ARM: case ELF::EM_HEXAGON: case ELF::EM_MIPS: 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"; + } + break; default: res = "Unknown"; } @@ -416,9 +513,8 @@ static std::error_code getRelocationValueString(const ELFObjectFile *Obj, } static std::error_code getRelocationValueString(const ELFObjectFileBase *Obj, - const RelocationRef &RelRef, + const RelocationRef &Rel, SmallVectorImpl &Result) { - DataRefImpl Rel = RelRef.getRawDataRefImpl(); if (auto *ELF32LE = dyn_cast(Obj)) return getRelocationValueString(ELF32LE, Rel, Result); if (auto *ELF64LE = dyn_cast(Obj)) @@ -469,7 +565,7 @@ static void printRelocationTargetName(const MachOObjectFile *O, // If we couldn't find a symbol that this relocation refers to, try // to find a section beginning instead. - for (const SectionRef &Section : O->sections()) { + for (const SectionRef &Section : ToolSectionFilter(*O)) { std::error_code ec; StringRef Name; @@ -494,8 +590,8 @@ static void printRelocationTargetName(const MachOObjectFile *O, symbol_iterator SI = O->symbol_begin(); advance(SI, Val); ErrorOr SOrErr = SI->getName(); - if (!error(SOrErr.getError())) - S = *SOrErr; + error(SOrErr.getError()); + S = *SOrErr; } else { section_iterator SI = O->section_begin(); // Adjust for the fact that sections are 1-indexed. @@ -730,10 +826,6 @@ static bool getHidden(RelocationRef RelRef) { static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); - // getTarget() will have already issued a diagnostic if necessary, so - // just bail here if it failed. - if (!TheTarget) - return; // Package up features to be passed to target/subtarget std::string FeaturesStr; @@ -746,42 +838,28 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::unique_ptr MRI( TheTarget->createMCRegInfo(TripleName)); - if (!MRI) { - errs() << "error: no register info for target " << TripleName << "\n"; - return; - } + if (!MRI) + report_fatal_error("error: no register info for target " + TripleName); // Set up disassembler. std::unique_ptr AsmInfo( TheTarget->createMCAsmInfo(*MRI, TripleName)); - if (!AsmInfo) { - errs() << "error: no assembly info for target " << TripleName << "\n"; - return; - } - + if (!AsmInfo) + report_fatal_error("error: no assembly info for target " + TripleName); std::unique_ptr STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); - if (!STI) { - errs() << "error: no subtarget info for target " << TripleName << "\n"; - return; - } - + if (!STI) + report_fatal_error("error: no subtarget info for target " + TripleName); std::unique_ptr MII(TheTarget->createMCInstrInfo()); - if (!MII) { - errs() << "error: no instruction info for target " << TripleName << "\n"; - return; - } - + if (!MII) + report_fatal_error("error: no instruction info for target " + TripleName); std::unique_ptr MOFI(new MCObjectFileInfo); MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get()); std::unique_ptr DisAsm( TheTarget->createMCDisassembler(*STI, Ctx)); - - if (!DisAsm) { - errs() << "error: no disassembler for target " << TripleName << "\n"; - return; - } + if (!DisAsm) + report_fatal_error("error: no disassembler for target " + TripleName); std::unique_ptr MIA( TheTarget->createMCInstrAnalysis(MII.get())); @@ -789,11 +867,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); std::unique_ptr IP(TheTarget->createMCInstPrinter( Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI)); - if (!IP) { - errs() << "error: no instruction printer for target " << TripleName - << '\n'; - return; - } + if (!IP) + report_fatal_error("error: no instruction printer for target " + + TripleName); IP->setPrintImmHex(PrintImmHex); PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); @@ -804,14 +880,75 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // in RelocSecs contain the relocations for section S. std::error_code EC; std::map> SectionRelocMap; - for (const SectionRef &Section : Obj->sections()) { + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { section_iterator Sec2 = Section.getRelocatedSection(); if (Sec2 != Obj->section_end()) SectionRelocMap[*Sec2].push_back(Section); } - for (const SectionRef &Section : Obj->sections()) { - if (!Section.isText() || Section.isVirtual()) + // Create a mapping from virtual address to symbol name. This is used to + // pretty print the symbols while disassembling. + typedef std::vector> SectionSymbolsTy; + std::map AllSymbols; + for (const SymbolRef &Symbol : Obj->symbols()) { + ErrorOr AddressOrErr = Symbol.getAddress(); + error(AddressOrErr.getError()); + uint64_t Address = *AddressOrErr; + + ErrorOr Name = Symbol.getName(); + error(Name.getError()); + if (Name->empty()) + continue; + + ErrorOr SectionOrErr = Symbol.getSection(); + error(SectionOrErr.getError()); + section_iterator SecI = *SectionOrErr; + if (SecI == Obj->section_end()) + continue; + + AllSymbols[*SecI].emplace_back(Address, *Name); + } + + // Create a mapping from virtual address to section. + std::vector> SectionAddresses; + for (SectionRef Sec : Obj->sections()) + SectionAddresses.emplace_back(Sec.getAddress(), Sec); + array_pod_sort(SectionAddresses.begin(), SectionAddresses.end()); + + // Linked executables (.exe and .dll files) typically don't include a real + // symbol table but they might contain an export table. + if (const auto *COFFObj = dyn_cast(Obj)) { + for (const auto &ExportEntry : COFFObj->export_directories()) { + StringRef Name; + error(ExportEntry.getSymbolName(Name)); + if (Name.empty()) + continue; + uint32_t RVA; + error(ExportEntry.getExportRVA(RVA)); + + uint64_t VA = COFFObj->getImageBase() + RVA; + auto Sec = std::upper_bound( + SectionAddresses.begin(), SectionAddresses.end(), VA, + [](uint64_t LHS, const std::pair &RHS) { + return LHS < RHS.first; + }); + if (Sec != SectionAddresses.begin()) + --Sec; + else + Sec = SectionAddresses.end(); + + if (Sec != SectionAddresses.end()) + AllSymbols[Sec->second].emplace_back(VA, Name); + } + } + + // Sort all the symbols, this allows us to use a simple binary search to find + // a symbol near an address. + for (std::pair &SecSyms : AllSymbols) + array_pod_sort(SecSyms.second.begin(), SecSyms.second.end()); + + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { + if (!DisassembleAll && (!Section.isText() || Section.isVirtual())) continue; uint64_t SectionAddr = Section.getAddress(); @@ -819,29 +956,23 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (!SectSize) continue; - // Make a list of all the symbols in this section. - std::vector> Symbols; - for (const SymbolRef &Symbol : Obj->symbols()) { - if (Section.containsSymbol(Symbol)) { - ErrorOr AddressOrErr = Symbol.getAddress(); - if (error(AddressOrErr.getError())) - break; - uint64_t Address = *AddressOrErr; - if (Address == UnknownAddress) - continue; - Address -= SectionAddr; - if (Address >= SectSize) - continue; - - ErrorOr Name = Symbol.getName(); - if (error(Name.getError())) - break; - Symbols.push_back(std::make_pair(Address, *Name)); + // Get the list of all the symbols in this section. + SectionSymbolsTy &Symbols = AllSymbols[Section]; + std::vector DataMappingSymsAddr; + std::vector TextMappingSymsAddr; + if (Obj->isELF() && Obj->getArch() == Triple::aarch64) { + for (const auto &Symb : Symbols) { + uint64_t Address = Symb.first; + StringRef Name = Symb.second; + if (Name.startswith("$d")) + DataMappingSymsAddr.push_back(Address - SectionAddr); + if (Name.startswith("$x")) + TextMappingSymsAddr.push_back(Address - SectionAddr); } } - // Sort the symbols by address, just in case they didn't come in that way. - array_pod_sort(Symbols.begin(), Symbols.end()); + std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end()); + std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end()); // Make a list of all the relocations for this section. std::vector Rels; @@ -862,8 +993,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SegmentName = MachO->getSectionFinalSegmentName(DR); } StringRef name; - if (error(Section.getName(name))) - break; + error(Section.getName(name)); outs() << "Disassembly of section "; if (!SegmentName.empty()) outs() << SegmentName << ","; @@ -871,14 +1001,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // If the section has no symbol at the start, just insert a dummy one. if (Symbols.empty() || Symbols[0].first != 0) - Symbols.insert(Symbols.begin(), std::make_pair(0, name)); + Symbols.insert(Symbols.begin(), std::make_pair(SectionAddr, name)); SmallString<40> Comments; raw_svector_ostream CommentStream(Comments); StringRef BytesStr; - if (error(Section.getContents(BytesStr))) - break; + error(Section.getContents(BytesStr)); ArrayRef Bytes(reinterpret_cast(BytesStr.data()), BytesStr.size()); @@ -890,11 +1019,16 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Disassemble symbol by symbol. for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { - uint64_t Start = Symbols[si].first; - // The end is either the section end or the beginning of the next symbol. - uint64_t End = (si == se - 1) ? SectSize : Symbols[si + 1].first; + uint64_t Start = Symbols[si].first - SectionAddr; + // The end is either the section end or the beginning of the next + // symbol. + uint64_t End = + (si == se - 1) ? SectSize : Symbols[si + 1].first - SectionAddr; + // Don't try to disassemble beyond the end of section contents. + if (End > SectSize) + End = SectSize; // If this symbol has the same address as the next symbol, then skip it. - if (Start == End) + if (Start >= End) continue; outs() << '\n' << Symbols[si].second << ":\n"; @@ -908,6 +1042,45 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { for (Index = Start; Index < End; Index += Size) { MCInst Inst; + // AArch64 ELF binaries can interleave data and text in the + // same section. We rely on the markers introduced to + // understand what we need to dump. + if (Obj->isELF() && Obj->getArch() == Triple::aarch64) { + uint64_t Stride = 0; + + auto DAI = std::lower_bound(DataMappingSymsAddr.begin(), + DataMappingSymsAddr.end(), Index); + if (DAI != DataMappingSymsAddr.end() && *DAI == Index) { + // Switch to data. + while (Index < End) { + outs() << format("%8" PRIx64 ":", SectionAddr + Index); + outs() << "\t"; + if (Index + 4 <= End) { + Stride = 4; + dumpBytes(Bytes.slice(Index, 4), outs()); + outs() << "\t.word"; + } else if (Index + 2 <= End) { + Stride = 2; + dumpBytes(Bytes.slice(Index, 2), outs()); + outs() << "\t.short"; + } else { + Stride = 1; + dumpBytes(Bytes.slice(Index, 1), outs()); + outs() << "\t.byte"; + } + Index += Stride; + outs() << "\n"; + auto TAI = std::lower_bound(TextMappingSymsAddr.begin(), + TextMappingSymsAddr.end(), Index); + if (TAI != TextMappingSymsAddr.end() && *TAI == Index) + break; + } + } + } + + if (Index >= End) + break; + if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), SectionAddr + Index, DebugOut, CommentStream)) { @@ -916,6 +1089,58 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SectionAddr + Index, outs(), "", *STI); outs() << CommentStream.str(); Comments.clear(); + + // Try to resolve the target of a call, tail call, etc. to a specific + // symbol. + if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) || + MIA->isConditionalBranch(Inst))) { + uint64_t Target; + if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) { + // In a relocatable object, the target's section must reside in + // the same section as the call instruction or it is accessed + // through a relocation. + // + // In a non-relocatable object, the target may be in any section. + // + // N.B. We don't walk the relocations in the relocatable case yet. + auto *TargetSectionSymbols = &Symbols; + if (!Obj->isRelocatableObject()) { + auto SectionAddress = std::upper_bound( + SectionAddresses.begin(), SectionAddresses.end(), Target, + [](uint64_t LHS, + const std::pair &RHS) { + return LHS < RHS.first; + }); + if (SectionAddress != SectionAddresses.begin()) { + --SectionAddress; + TargetSectionSymbols = &AllSymbols[SectionAddress->second]; + } else { + TargetSectionSymbols = nullptr; + } + } + + // Find the first symbol in the section whose offset is less than + // or equal to the target. + if (TargetSectionSymbols) { + auto TargetSym = std::upper_bound( + TargetSectionSymbols->begin(), TargetSectionSymbols->end(), + Target, [](uint64_t LHS, + const std::pair &RHS) { + return LHS < RHS.first; + }); + if (TargetSym != TargetSectionSymbols->begin()) { + --TargetSym; + uint64_t TargetAddress = std::get<0>(*TargetSym); + StringRef TargetName = std::get<1>(*TargetSym); + outs() << " <" << TargetName; + uint64_t Disp = Target - TargetAddress; + if (Disp) + outs() << '+' << utohexstr(Disp); + outs() << '>'; + } + } + } + } outs() << "\n"; } else { errs() << ToolName << ": warning: invalid instruction encoding\n"; @@ -936,8 +1161,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; rel_cur->getTypeName(name); - if (error(getRelocationValueString(*rel_cur, val))) - goto skip_print_rel; + error(getRelocationValueString(*rel_cur, val)); outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; @@ -957,12 +1181,11 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { if (!Obj->isRelocatableObject()) return; - for (const SectionRef &Section : Obj->sections()) { + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { if (Section.relocation_begin() == Section.relocation_end()) continue; StringRef secname; - if (error(Section.getName(secname))) - continue; + error(Section.getName(secname)); outs() << "RELOCATION RECORDS FOR [" << secname << "]:\n"; for (const RelocationRef &Reloc : Section.relocations()) { bool hidden = getHidden(Reloc); @@ -972,8 +1195,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) { if (hidden) continue; Reloc.getTypeName(relocname); - if (error(getRelocationValueString(Reloc, valuestr))) - continue; + error(getRelocationValueString(Reloc, valuestr)); outs() << format(Fmt.data(), address) << " " << relocname << " " << valuestr << "\n"; } @@ -985,10 +1207,9 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) { outs() << "Sections:\n" "Idx Name Size Address Type\n"; unsigned i = 0; - for (const SectionRef &Section : Obj->sections()) { + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { StringRef Name; - if (error(Section.getName(Name))) - return; + error(Section.getName(Name)); uint64_t Address = Section.getAddress(); uint64_t Size = Section.getSize(); bool Text = Section.isText(); @@ -1004,11 +1225,10 @@ void llvm::PrintSectionHeaders(const ObjectFile *Obj) { void llvm::PrintSectionContents(const ObjectFile *Obj) { std::error_code EC; - for (const SectionRef &Section : Obj->sections()) { + for (const SectionRef &Section : ToolSectionFilter(*Obj)) { StringRef Name; StringRef Contents; - if (error(Section.getName(Name))) - continue; + error(Section.getName(Name)); uint64_t BaseAddr = Section.getAddress(); uint64_t Size = Section.getSize(); if (!Size) @@ -1022,8 +1242,7 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) { continue; } - if (error(Section.getContents(Contents))) - continue; + error(Section.getContents(Contents)); // Dump out the content as hex and printable ascii characters. for (std::size_t addr = 0, end = Contents.size(); addr < end; addr += 16) { @@ -1051,84 +1270,28 @@ void llvm::PrintSectionContents(const ObjectFile *Obj) { } } -static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { - for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) { - ErrorOr Symbol = coff->getSymbol(SI); - StringRef Name; - if (error(Symbol.getError())) - return; - - if (error(coff->getSymbolName(*Symbol, Name))) - return; - - outs() << "[" << format("%2d", SI) << "]" - << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")" - << "(fl 0x00)" // Flag bits, which COFF doesn't have. - << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")" - << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") " - << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") " - << "0x" << format("%08x", unsigned(Symbol->getValue())) << " " - << Name << "\n"; - - for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) { - if (Symbol->isSectionDefinition()) { - const coff_aux_section_definition *asd; - if (error(coff->getAuxSymbol(SI + 1, asd))) - return; - - int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); - - outs() << "AUX " - << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " - , unsigned(asd->Length) - , unsigned(asd->NumberOfRelocations) - , unsigned(asd->NumberOfLinenumbers) - , unsigned(asd->CheckSum)) - << format("assoc %d comdat %d\n" - , unsigned(AuxNumber) - , unsigned(asd->Selection)); - } else if (Symbol->isFileRecord()) { - const char *FileName; - if (error(coff->getAuxSymbol(SI + 1, FileName))) - return; - - StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() * - coff->getSymbolTableEntrySize()); - outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n'; - - SI = SI + Symbol->getNumberOfAuxSymbols(); - break; - } else { - outs() << "AUX Unknown\n"; - } - } - } -} - void llvm::PrintSymbolTable(const ObjectFile *o) { outs() << "SYMBOL TABLE:\n"; if (const COFFObjectFile *coff = dyn_cast(o)) { - PrintCOFFSymbolTable(coff); + printCOFFSymbolTable(coff); return; } for (const SymbolRef &Symbol : o->symbols()) { ErrorOr AddressOrError = Symbol.getAddress(); - if (error(AddressOrError.getError())) - continue; + error(AddressOrError.getError()); uint64_t Address = *AddressOrError; SymbolRef::Type Type = Symbol.getType(); uint32_t Flags = Symbol.getFlags(); - section_iterator Section = o->section_end(); - if (error(Symbol.getSection(Section))) - continue; + ErrorOr SectionOrErr = Symbol.getSection(); + error(SectionOrErr.getError()); + section_iterator Section = *SectionOrErr; StringRef Name; if (Type == SymbolRef::ST_Debug && Section != o->section_end()) { Section->getName(Name); } else { ErrorOr NameOrErr = Symbol.getName(); - if (error(NameOrErr.getError())) - continue; + error(NameOrErr.getError()); Name = *NameOrErr; } @@ -1138,11 +1301,6 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { bool Common = Flags & SymbolRef::SF_Common; bool Hidden = Flags & SymbolRef::SF_Hidden; - if (Common) - Address = Symbol.getCommonSize(); - - if (Address == UnknownAddress) - Address = 0; char GlobLoc = ' '; if (Type != SymbolRef::ST_Unknown) GlobLoc = Global ? 'g' : 'l'; @@ -1180,8 +1338,7 @@ void llvm::PrintSymbolTable(const ObjectFile *o) { outs() << SegmentName << ","; } StringRef SectionName; - if (error(Section->getName(SectionName))) - SectionName = ""; + error(Section->getName(SectionName)); outs() << SectionName; } @@ -1270,6 +1427,39 @@ void llvm::printWeakBindTable(const ObjectFile *o) { } } +/// Dump the raw contents of the __clangast section so the output can be piped +/// into llvm-bcanalyzer. +void llvm::printRawClangAST(const ObjectFile *Obj) { + if (outs().is_displayed()) { + errs() << "The -raw-clang-ast option will dump the raw binary contents of " + "the clang ast section.\n" + "Please redirect the output to a file or another program such as " + "llvm-bcanalyzer.\n"; + return; + } + + StringRef ClangASTSectionName("__clangast"); + if (isa(Obj)) { + ClangASTSectionName = "clangast"; + } + + Optional ClangASTSection; + for (auto Sec : ToolSectionFilter(*Obj)) { + StringRef Name; + Sec.getName(Name); + if (Name == ClangASTSectionName) { + ClangASTSection = Sec; + break; + } + } + if (!ClangASTSection) + return; + + StringRef ClangASTContents; + error(ClangASTSection.getValue().getContents(ClangASTContents)); + outs().write(ClangASTContents.data(), ClangASTContents.size()); +} + static void printFaultMaps(const ObjectFile *Obj) { const char *FaultMapSectionName = nullptr; @@ -1285,7 +1475,7 @@ static void printFaultMaps(const ObjectFile *Obj) { Optional FaultMapSection; - for (auto Sec : Obj->sections()) { + for (auto Sec : ToolSectionFilter(*Obj)) { StringRef Name; Sec.getName(Name); if (Name == FaultMapSectionName) { @@ -1302,10 +1492,7 @@ static void printFaultMaps(const ObjectFile *Obj) { } StringRef FaultMapContents; - if (error(FaultMapSection.getValue().getContents(FaultMapContents))) { - errs() << "Could not read the " << FaultMapContents << " section!\n"; - return; - } + error(FaultMapSection.getValue().getContents(FaultMapContents)); FaultMapParser FMP(FaultMapContents.bytes_begin(), FaultMapContents.bytes_end()); @@ -1313,20 +1500,36 @@ static void printFaultMaps(const ObjectFile *Obj) { outs() << FMP; } -static void printPrivateFileHeader(const ObjectFile *o) { - if (o->isELF()) { +static void printPrivateFileHeaders(const ObjectFile *o) { + if (o->isELF()) printELFFileHeader(o); - } else if (o->isCOFF()) { + else if (o->isCOFF()) printCOFFFileHeader(o); - } else if (o->isMachO()) { + else if (o->isMachO()) { printMachOFileHeader(o); - } + printMachOLoadCommands(o); + } else + report_fatal_error("Invalid/Unsupported object file format"); +} + +static void printFirstPrivateFileHeader(const ObjectFile *o) { + if (o->isELF()) + printELFFileHeader(o); + else if (o->isCOFF()) + printCOFFFileHeader(o); + else if (o->isMachO()) + printMachOFileHeader(o); + else + report_fatal_error("Invalid/Unsupported object file format"); } static void DumpObject(const ObjectFile *o) { - outs() << '\n'; - outs() << o->getFileName() - << ":\tfile format " << o->getFileFormatName() << "\n\n"; + // Avoid other output when using a raw option. + if (!RawClangAST) { + outs() << '\n'; + outs() << o->getFileName() + << ":\tfile format " << o->getFileFormatName() << "\n\n"; + } if (Disassemble) DisassembleObject(o, Relocations); @@ -1341,7 +1544,9 @@ static void DumpObject(const ObjectFile *o) { if (UnwindInfo) PrintUnwindInfo(o); if (PrivateHeaders) - printPrivateFileHeader(o); + printPrivateFileHeaders(o); + if (FirstPrivateHeader) + printFirstPrivateFileHeader(o); if (ExportsTrie) printExportsTrie(o); if (Rebase) @@ -1352,21 +1557,22 @@ static void DumpObject(const ObjectFile *o) { printLazyBindTable(o); if (WeakBind) printWeakBindTable(o); + if (RawClangAST) + printRawClangAST(o); if (PrintFaultMaps) printFaultMaps(o); } /// @brief Dump each object file in \a a; static void DumpArchive(const Archive *a) { - for (Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e; - ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); - if (std::error_code EC = ChildOrErr.getError()) { - // Ignore non-object files. + for (auto &ErrorOrChild : a->children()) { + if (std::error_code EC = ErrorOrChild.getError()) + report_error(a->getFileName(), EC); + const Archive::Child &C = *ErrorOrChild; + ErrorOr> ChildOrErr = C.getAsBinary(); + if (std::error_code EC = ChildOrErr.getError()) if (EC != object_error::invalid_file_type) report_error(a->getFileName(), EC); - continue; - } if (ObjectFile *o = dyn_cast(&*ChildOrErr.get())) DumpObject(o); else @@ -1376,11 +1582,6 @@ static void DumpArchive(const Archive *a) { /// @brief Open file and figure out how to dump it. static void DumpInput(StringRef file) { - // If file isn't stdin, check that it exists. - if (file != "-" && !sys::fs::exists(file)) { - report_error(file, errc::no_such_file_or_directory); - return; - } // If we are using the Mach-O specific object file parser, then let it parse // the file and process the command line options. So the -arch flags can @@ -1392,10 +1593,8 @@ static void DumpInput(StringRef file) { // Attempt to open the binary. ErrorOr> BinaryOrErr = createBinary(file); - if (std::error_code EC = BinaryOrErr.getError()) { + if (std::error_code EC = BinaryOrErr.getError()) report_error(file, EC); - return; - } Binary &Binary = *BinaryOrErr.get().getBinary(); if (Archive *a = dyn_cast(&Binary)) @@ -1415,7 +1614,6 @@ int main(int argc, char **argv) { // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. @@ -1430,6 +1628,8 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); + if (DisassembleAll) + Disassemble = true; if (!Disassemble && !Relocations && !SectionHeaders @@ -1437,11 +1637,13 @@ int main(int argc, char **argv) { && !SymbolTable && !UnwindInfo && !PrivateHeaders + && !FirstPrivateHeader && !ExportsTrie && !Rebase && !Bind && !LazyBind && !WeakBind + && !RawClangAST && !(UniversalHeaders && MachOOpt) && !(ArchiveHeaders && MachOOpt) && !(IndirectSymbols && MachOOpt) @@ -1451,7 +1653,7 @@ int main(int argc, char **argv) { && !(DylibsUsed && MachOOpt) && !(DylibId && MachOOpt) && !(ObjcMetaData && MachOOpt) - && !(DumpSections.size() != 0 && MachOOpt) + && !(FilterSections.size() != 0 && MachOOpt) && !PrintFaultMaps) { cl::PrintHelpMessage(); return 2; @@ -1460,5 +1662,5 @@ int main(int argc, char **argv) { std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput); - return ReturnValue; + return EXIT_SUCCESS; }