[llvm-pdbutil] Dump image section headers.

Image section headers are stored in the DBI stream, but we
had no way to dump them.  This patch adds dumping support,
along with some tests that LLD actually dumps them correctly.

Differential Revision: https://reviews.llvm.org/D36332

llvm-svn: 310107
This commit is contained in:
Zachary Turner 2017-08-04 20:02:38 +00:00
parent 9cb37f0db2
commit 83e6215a4e
6 changed files with 167 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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<std::string> 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<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: ");
@ -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));

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include <string>
@ -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<codeview::LazyRandomTypeCollection> TpiTypes;

View File

@ -518,6 +518,9 @@ cl::opt<bool> DumpSectionContribs("section-contribs",
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));
@ -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;

View File

@ -139,6 +139,7 @@ extern llvm::cl::opt<bool> DumpTypeData;
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;