summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-06-02 17:10:43 +0000
committerReid Kleckner <rnk@google.com>2016-06-02 17:10:43 +0000
commit2da433ea997e0a48696c4b253894a796c6c1af9f (patch)
tree349ea66cddd93832785072b15b2fd76b170f8890 /llvm/tools
parent6393ef135ca804bef2f4519a38ef9d9d002750a9 (diff)
downloadbcm5719-llvm-2da433ea997e0a48696c4b253894a796c6c1af9f.tar.gz
bcm5719-llvm-2da433ea997e0a48696c4b253894a796c6c1af9f.zip
[COFF] Expose the PE debug data directory and dump it
This directory is used to find if there is a PDB associated with an executable. I plan to use this functionality to teach llvm-symbolizer whether it should use DIA or DWARF to symbolize a given DLL. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D20885 llvm-svn: 271539
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-readobj/COFFDumper.cpp56
-rw-r--r--llvm/tools/llvm-readobj/ObjDumper.h1
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.cpp7
3 files changed, 63 insertions, 1 deletions
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index fccfd465c57..306ebf90b87 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -75,6 +75,7 @@ public:
void printCOFFExports() override;
void printCOFFDirectives() override;
void printCOFFBaseReloc() override;
+ void printCOFFDebugDirectory() override;
void printCodeViewDebugInfo() override;
void
mergeCodeViewTypes(llvm::codeview::MemoryTypeTableBuilder &CVTypes) override;
@@ -475,6 +476,25 @@ static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
{ "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST }
};
+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 },
+ { "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 },
+ { "NoTimestamp", COFF::IMAGE_DEBUG_TYPE_NO_TIMESTAMP },
+};
+
static const EnumEntry<COFF::WeakExternalCharacteristics>
WeakExternalCharacteristics[] = {
{ "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
@@ -643,8 +663,42 @@ void COFFDumper::printPEHeader(const PEHeader *Hdr) {
"DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
};
- for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
+ for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i)
printDataDirectory(i, directory[i]);
+ }
+}
+
+void COFFDumper::printCOFFDebugDirectory() {
+ ListScope LS(W, "DebugDirectory");
+ for (const debug_directory &D : Obj->debug_directories()) {
+ char FormattedTime[20] = {};
+ time_t TDS = D.TimeDateStamp;
+ strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
+ DictScope S(W, "DebugEntry");
+ W.printHex("Characteristics", D.Characteristics);
+ W.printHex("TimeDateStamp", FormattedTime, D.TimeDateStamp);
+ W.printHex("MajorVersion", D.MajorVersion);
+ W.printHex("MinorVersion", D.MinorVersion);
+ W.printEnum("Type", D.Type, makeArrayRef(ImageDebugType));
+ W.printHex("SizeOfData", D.SizeOfData);
+ W.printHex("AddressOfRawData", D.AddressOfRawData);
+ W.printHex("PointerToRawData", D.PointerToRawData);
+ if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) {
+ const debug_pdb_info *PDBInfo;
+ StringRef PDBFileName;
+ error(Obj->getDebugPDBInfo(&D, PDBInfo, PDBFileName));
+ DictScope PDBScope(W, "PDBInfo");
+ W.printHex("PDBSignature", PDBInfo->Signature);
+ W.printBinary("PDBGUID", makeArrayRef(PDBInfo->Guid));
+ W.printNumber("PDBAge", PDBInfo->Age);
+ W.printString("PDBFileName", PDBFileName);
+ } else {
+ // FIXME: Type values of 12 and 13 are commonly observed but are not in
+ // the documented type enum. Figure out what they mean.
+ ArrayRef<uint8_t> RawData;
+ error(
+ Obj->getRvaAndSizeAsBytes(D.AddressOfRawData, D.SizeOfData, RawData));
+ W.printBinaryBlock("RawData", RawData);
}
}
}
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index c6f7c64ced5..a39fc260b54 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -62,6 +62,7 @@ public:
virtual void printCOFFExports() { }
virtual void printCOFFDirectives() { }
virtual void printCOFFBaseReloc() { }
+ virtual void printCOFFDebugDirectory() { }
virtual void printCodeViewDebugInfo() { }
virtual void
mergeCodeViewTypes(llvm::codeview::MemoryTypeTableBuilder &CVTypes) {}
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 386b32b6cc7..edeb8c95484 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -196,6 +196,11 @@ namespace opts {
COFFBaseRelocs("coff-basereloc",
cl::desc("Display the PE/COFF .reloc section"));
+ // -coff-debug-directory
+ cl::opt<bool>
+ COFFDebugDirectory("coff-debug-directory",
+ cl::desc("Display the PE/COFF debug directory"));
+
// -macho-data-in-code
cl::opt<bool>
MachODataInCode("macho-data-in-code",
@@ -392,6 +397,8 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printCOFFDirectives();
if (opts::COFFBaseRelocs)
Dumper->printCOFFBaseReloc();
+ if (opts::COFFDebugDirectory)
+ Dumper->printCOFFDebugDirectory();
if (opts::CodeView)
Dumper->printCodeViewDebugInfo();
if (opts::CodeViewMergedTypes)
OpenPOWER on IntegriCloud