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
--- /dev/null
+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
return EC;
}
+ if (opts::dump::DumpSectionHeaders) {
+ if (auto EC = dumpSectionHeaders())
+ return EC;
+ }
+
if (opts::dump::DumpSectionContribs) {
if (auto EC = dumpSectionContribs())
return EC;
}
static std::string formatSectionCharacteristics(uint32_t IndentLevel,
- uint32_t C) {
+ uint32_t C,
+ uint32_t FlagsPerLine,
+ StringRef Separator) {
using SC = COFF::SectionCharacteristics;
std::vector<std::string> Opts;
if (C == COFF::SC_Invalid)
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,
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<object::coff_section> 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: ");
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 "
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:
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));
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include <string>
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<codeview::LazyRandomTypeCollection> TpiTypes;
cl::sub(DumpSubcommand));
cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
+ cl::desc("Dump image section headers"),
+ cl::cat(MiscOptions), cl::sub(DumpSubcommand));
cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
cl::cat(MiscOptions), cl::sub(DumpSubcommand));
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;
extern llvm::cl::opt<bool> DumpTypeExtras;
extern llvm::cl::list<uint32_t> DumpTypeIndex;
extern llvm::cl::opt<bool> DumpTypeDependents;
+extern llvm::cl::opt<bool> DumpSectionHeaders;
extern llvm::cl::opt<bool> DumpIds;
extern llvm::cl::opt<bool> DumpIdData;