diff --git a/test/DebugInfo/PDB/pdbdump-headers.test b/test/DebugInfo/PDB/pdbdump-headers.test index bbf500233b2..92bb9b8087e 100644 --- a/test/DebugInfo/PDB/pdbdump-headers.test +++ b/test/DebugInfo/PDB/pdbdump-headers.test @@ -534,19 +534,19 @@ ALL-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IM ALL-NEXT: IMAGE_SCN_MEM_WRITE ALL: Section Map ALL-NEXT: ============================================================ -ALL-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1 +ALL-NEXT: Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535 ALL-NEXT: class = 65535, offset = 0, size = 4122 ALL-NEXT: flags = read | execute | 32 bit addr | selector -ALL-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2 +ALL-NEXT: Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535 ALL-NEXT: class = 65535, offset = 0, size = 690 ALL-NEXT: flags = read | 32 bit addr | selector -ALL-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3 +ALL-NEXT: Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535 ALL-NEXT: class = 65535, offset = 0, size = 4 ALL-NEXT: flags = read | write | 32 bit addr | selector -ALL-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4 +ALL-NEXT: Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535 ALL-NEXT: class = 65535, offset = 0, size = 8 ALL-NEXT: flags = read | 32 bit addr | selector -ALL-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 0 +ALL-NEXT: Section 0004 | ovl = 0, group = 0, frame = 0, name = 65535 ALL-NEXT: class = 65535, offset = 0, size = 4294967295 ALL-NEXT: flags = 32 bit addr | absolute addr diff --git a/test/DebugInfo/PDB/section-headers.test b/test/DebugInfo/PDB/section-headers.test new file mode 100644 index 00000000000..a4b4ba427c1 --- /dev/null +++ b/test/DebugInfo/PDB/section-headers.test @@ -0,0 +1,66 @@ +RUN: llvm-pdbutil dump -section-headers %p/Inputs/empty.pdb | FileCheck %s + +CHECK: Section Headers +CHECK-NEXT: ============================================================ +CHECK-LABEL: SECTION HEADER #1 +CHECK-NEXT: .text name +CHECK-NEXT: 101A virtual size +CHECK-NEXT: 1000 virtual address +CHECK-NEXT: 1200 size of raw data +CHECK-NEXT: 400 file pointer to raw data +CHECK-NEXT: 0 file pointer to relocation table +CHECK-NEXT: 0 file pointer to line numbers +CHECK-NEXT: 0 number of relocations +CHECK-NEXT: 0 number of line numbers +CHECK-NEXT: 60000020 flags +CHECK-NEXT: IMAGE_SCN_CNT_CODE +CHECK-NEXT: IMAGE_SCN_MEM_EXECUTE +CHECK-NEXT: IMAGE_SCN_MEM_READ + +CHECK-LABEL: SECTION HEADER #2 +CHECK-NEXT: .rdata name +CHECK-NEXT: 2B2 virtual size +CHECK-NEXT: 3000 virtual address +CHECK-NEXT: 400 size of raw data +CHECK-NEXT: 1600 file pointer to raw data +CHECK-NEXT: 0 file pointer to relocation table +CHECK-NEXT: 0 file pointer to line numbers +CHECK-NEXT: 0 number of relocations +CHECK-NEXT: 0 number of line numbers +CHECK-NEXT: 40000040 flags +CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +CHECK-NEXT: IMAGE_SCN_MEM_READ + +CHECK-LABEL: SECTION HEADER #3 +CHECK-NEXT: .data name +CHECK-NEXT: 4 virtual size +CHECK-NEXT: 4000 virtual address +CHECK-NEXT: 0 size of raw data +CHECK-NEXT: 0 file pointer to raw data +CHECK-NEXT: 0 file pointer to relocation table +CHECK-NEXT: 0 file pointer to line numbers +CHECK-NEXT: 0 number of relocations +CHECK-NEXT: 0 number of line numbers +CHECK-NEXT: C0000040 flags +CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +CHECK-NEXT: IMAGE_SCN_MEM_READ +CHECK-NEXT: IMAGE_SCN_MEM_WRITE + +CHECK-LABEL: SECTION HEADER #4 +CHECK-NEXT: .reloc name +CHECK-NEXT: 8 virtual size +CHECK-NEXT: 5000 virtual address +CHECK-NEXT: 200 size of raw data +CHECK-NEXT: 1A00 file pointer to raw data +CHECK-NEXT: 0 file pointer to relocation table +CHECK-NEXT: 0 file pointer to line numbers +CHECK-NEXT: 0 number of relocations +CHECK-NEXT: 0 number of line numbers +CHECK-NEXT: 42000040 flags +CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +CHECK-NEXT: IMAGE_SCN_MEM_DISCARDABLE +CHECK-NEXT: IMAGE_SCN_MEM_READ + +CHECK: Original Section Headers +CHECK-NEXT: ============================================================ +CHECK-NEXT: PDB does not contain the requested image section header type diff --git a/tools/llvm-pdbutil/DumpOutputStyle.cpp b/tools/llvm-pdbutil/DumpOutputStyle.cpp index 248e0de675e..6797adfc8f8 100644 --- a/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -145,6 +145,11 @@ Error DumpOutputStyle::dump() { return EC; } + if (opts::dump::DumpSectionHeaders) { + if (auto EC = dumpSectionHeaders()) + return EC; + } + if (opts::dump::DumpSectionContribs) { if (auto EC = dumpSectionContribs()) return EC; @@ -974,7 +979,9 @@ Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table, } static std::string formatSectionCharacteristics(uint32_t IndentLevel, - uint32_t C) { + uint32_t C, + uint32_t FlagsPerLine, + StringRef Separator) { using SC = COFF::SectionCharacteristics; std::vector Opts; if (C == COFF::SC_Invalid) @@ -1036,7 +1043,7 @@ static std::string formatSectionCharacteristics(uint32_t IndentLevel, PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE"); PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ"); PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE"); - return typesetItemList(Opts, IndentLevel, 3, " | "); + return typesetItemList(Opts, IndentLevel, FlagsPerLine, Separator); } static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel, @@ -1055,6 +1062,79 @@ static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel, return typesetItemList(Opts, IndentLevel, 4, " | "); } +Error DumpOutputStyle::dumpSectionHeaders() { + dumpSectionHeaders("Section Headers", DbgHeaderType::SectionHdr); + dumpSectionHeaders("Original Section Headers", DbgHeaderType::SectionHdrOrig); + return Error::success(); +} + +void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) { + printHeader(P, Label); + ExitOnError Err("Error dumping publics stream: "); + + AutoIndent Indent(P); + if (!File.hasPDBDbiStream()) { + P.formatLine( + "Section headers require a DBI Stream, which could not be loaded"); + return; + } + + auto &Dbi = Err(File.getPDBDbiStream()); + uint32_t SI = Dbi.getDebugStreamIndex(Type); + + if (SI == kInvalidStreamIndex) { + P.formatLine( + "PDB does not contain the requested image section header type"); + return; + } + + auto Stream = MappedBlockStream::createIndexedStream( + File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator()); + if (!Stream) { + P.formatLine("Could not load the required stream data"); + return; + } + ArrayRef Headers; + if (Stream->getLength() % sizeof(object::coff_section) != 0) { + P.formatLine( + "Section header array size is not a multiple of section header size"); + return; + } + uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section); + BinaryStreamReader Reader(*Stream); + cantFail(Reader.readArray(Headers, NumHeaders)); + if (Headers.empty()) { + P.formatLine("No section headers"); + return; + } + + uint32_t I = 1; + for (const auto &Header : Headers) { + P.NewLine(); + P.formatLine("SECTION HEADER #{0}", I); + P.formatLine("{0,8} name", Header.Name); + P.formatLine("{0,8:X-} virtual size", uint32_t(Header.VirtualSize)); + P.formatLine("{0,8:X-} virtual address", uint32_t(Header.VirtualAddress)); + P.formatLine("{0,8:X-} size of raw data", uint32_t(Header.SizeOfRawData)); + P.formatLine("{0,8:X-} file pointer to raw data", + uint32_t(Header.PointerToRawData)); + P.formatLine("{0,8:X-} file pointer to relocation table", + uint32_t(Header.PointerToRelocations)); + P.formatLine("{0,8:X-} file pointer to line numbers", + uint32_t(Header.PointerToLinenumbers)); + P.formatLine("{0,8:X-} number of relocations", + uint32_t(Header.NumberOfRelocations)); + P.formatLine("{0,8:X-} number of line numbers", + uint32_t(Header.NumberOfLinenumbers)); + P.formatLine("{0,8:X-} flags", uint32_t(Header.Characteristics)); + AutoIndent IndentMore(P, 9); + P.formatLine("{0}", formatSectionCharacteristics( + P.getIndentLevel(), Header.Characteristics, 1, "")); + ++I; + } + return; +} + Error DumpOutputStyle::dumpSectionContribs() { printHeader(P, "Section Contributions"); ExitOnError Err("Error dumping publics stream: "); @@ -1078,7 +1158,7 @@ Error DumpOutputStyle::dumpSectionContribs() { fmtle(SC.DataCrc), fmtle(SC.RelocCrc)); P.formatLine(" {0}", formatSectionCharacteristics(P.getIndentLevel() + 6, - SC.Characteristics)); + SC.Characteristics, 3, " | ")); } void visit(const SectionContrib2 &SC) override { P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc " @@ -1087,9 +1167,9 @@ Error DumpOutputStyle::dumpSectionContribs() { fmtle(SC.Base.Size), fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc), fmtle(SC.ISectCoff)); - P.formatLine(" {0}", - formatSectionCharacteristics(P.getIndentLevel() + 6, - SC.Base.Characteristics)); + P.formatLine(" {0}", formatSectionCharacteristics( + P.getIndentLevel() + 6, + SC.Base.Characteristics, 3, " | ")); } private: @@ -1117,7 +1197,7 @@ Error DumpOutputStyle::dumpSectionMap() { uint32_t I = 0; for (auto &M : Dbi.getSectionMap()) { P.formatLine( - "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I, + "Section {0:4} | ovl = {1}, group = {2}, frame = {3}, name = {4}", I, fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName)); P.formatLine(" class = {0}, offset = {1}, size = {2}", fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength)); diff --git a/tools/llvm-pdbutil/DumpOutputStyle.h b/tools/llvm-pdbutil/DumpOutputStyle.h index d1d3e1d4892..383388f1b15 100644 --- a/tools/llvm-pdbutil/DumpOutputStyle.h +++ b/tools/llvm-pdbutil/DumpOutputStyle.h @@ -15,6 +15,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include @@ -51,9 +52,12 @@ private: Error dumpGlobals(); Error dumpPublics(); Error dumpSymbolsFromGSI(const GSIHashTable &Table, bool HashExtras); + Error dumpSectionHeaders(); Error dumpSectionContribs(); Error dumpSectionMap(); + void dumpSectionHeaders(StringRef Label, DbgHeaderType Type); + PDBFile &File; LinePrinter P; std::unique_ptr TpiTypes; diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp index 1cf9a86b1ea..75560b3f937 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -518,6 +518,9 @@ cl::opt DumpSectionContribs("section-contribs", cl::sub(DumpSubcommand)); cl::opt DumpSectionMap("section-map", cl::desc("dump section map"), cl::cat(MiscOptions), cl::sub(DumpSubcommand)); +cl::opt DumpSectionHeaders("section-headers", + cl::desc("Dump image section headers"), + cl::cat(MiscOptions), cl::sub(DumpSubcommand)); cl::opt RawAll("all", cl::desc("Implies most other options."), cl::cat(MiscOptions), cl::sub(DumpSubcommand)); @@ -1092,6 +1095,7 @@ int main(int argc_, const char *argv_[]) { opts::dump::DumpStreams = true; opts::dump::DumpStreamBlocks = true; opts::dump::DumpStringTable = true; + opts::dump::DumpSectionHeaders = true; opts::dump::DumpSummary = true; opts::dump::DumpSymbols = true; opts::dump::DumpIds = true; diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h index ccdb992db38..621c9fad437 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -139,6 +139,7 @@ extern llvm::cl::opt DumpTypeData; extern llvm::cl::opt DumpTypeExtras; extern llvm::cl::list DumpTypeIndex; extern llvm::cl::opt DumpTypeDependents; +extern llvm::cl::opt DumpSectionHeaders; extern llvm::cl::opt DumpIds; extern llvm::cl::opt DumpIdData;