Index: include/llvm/DebugInfo/PDB/Raw/PDBFile.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -20,10 +20,19 @@ namespace llvm { class MemoryBuffer; +namespace codeview { +template class FixedStreamArray; +} + +namespace object { +struct coff_section; +} + namespace pdb { struct PDBFileContext; class DbiStream; class InfoStream; +class MappedBlockStream; class PublicsStream; class SymbolStream; class TpiStream; @@ -67,6 +76,8 @@ Expected getPDBIpiStream(); Expected getPDBPublicsStream(); Expected getPDBSymbolStream(); + Expected> + getPDBSectionHeaders(); private: std::unique_ptr Context; @@ -76,6 +87,7 @@ std::unique_ptr Ipi; std::unique_ptr Publics; std::unique_ptr Symbols; + std::unique_ptr SectionHeaders; }; } } Index: lib/DebugInfo/PDB/Raw/PDBFile.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -9,12 +9,15 @@ #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/StreamArray.h" +#include "llvm/DebugInfo/CodeView/StreamReader.h" #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -332,3 +335,27 @@ } return *Symbols; } + +Expected> +PDBFile::getPDBSectionHeaders() { + if (!SectionHeaders) { + auto DbiS = getPDBDbiStream(); + if (auto EC = DbiS.takeError()) + return std::move(EC); + uint32_t StreamNum = DbiS->getDebugStreamIndex(DbgHeaderType::SectionHdr); + SectionHeaders.reset(new MappedBlockStream(StreamNum, *this)); + } + + size_t StreamLen = SectionHeaders->getLength(); + if (StreamLen % sizeof(object::coff_section)) + return make_error(raw_error_code::corrupt_file, + "Corrupted section header stream."); + + size_t NumSections = StreamLen / sizeof(object::coff_section); + codeview::StreamReader Reader(*SectionHeaders); + codeview::FixedStreamArray Sections; + if (auto EC = Reader.readArray(Sections, NumSections)) + return make_error(raw_error_code::corrupt_file, + "Could not read a bitmap."); + return Sections; +} Index: test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- test/DebugInfo/PDB/pdbdump-headers.test +++ test/DebugInfo/PDB/pdbdump-headers.test @@ -1,7 +1,7 @@ ; RUN: llvm-pdbdump -raw-headers -raw-tpi-records -raw-tpi-record-bytes -raw-module-syms \ ; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \ ; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \ -; RUN: %p/Inputs/empty.pdb \ +; RUN: -raw-section-headers %p/Inputs/empty.pdb \ ; RUN: | FileCheck -check-prefix=EMPTY %s ; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s ; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \ @@ -595,6 +595,56 @@ ; EMPTY-NEXT: } ; EMPTY-NEXT: ] ; EMPTY-NEXT: } +; EMPTY-NEXT: Section Headers [ +; EMPTY-NEXT: { +; EMPTY-NEXT: Name: .text +; EMPTY-NEXT: Virtual Size: 4122 +; EMPTY-NEXT: Virtual Address: 4096 +; EMPTY-NEXT: Size of Raw Data: 4608 +; EMPTY-NEXT: File Pointer to Raw Data: 1024 +; EMPTY-NEXT: File Pointer to Relocations: 0 +; EMPTY-NEXT: File Pointer to Linenumbers: 0 +; EMPTY-NEXT: Number of Relocations: 0 +; EMPTY-NEXT: Number of Linenumbers: 0 +; EMPTY-NEXT: Characteristics: 1610612768 +; EMPTY-NEXT: } +; EMPTY-NEXT: { +; EMPTY-NEXT: Name: .rdata +; EMPTY-NEXT: Virtual Size: 690 +; EMPTY-NEXT: Virtual Address: 12288 +; EMPTY-NEXT: Size of Raw Data: 1024 +; EMPTY-NEXT: File Pointer to Raw Data: 5632 +; EMPTY-NEXT: File Pointer to Relocations: 0 +; EMPTY-NEXT: File Pointer to Linenumbers: 0 +; EMPTY-NEXT: Number of Relocations: 0 +; EMPTY-NEXT: Number of Linenumbers: 0 +; EMPTY-NEXT: Characteristics: 1073741888 +; EMPTY-NEXT: } +; EMPTY-NEXT: { +; EMPTY-NEXT: Name: .data +; EMPTY-NEXT: Virtual Size: 4 +; EMPTY-NEXT: Virtual Address: 16384 +; EMPTY-NEXT: Size of Raw Data: 0 +; EMPTY-NEXT: File Pointer to Raw Data: 0 +; EMPTY-NEXT: File Pointer to Relocations: 0 +; EMPTY-NEXT: File Pointer to Linenumbers: 0 +; EMPTY-NEXT: Number of Relocations: 0 +; EMPTY-NEXT: Number of Linenumbers: 0 +; EMPTY-NEXT: Characteristics: 3221225536 +; EMPTY-NEXT: } +; EMPTY-NEXT: { +; EMPTY-NEXT: Name: .reloc +; EMPTY-NEXT: Virtual Size: 8 +; EMPTY-NEXT: Virtual Address: 20480 +; EMPTY-NEXT: Size of Raw Data: 512 +; EMPTY-NEXT: File Pointer to Raw Data: 6656 +; EMPTY-NEXT: File Pointer to Relocations: 0 +; EMPTY-NEXT: File Pointer to Linenumbers: 0 +; EMPTY-NEXT: Number of Relocations: 0 +; EMPTY-NEXT: Number of Linenumbers: 0 +; EMPTY-NEXT: Characteristics: 1107296320 +; EMPTY-NEXT: } +; EMPTY-NEXT: ] ; ALL: FileHeaders { ; ALL: BlockSize: 4096 @@ -876,7 +926,7 @@ ; ALL: { ; ALL: Name: * Linker * ; ALL: Debug Stream Index: 14 -; ALL: Object File Name: +; ALL: Object File Name: ; ALL: Num Files: 0 ; ALL: Source File Name Idx: 0 ; ALL: Pdb File Name Idx: 1 @@ -1063,6 +1113,56 @@ ; ALL: } ; ALL: ] ; ALL: } +; ALL: Section Headers [ +; ALL: { +; ALL: Name: .text +; ALL: Virtual Size: 4122 +; ALL: Virtual Address: 4096 +; ALL: Size of Raw Data: 4608 +; ALL: File Pointer to Raw Data: 1024 +; ALL: File Pointer to Relocations: 0 +; ALL: File Pointer to Linenumbers: 0 +; ALL: Number of Relocations: 0 +; ALL: Number of Linenumbers: 0 +; ALL: Characteristics: 1610612768 +; ALL: } +; ALL: { +; ALL: Name: .rdata +; ALL: Virtual Size: 690 +; ALL: Virtual Address: 12288 +; ALL: Size of Raw Data: 1024 +; ALL: File Pointer to Raw Data: 5632 +; ALL: File Pointer to Relocations: 0 +; ALL: File Pointer to Linenumbers: 0 +; ALL: Number of Relocations: 0 +; ALL: Number of Linenumbers: 0 +; ALL: Characteristics: 1073741888 +; ALL: } +; ALL: { +; ALL: Name: .data +; ALL: Virtual Size: 4 +; ALL: Virtual Address: 16384 +; ALL: Size of Raw Data: 0 +; ALL: File Pointer to Raw Data: 0 +; ALL: File Pointer to Relocations: 0 +; ALL: File Pointer to Linenumbers: 0 +; ALL: Number of Relocations: 0 +; ALL: Number of Linenumbers: 0 +; ALL: Characteristics: 3221225536 +; ALL: } +; ALL: { +; ALL: Name: .reloc +; ALL: Virtual Size: 8 +; ALL: Virtual Address: 20480 +; ALL: Size of Raw Data: 512 +; ALL: File Pointer to Raw Data: 6656 +; ALL: File Pointer to Relocations: 0 +; ALL: File Pointer to Linenumbers: 0 +; ALL: Number of Relocations: 0 +; ALL: Number of Linenumbers: 0 +; ALL: Characteristics: 1107296320 +; ALL: } +; ALL: ] ; BIG: FileHeaders { ; BIG-NEXT: BlockSize: 4096 Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -50,6 +50,7 @@ #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/RawSession.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" @@ -62,6 +63,8 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" +#include + #if defined(HAVE_DIA_SDK) #ifndef NOMINMAX #define NOMINMAX @@ -147,6 +150,10 @@ DumpSymRecordBytes("raw-sym-record-bytes", cl::desc("dump CodeView symbol record raw bytes"), cl::cat(NativeOptions)); +cl::opt DumpSectionHeaders("raw-section-headers", + cl::desc("dump section headers"), + cl::cat(NativeOptions)); + cl::opt RawAll("raw-all", cl::desc("Implies most other options in 'Native Options' category"), @@ -605,6 +612,34 @@ return Error::success(); } +static Error dumpSectionHeaders(ScopedPrinter &P, PDBFile &File, + codeview::CVTypeDumper &TD) { + if (!opts::DumpSectionHeaders) + return Error::success(); + + ListScope D(P, "Section Headers"); + auto SectionsS = File.getPDBSectionHeaders(); + if (auto EC = SectionsS.takeError()) + return EC; + for (const object::coff_section &Section : SectionsS.get()) { + DictScope DD(P, ""); + + // If a name is 8 characters long, there is no NUL character at end. + StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name))); + P.printString("Name", Name); + P.printNumber("Virtual Size", Section.VirtualSize); + P.printNumber("Virtual Address", Section.VirtualAddress); + P.printNumber("Size of Raw Data", Section.SizeOfRawData); + P.printNumber("File Pointer to Raw Data", Section.PointerToRawData); + P.printNumber("File Pointer to Relocations", Section.PointerToRelocations); + P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers); + P.printNumber("Number of Relocations", Section.NumberOfRelocations); + P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers); + P.printNumber("Characteristics", Section.Characteristics); + } + return Error::success(); +} + static Error dumpStructure(RawSession &RS) { PDBFile &File = RS.getPDBFile(); ScopedPrinter P(outs()); @@ -630,6 +665,7 @@ codeview::CVTypeDumper TD(P, false); if (auto EC = dumpTpiStream(P, File, TD, StreamTPI)) return EC; + if (auto EC = dumpTpiStream(P, File, TD, StreamIPI)) return EC; @@ -638,6 +674,9 @@ if (auto EC = dumpPublicsStream(P, File, TD)) return EC; + + if (auto EC = dumpSectionHeaders(P, File, TD)) + return EC; return Error::success(); } @@ -841,6 +880,7 @@ opts::DumpModuleFiles = true; opts::DumpModuleSyms = true; opts::DumpPublics = true; + opts::DumpSectionHeaders = true; opts::DumpStreamSummary = true; opts::DumpStreamBlocks = true; opts::DumpTpiRecords = true;