Index: lld/trunk/test/COFF/pdb.test =================================================================== --- lld/trunk/test/COFF/pdb.test +++ lld/trunk/test/COFF/pdb.test @@ -6,7 +6,7 @@ # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \ # RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s -# RUN: llvm-pdbutil dump -modules -section-map -section-contribs \ +# RUN: llvm-pdbutil dump -modules -section-map -section-contribs -section-headers \ # RUN: -publics -public-extras -types -ids -type-extras -id-extras %t.pdb \ # RUN: | FileCheck -check-prefix RAW %s @@ -188,6 +188,64 @@ RAW-NEXT: Address Map RAW-NEXT: off = 20 RAW-NEXT: off = 0 +RAW: Section Headers +RAW-NEXT: ============================================================ +RAW: SECTION HEADER #1 +RAW-NEXT: .pdata name +RAW-NEXT: C virtual size +RAW-NEXT: 1000 virtual address +RAW-NEXT: 200 size of raw data +RAW-NEXT: 400 file pointer to raw data +RAW-NEXT: 0 file pointer to relocation table +RAW-NEXT: 0 file pointer to line numbers +RAW-NEXT: 0 number of relocations +RAW-NEXT: 0 number of line numbers +RAW-NEXT: 40000040 flags +RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW: SECTION HEADER #2 +RAW-NEXT: .text name +RAW-NEXT: 16 virtual size +RAW-NEXT: 2000 virtual address +RAW-NEXT: 200 size of raw data +RAW-NEXT: 600 file pointer to raw data +RAW-NEXT: 0 file pointer to relocation table +RAW-NEXT: 0 file pointer to line numbers +RAW-NEXT: 0 number of relocations +RAW-NEXT: 0 number of line numbers +RAW-NEXT: 60000020 flags +RAW-NEXT: IMAGE_SCN_CNT_CODE +RAW-NEXT: IMAGE_SCN_MEM_EXECUTE +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW: SECTION HEADER #3 +RAW-NEXT: .xdata name +RAW-NEXT: 8 virtual size +RAW-NEXT: 3000 virtual address +RAW-NEXT: 200 size of raw data +RAW-NEXT: 800 file pointer to raw data +RAW-NEXT: 0 file pointer to relocation table +RAW-NEXT: 0 file pointer to line numbers +RAW-NEXT: 0 number of relocations +RAW-NEXT: 0 number of line numbers +RAW-NEXT: 40000040 flags +RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW: SECTION HEADER #4 +RAW-NEXT: .rdata name +RAW-NEXT: 77 virtual size +RAW-NEXT: 4000 virtual address +RAW-NEXT: 200 size of raw data +RAW-NEXT: A00 file pointer to raw data +RAW-NEXT: 0 file pointer to relocation table +RAW-NEXT: 0 file pointer to line numbers +RAW-NEXT: 0 number of relocations +RAW-NEXT: 0 number of line numbers +RAW-NEXT: 40000040 flags +RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +RAW-NEXT: IMAGE_SCN_MEM_READ +RAW: Original Section Headers +RAW-NEXT: ============================================================ +RAW-NEXT: PDB does not contain the requested image section header type RAW: Section Contributions RAW-NEXT: ============================================================ RAW-NEXT: SC | mod = 0, 0001:0000, size = 12, data crc = 0, reloc crc = 0 @@ -202,18 +260,18 @@ RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ RAW: Section Map RAW-NEXT: ============================================================ -RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1 +RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535 RAW-NEXT: class = 65535, offset = 0, size = RAW-NEXT: flags = read | 32 bit addr | selector -RAW-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2 +RAW-NEXT: Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535 RAW-NEXT: class = 65535, offset = 0, size = RAW-NEXT: flags = read | execute | 32 bit addr | selector -RAW-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3 +RAW-NEXT: Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535 RAW-NEXT: class = 65535, offset = 0, size = RAW-NEXT: flags = read | 32 bit addr | selector -RAW-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4 +RAW-NEXT: Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535 RAW-NEXT: class = 65535, offset = 0, size = RAW-NEXT: flags = read | 32 bit addr | selector -RAW-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 5 +RAW-NEXT: Section 0004 | ovl = 0, group = 0, frame = 5, name = 65535 RAW-NEXT: class = 65535, offset = 0, size = RAW-NEXT: flags = 32 bit addr | absolute addr Index: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test +++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test @@ -534,19 +534,19 @@ 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 Index: llvm/trunk/test/DebugInfo/PDB/section-headers.test =================================================================== --- llvm/trunk/test/DebugInfo/PDB/section-headers.test +++ llvm/trunk/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 Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h =================================================================== --- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h +++ llvm/trunk/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 @@ 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; Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -145,6 +145,11 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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)); Index: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h =================================================================== --- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h +++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h @@ -139,6 +139,7 @@ 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; Index: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -518,6 +518,9 @@ 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 @@ 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;