diff options
Diffstat (limited to 'llvm/tools/llvm-readobj/COFFDumper.cpp')
-rw-r--r-- | llvm/tools/llvm-readobj/COFFDumper.cpp | 265 |
1 files changed, 156 insertions, 109 deletions
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 9b2c6adb9d93..89a904f53ae7 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -104,7 +104,10 @@ public: bool GHash) override; void printStackMap() const override; void printAddrsig() override; + void printCGProfile() override; + private: + StringRef getSymbolName(uint32_t Index); void printSymbols() override; void printDynamicSymbols() override; void printSymbol(const SymbolRef &Sym); @@ -409,6 +412,11 @@ static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = { LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE), }; +static const EnumEntry<COFF::ExtendedDLLCharacteristics> + PEExtendedDLLCharacteristics[] = { + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT), +}; + static const EnumEntry<COFF::SectionCharacteristics> ImageSectionCharacteristics[] = { LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD ), @@ -516,23 +524,25 @@ static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = { }; static const EnumEntry<COFF::DebugType> ImageDebugType[] = { - { "Unknown" , COFF::IMAGE_DEBUG_TYPE_UNKNOWN }, - { "COFF" , COFF::IMAGE_DEBUG_TYPE_COFF }, - { "CodeView" , COFF::IMAGE_DEBUG_TYPE_CODEVIEW }, - { "FPO" , COFF::IMAGE_DEBUG_TYPE_FPO }, - { "Misc" , COFF::IMAGE_DEBUG_TYPE_MISC }, - { "Exception" , COFF::IMAGE_DEBUG_TYPE_EXCEPTION }, - { "Fixup" , COFF::IMAGE_DEBUG_TYPE_FIXUP }, - { "OmapToSrc" , COFF::IMAGE_DEBUG_TYPE_OMAP_TO_SRC }, - { "OmapFromSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC }, - { "Borland" , COFF::IMAGE_DEBUG_TYPE_BORLAND }, - { "Reserved10" , COFF::IMAGE_DEBUG_TYPE_RESERVED10 }, - { "CLSID" , COFF::IMAGE_DEBUG_TYPE_CLSID }, - { "VCFeature" , COFF::IMAGE_DEBUG_TYPE_VC_FEATURE }, - { "POGO" , COFF::IMAGE_DEBUG_TYPE_POGO }, - { "ILTCG" , COFF::IMAGE_DEBUG_TYPE_ILTCG }, - { "MPX" , COFF::IMAGE_DEBUG_TYPE_MPX }, - { "Repro" , COFF::IMAGE_DEBUG_TYPE_REPRO }, + {"Unknown", COFF::IMAGE_DEBUG_TYPE_UNKNOWN}, + {"COFF", COFF::IMAGE_DEBUG_TYPE_COFF}, + {"CodeView", COFF::IMAGE_DEBUG_TYPE_CODEVIEW}, + {"FPO", COFF::IMAGE_DEBUG_TYPE_FPO}, + {"Misc", COFF::IMAGE_DEBUG_TYPE_MISC}, + {"Exception", COFF::IMAGE_DEBUG_TYPE_EXCEPTION}, + {"Fixup", COFF::IMAGE_DEBUG_TYPE_FIXUP}, + {"OmapToSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_TO_SRC}, + {"OmapFromSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC}, + {"Borland", COFF::IMAGE_DEBUG_TYPE_BORLAND}, + {"Reserved10", COFF::IMAGE_DEBUG_TYPE_RESERVED10}, + {"CLSID", COFF::IMAGE_DEBUG_TYPE_CLSID}, + {"VCFeature", COFF::IMAGE_DEBUG_TYPE_VC_FEATURE}, + {"POGO", COFF::IMAGE_DEBUG_TYPE_POGO}, + {"ILTCG", COFF::IMAGE_DEBUG_TYPE_ILTCG}, + {"MPX", COFF::IMAGE_DEBUG_TYPE_MPX}, + {"Repro", COFF::IMAGE_DEBUG_TYPE_REPRO}, + {"ExtendedDLLCharacteristics", + COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS}, }; static const EnumEntry<COFF::WeakExternalCharacteristics> @@ -601,8 +611,8 @@ void COFFDumper::cacheRelocations() { void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) { - const data_directory *Data; - if (Obj->getDataDirectory(Index, Data)) + const data_directory *Data = Obj->getDataDirectory(Index); + if (!Data) return; W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress); W.printHex(FieldName + "Size", Data->Size); @@ -621,6 +631,7 @@ void COFFDumper::printFileHeaders() { W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp()); W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable()); W.printNumber("SymbolCount", Obj->getNumberOfSymbols()); + W.printNumber("StringTableSize", Obj->getStringTableSize()); W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader()); W.printFlags ("Characteristics", Obj->getCharacteristics(), makeArrayRef(ImageFileCharacteristics)); @@ -722,11 +733,15 @@ void COFFDumper::printCOFFDebugDirectory() { W.printHex("SizeOfData", D.SizeOfData); W.printHex("AddressOfRawData", D.AddressOfRawData); W.printHex("PointerToRawData", D.PointerToRawData); + // Ideally, if D.AddressOfRawData == 0, we should try to load the payload + // using D.PointerToRawData instead. + if (D.AddressOfRawData == 0) + continue; if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) { const codeview::DebugInfo *DebugInfo; StringRef PDBFileName; - if (std::error_code EC = Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName)) + reportError(std::move(E), Obj->getFileName()); DictScope PDBScope(W, "PDBInfo"); W.printHex("PDBSignature", DebugInfo->Signature.CVSignature); @@ -736,12 +751,19 @@ void COFFDumper::printCOFFDebugDirectory() { W.printString("PDBFileName", PDBFileName); } } else if (D.SizeOfData != 0) { - // FIXME: Type values of 12 and 13 are commonly observed but are not in - // the documented type enum. Figure out what they mean. + // FIXME: Data visualization for IMAGE_DEBUG_TYPE_VC_FEATURE and + // IMAGE_DEBUG_TYPE_POGO? ArrayRef<uint8_t> RawData; - if (std::error_code EC = Obj->getRvaAndSizeAsBytes(D.AddressOfRawData, + if (Error E = Obj->getRvaAndSizeAsBytes(D.AddressOfRawData, D.SizeOfData, RawData)) - reportError(errorCodeToError(EC), Obj->getFileName()); + reportError(std::move(E), Obj->getFileName()); + if (D.Type == COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS) { + // FIXME right now the only possible value would fit in 8 bits, + // but that might change in the future + uint16_t Characteristics = RawData[0]; + W.printFlags("ExtendedCharacteristics", Characteristics, + makeArrayRef(PEExtendedDLLCharacteristics)); + } W.printBinaryBlock("RawData", RawData); } } @@ -750,11 +772,11 @@ void COFFDumper::printCOFFDebugDirectory() { void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count, uint64_t EntrySize, PrintExtraCB PrintExtra) { uintptr_t TableStart, TableEnd; - if (std::error_code EC = Obj->getVaPtr(TableVA, TableStart)) - reportError(errorCodeToError(EC), Obj->getFileName()); - if (std::error_code EC = + if (Error E = Obj->getVaPtr(TableVA, TableStart)) + reportError(std::move(E), Obj->getFileName()); + if (Error E = Obj->getVaPtr(TableVA + Count * EntrySize - 1, TableEnd)) - reportError(errorCodeToError(EC), Obj->getFileName()); + reportError(std::move(E), Obj->getFileName()); TableEnd++; for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) { uint32_t RVA = *reinterpret_cast<const ulittle32_t *>(I); @@ -1135,7 +1157,7 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, return; } - std::string PC = formatv("+{0:X}", uint32_t(Line.Offset)); + std::string PC = std::string(formatv("+{0:X}", uint32_t(Line.Offset))); ListScope PCScope(W, PC); codeview::LineInfo LI(Line.Flags); @@ -1449,21 +1471,25 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { DictScope D(W, "Symbol"); COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym); - const coff_section *Section; - if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) { - W.startLine() << "Invalid section number: " << EC.message() << "\n"; + Expected<const coff_section *> SecOrErr = + Obj->getSection(Symbol.getSectionNumber()); + if (!SecOrErr) { + W.startLine() << "Invalid section number: " << Symbol.getSectionNumber() + << "\n"; W.flush(); + consumeError(SecOrErr.takeError()); return; } + const coff_section *Section = *SecOrErr; StringRef SymbolName; - if (Obj->getSymbolName(Symbol, SymbolName)) - SymbolName = ""; + if (Expected<StringRef> SymNameOrErr = Obj->getSymbolName(Symbol)) + SymbolName = *SymNameOrErr; StringRef SectionName; - if (Expected<StringRef> NameOrErr = + if (Expected<StringRef> SecNameOrErr = getSectionName(Obj, Symbol.getSectionNumber(), Section)) - SectionName = *NameOrErr; + SectionName = *SecNameOrErr; W.printString("Name", SymbolName); W.printNumber("Value", Symbol.getValue()); @@ -1492,16 +1518,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux)) reportError(errorCodeToError(EC), Obj->getFileName()); - Expected<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex); - if (!Linked) - reportError(Linked.takeError(), Obj->getFileName()); - - StringRef LinkedName; - if (std::error_code EC = Obj->getSymbolName(*Linked, LinkedName)) - reportError(errorCodeToError(EC), Obj->getFileName()); - DictScope AS(W, "AuxWeakExternal"); - W.printNumber("Linked", LinkedName, Aux->TagIndex); + W.printNumber("Linked", getSymbolName(Aux->TagIndex), Aux->TagIndex); W.printEnum ("Search", Aux->Characteristics, makeArrayRef(WeakExternalCharacteristics)); @@ -1532,35 +1550,25 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - const coff_section *Assoc; - StringRef AssocName = ""; - if (std::error_code EC = Obj->getSection(AuxNumber, Assoc)) - reportError(errorCodeToError(EC), Obj->getFileName()); - Expected<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc); - if (!Res) - reportError(Res.takeError(), Obj->getFileName()); - AssocName = *Res; - - W.printNumber("AssocSection", AssocName, AuxNumber); + Expected<const coff_section *> Assoc = Obj->getSection(AuxNumber); + if (!Assoc) + reportError(Assoc.takeError(), Obj->getFileName()); + Expected<StringRef> AssocName = getSectionName(Obj, AuxNumber, *Assoc); + if (!AssocName) + reportError(AssocName.takeError(), Obj->getFileName()); + + W.printNumber("AssocSection", *AssocName, AuxNumber); } } else if (Symbol.isCLRToken()) { const coff_aux_clr_token *Aux; if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux)) reportError(errorCodeToError(EC), Obj->getFileName()); - Expected<COFFSymbolRef> ReferredSym = - Obj->getSymbol(Aux->SymbolTableIndex); - if (!ReferredSym) - reportError(ReferredSym.takeError(), Obj->getFileName()); - - StringRef ReferredName; - if (std::error_code EC = Obj->getSymbolName(*ReferredSym, ReferredName)) - reportError(errorCodeToError(EC), Obj->getFileName()); - DictScope AS(W, "AuxCLRToken"); W.printNumber("AuxType", Aux->AuxType); W.printNumber("Reserved", Aux->Reserved); - W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); + W.printNumber("SymbolTableIndex", getSymbolName(Aux->SymbolTableIndex), + Aux->SymbolTableIndex); } else { W.startLine() << "<unhandled auxiliary record>\n"; @@ -1621,11 +1629,11 @@ void COFFDumper::printImportedSymbols( iterator_range<imported_symbol_iterator> Range) { for (const ImportedSymbolRef &I : Range) { StringRef Sym; - if (std::error_code EC = I.getSymbolName(Sym)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getSymbolName(Sym)) + reportError(std::move(E), Obj->getFileName()); uint16_t Ordinal; - if (std::error_code EC = I.getOrdinal(Ordinal)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getOrdinal(Ordinal)) + reportError(std::move(E), Obj->getFileName()); W.printNumber("Symbol", Sym, Ordinal); } } @@ -1637,17 +1645,17 @@ void COFFDumper::printDelayImportedSymbols( for (const ImportedSymbolRef &S : Range) { DictScope Import(W, "Import"); StringRef Sym; - if (std::error_code EC = S.getSymbolName(Sym)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = S.getSymbolName(Sym)) + reportError(std::move(E), Obj->getFileName()); uint16_t Ordinal; - if (std::error_code EC = S.getOrdinal(Ordinal)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = S.getOrdinal(Ordinal)) + reportError(std::move(E), Obj->getFileName()); W.printNumber("Symbol", Sym, Ordinal); uint64_t Addr; - if (std::error_code EC = I.getImportAddress(Index++, Addr)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getImportAddress(Index++, Addr)) + reportError(std::move(E), Obj->getFileName()); W.printHex("Address", Addr); } } @@ -1657,16 +1665,16 @@ void COFFDumper::printCOFFImports() { for (const ImportDirectoryEntryRef &I : Obj->import_directories()) { DictScope Import(W, "Import"); StringRef Name; - if (std::error_code EC = I.getName(Name)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getName(Name)) + reportError(std::move(E), Obj->getFileName()); W.printString("Name", Name); uint32_t ILTAddr; - if (std::error_code EC = I.getImportLookupTableRVA(ILTAddr)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getImportLookupTableRVA(ILTAddr)) + reportError(std::move(E), Obj->getFileName()); W.printHex("ImportLookupTableRVA", ILTAddr); uint32_t IATAddr; - if (std::error_code EC = I.getImportAddressTableRVA(IATAddr)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getImportAddressTableRVA(IATAddr)) + reportError(std::move(E), Obj->getFileName()); W.printHex("ImportAddressTableRVA", IATAddr); // The import lookup table can be missing with certain older linkers, so // fall back to the import address table in that case. @@ -1680,12 +1688,12 @@ void COFFDumper::printCOFFImports() { for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) { DictScope Import(W, "DelayImport"); StringRef Name; - if (std::error_code EC = I.getName(Name)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getName(Name)) + reportError(std::move(E), Obj->getFileName()); W.printString("Name", Name); const delay_import_directory_table_entry *Table; - if (std::error_code EC = I.getDelayImportTable(Table)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getDelayImportTable(Table)) + reportError(std::move(E), Obj->getFileName()); W.printHex("Attributes", Table->Attributes); W.printHex("ModuleHandle", Table->ModuleHandle); W.printHex("ImportAddressTable", Table->DelayImportAddressTable); @@ -1697,18 +1705,18 @@ void COFFDumper::printCOFFImports() { } void COFFDumper::printCOFFExports() { - for (const ExportDirectoryEntryRef &E : Obj->export_directories()) { + for (const ExportDirectoryEntryRef &Exp : Obj->export_directories()) { DictScope Export(W, "Export"); StringRef Name; uint32_t Ordinal, RVA; - if (std::error_code EC = E.getSymbolName(Name)) - reportError(errorCodeToError(EC), Obj->getFileName()); - if (std::error_code EC = E.getOrdinal(Ordinal)) - reportError(errorCodeToError(EC), Obj->getFileName()); - if (std::error_code EC = E.getExportRVA(RVA)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = Exp.getSymbolName(Name)) + reportError(std::move(E), Obj->getFileName()); + if (Error E = Exp.getOrdinal(Ordinal)) + reportError(std::move(E), Obj->getFileName()); + if (Error E = Exp.getExportRVA(RVA)) + reportError(std::move(E), Obj->getFileName()); W.printNumber("Ordinal", Ordinal); W.printString("Name", Name); @@ -1746,10 +1754,10 @@ void COFFDumper::printCOFFBaseReloc() { for (const BaseRelocRef &I : Obj->base_relocs()) { uint8_t Type; uint32_t RVA; - if (std::error_code EC = I.getRVA(RVA)) - reportError(errorCodeToError(EC), Obj->getFileName()); - if (std::error_code EC = I.getType(Type)) - reportError(errorCodeToError(EC), Obj->getFileName()); + if (Error E = I.getRVA(RVA)) + reportError(std::move(E), Obj->getFileName()); + if (Error E = I.getType(Type)) + reportError(std::move(E), Obj->getFileName()); DictScope Import(W, "Entry"); W.printString("Type", getBaseRelocTypeName(Type)); W.printHex("Address", RVA); @@ -1882,7 +1890,7 @@ void COFFDumper::printResourceDirectoryTable( } void COFFDumper::printStackMap() const { - object::SectionRef StackMapSection; + SectionRef StackMapSection; for (auto Sec : Obj->sections()) { StringRef Name; if (Expected<StringRef> NameOrErr = Sec.getName()) @@ -1896,7 +1904,7 @@ void COFFDumper::printStackMap() const { } } - if (StackMapSection == object::SectionRef()) + if (StackMapSection == SectionRef()) return; StringRef StackMapContents = @@ -1913,7 +1921,7 @@ void COFFDumper::printStackMap() const { } void COFFDumper::printAddrsig() { - object::SectionRef AddrsigSection; + SectionRef AddrsigSection; for (auto Sec : Obj->sections()) { StringRef Name; if (Expected<StringRef> NameOrErr = Sec.getName()) @@ -1927,7 +1935,7 @@ void COFFDumper::printAddrsig() { } } - if (AddrsigSection == object::SectionRef()) + if (AddrsigSection == SectionRef()) return; StringRef AddrsigContents = @@ -1945,19 +1953,58 @@ void COFFDumper::printAddrsig() { if (Err) reportError(createError(Err), Obj->getFileName()); - Expected<COFFSymbolRef> Sym = Obj->getSymbol(SymIndex); - if (!Sym) - reportError(Sym.takeError(), Obj->getFileName()); + W.printNumber("Sym", getSymbolName(SymIndex), SymIndex); + Cur += Size; + } +} - StringRef SymName; - if (std::error_code EC = Obj->getSymbolName(*Sym, SymName)) - reportError(errorCodeToError(EC), Obj->getFileName()); +void COFFDumper::printCGProfile() { + SectionRef CGProfileSection; + for (SectionRef Sec : Obj->sections()) { + StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName()); + if (Name == ".llvm.call-graph-profile") { + CGProfileSection = Sec; + break; + } + } - W.printNumber("Sym", SymName, SymIndex); - Cur += Size; + if (CGProfileSection == SectionRef()) + return; + + StringRef CGProfileContents = + unwrapOrError(Obj->getFileName(), CGProfileSection.getContents()); + BinaryStreamReader Reader(CGProfileContents, llvm::support::little); + + ListScope L(W, "CGProfile"); + while (!Reader.empty()) { + uint32_t FromIndex, ToIndex; + uint64_t Count; + if (Error Err = Reader.readInteger(FromIndex)) + reportError(std::move(Err), Obj->getFileName()); + if (Error Err = Reader.readInteger(ToIndex)) + reportError(std::move(Err), Obj->getFileName()); + if (Error Err = Reader.readInteger(Count)) + reportError(std::move(Err), Obj->getFileName()); + + DictScope D(W, "CGProfileEntry"); + W.printNumber("From", getSymbolName(FromIndex), FromIndex); + W.printNumber("To", getSymbolName(ToIndex), ToIndex); + W.printNumber("Weight", Count); } } +StringRef COFFDumper::getSymbolName(uint32_t Index) { + Expected<COFFSymbolRef> Sym = Obj->getSymbol(Index); + if (!Sym) + reportError(Sym.takeError(), Obj->getFileName()); + + Expected<StringRef> SymName = Obj->getSymbolName(*Sym); + if (!SymName) + reportError(SymName.takeError(), Obj->getFileName()); + + return *SymName; +} + void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer, ArrayRef<ArrayRef<uint8_t>> IpiRecords, ArrayRef<ArrayRef<uint8_t>> TpiRecords) { |