aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-readobj/COFFDumper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-readobj/COFFDumper.cpp')
-rw-r--r--llvm/tools/llvm-readobj/COFFDumper.cpp265
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) {