diff --git a/llvm/test/tools/llvm-pdbutil/dbi-section-headers.test b/llvm/test/tools/llvm-pdbutil/dbi-section-headers.test new file mode 100644 index 0000000000000..ea063d7a1dfb8 --- /dev/null +++ b/llvm/test/tools/llvm-pdbutil/dbi-section-headers.test @@ -0,0 +1,131 @@ +# RUN: llvm-pdbutil yaml2pdb %s --pdb=%t.pdb +# RUN: llvm-pdbutil dump --section-headers --section-map %t.pdb | FileCheck --check-prefix=CHECK-YAML2PDB %s + +# RUN: llvm-pdbutil pdb2yaml --section-headers %t.pdb > %t.yaml +# RUN: FileCheck --input-file=%t.yaml --check-prefix=CHECK-PDB2YAML %s + +# CHECK-YAML2PDB: Section Headers +# CHECK-YAML2PDB: SECTION HEADER #1 +# CHECK-YAML2PDB: .text name +# CHECK-YAML2PDB: 47 virtual size +# CHECK-YAML2PDB: 1000 virtual address +# CHECK-YAML2PDB: 200 size of raw data +# CHECK-YAML2PDB: 400 file pointer to raw data +# CHECK-YAML2PDB: 0 file pointer to relocation table +# CHECK-YAML2PDB: 0 file pointer to line numbers +# CHECK-YAML2PDB: 0 number of relocations +# CHECK-YAML2PDB: 0 number of line numbers +# CHECK-YAML2PDB: 60000020 flags +# CHECK-YAML2PDB: IMAGE_SCN_CNT_CODE +# CHECK-YAML2PDB: IMAGE_SCN_MEM_EXECUTE +# CHECK-YAML2PDB: IMAGE_SCN_MEM_READ + +# CHECK-YAML2PDB: SECTION HEADER #2 +# CHECK-YAML2PDB: .rdata name +# CHECK-YAML2PDB: 64 virtual size +# CHECK-YAML2PDB: 2000 virtual address +# CHECK-YAML2PDB: 200 size of raw data +# CHECK-YAML2PDB: 600 file pointer to raw data +# CHECK-YAML2PDB: 0 file pointer to relocation table +# CHECK-YAML2PDB: 0 file pointer to line numbers +# CHECK-YAML2PDB: 0 number of relocations +# CHECK-YAML2PDB: 0 number of line numbers +# CHECK-YAML2PDB: 40000040 flags +# CHECK-YAML2PDB: IMAGE_SCN_CNT_INITIALIZED_DATA +# CHECK-YAML2PDB: IMAGE_SCN_MEM_READ + +# CHECK-YAML2PDB: SECTION HEADER #3 +# CHECK-YAML2PDB: .pdata name +# CHECK-YAML2PDB: 18 virtual size +# CHECK-YAML2PDB: 3000 virtual address +# CHECK-YAML2PDB: 200 size of raw data +# CHECK-YAML2PDB: 800 file pointer to raw data +# CHECK-YAML2PDB: 0 file pointer to relocation table +# CHECK-YAML2PDB: 0 file pointer to line numbers +# CHECK-YAML2PDB: 0 number of relocations +# CHECK-YAML2PDB: 0 number of line numbers +# CHECK-YAML2PDB: 40000040 flags +# CHECK-YAML2PDB: IMAGE_SCN_CNT_INITIALIZED_DATA +# CHECK-YAML2PDB: IMAGE_SCN_MEM_READ + +# CHECK-YAML2PDB: Section Map +# CHECK-YAML2PDB: Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535 +# CHECK-YAML2PDB: class = 65535, offset = 0, size = 71 +# CHECK-YAML2PDB: flags = read | execute | 32 bit addr | selector +# CHECK-YAML2PDB: Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535 +# CHECK-YAML2PDB: class = 65535, offset = 0, size = 100 +# CHECK-YAML2PDB: flags = read | 32 bit addr | selector +# CHECK-YAML2PDB: Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535 +# CHECK-YAML2PDB: class = 65535, offset = 0, size = 24 +# CHECK-YAML2PDB: flags = read | 32 bit addr | selector +# CHECK-YAML2PDB: Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535 +# CHECK-YAML2PDB: class = 65535, offset = 0, size = 4294967295 +# CHECK-YAML2PDB: flags = 32 bit addr | absolute addr + +# CHECK-PDB2YAML:DbiStream: +# CHECK-PDB2YAML: SectionHeaders: +# CHECK-PDB2YAML: - Name: .text +# CHECK-PDB2YAML: VirtualSize: 71 +# CHECK-PDB2YAML: VirtualAddress: 4096 +# CHECK-PDB2YAML: SizeOfRawData: 512 +# CHECK-PDB2YAML: PointerToRawData: 1024 +# CHECK-PDB2YAML: PointerToRelocations: 0 +# CHECK-PDB2YAML: PointerToLinenumbers: 0 +# CHECK-PDB2YAML: NumberOfRelocations: 0 +# CHECK-PDB2YAML: NumberOfLinenumbers: 0 +# CHECK-PDB2YAML: Characteristics: 1610612768 +# CHECK-PDB2YAML: - Name: .rdata +# CHECK-PDB2YAML: VirtualSize: 100 +# CHECK-PDB2YAML: VirtualAddress: 8192 +# CHECK-PDB2YAML: SizeOfRawData: 512 +# CHECK-PDB2YAML: PointerToRawData: 1536 +# CHECK-PDB2YAML: PointerToRelocations: 0 +# CHECK-PDB2YAML: PointerToLinenumbers: 0 +# CHECK-PDB2YAML: NumberOfRelocations: 0 +# CHECK-PDB2YAML: NumberOfLinenumbers: 0 +# CHECK-PDB2YAML: Characteristics: 1073741888 +# CHECK-PDB2YAML: - Name: .pdata +# CHECK-PDB2YAML: VirtualSize: 24 +# CHECK-PDB2YAML: VirtualAddress: 12288 +# CHECK-PDB2YAML: SizeOfRawData: 512 +# CHECK-PDB2YAML: PointerToRawData: 2048 +# CHECK-PDB2YAML: PointerToRelocations: 0 +# CHECK-PDB2YAML: PointerToLinenumbers: 0 +# CHECK-PDB2YAML: NumberOfRelocations: 0 +# CHECK-PDB2YAML: NumberOfLinenumbers: 0 +# CHECK-PDB2YAML: Characteristics: 1073741888 + +--- +DbiStream: + SectionHeaders: + - Name: .text + VirtualSize: 71 + VirtualAddress: 4096 + SizeOfRawData: 512 + PointerToRawData: 1024 + PointerToRelocations: 0 + PointerToLinenumbers: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + Characteristics: 1610612768 + - Name: .rdata + VirtualSize: 100 + VirtualAddress: 8192 + SizeOfRawData: 512 + PointerToRawData: 1536 + PointerToRelocations: 0 + PointerToLinenumbers: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + Characteristics: 1073741888 + - Name: .pdata + VirtualSize: 24 + VirtualAddress: 12288 + SizeOfRawData: 512 + PointerToRawData: 2048 + PointerToRelocations: 0 + PointerToLinenumbers: 0 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + Characteristics: 1073741888 +... diff --git a/llvm/tools/llvm-pdbutil/PdbYaml.cpp b/llvm/tools/llvm-pdbutil/PdbYaml.cpp index fac1d89321610..4131292c5c908 100644 --- a/llvm/tools/llvm-pdbutil/PdbYaml.cpp +++ b/llvm/tools/llvm-pdbutil/PdbYaml.cpp @@ -22,6 +22,7 @@ using namespace llvm::pdb; using namespace llvm::pdb::yaml; using namespace llvm::yaml; +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::CoffSectionHeader) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) @@ -135,6 +136,49 @@ void MappingTraits::mapping(IO &IO, msf::SuperBlock &SB) { IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U)); } +CoffSectionHeader::CoffSectionHeader() = default; + +CoffSectionHeader::CoffSectionHeader(const object::coff_section &Section) + : Name(Section.Name), VirtualSize(Section.VirtualSize), + VirtualAddress(Section.VirtualAddress), + SizeOfRawData(Section.SizeOfRawData), + PointerToRawData(Section.PointerToRawData), + PointerToRelocations(Section.PointerToRelocations), + PointerToLinenumbers(Section.PointerToLinenumbers), + NumberOfRelocations(Section.NumberOfRelocations), + NumberOfLinenumbers(Section.NumberOfLinenumbers), + Characteristics(Section.Characteristics) {} + +object::coff_section CoffSectionHeader::toCoffSection() const { + object::coff_section Sec; + std::memset(Sec.Name, 0, COFF::NameSize); + std::memcpy(Sec.Name, Name.data(), + std::min(static_cast(COFF::NameSize), Name.size())); + Sec.VirtualSize = VirtualSize; + Sec.VirtualAddress = VirtualAddress; + Sec.SizeOfRawData = SizeOfRawData; + Sec.PointerToRawData = PointerToRawData; + Sec.PointerToRelocations = PointerToRelocations; + Sec.PointerToLinenumbers = PointerToLinenumbers; + Sec.NumberOfRelocations = NumberOfRelocations; + Sec.NumberOfLinenumbers = NumberOfLinenumbers; + Sec.Characteristics = Characteristics; + return Sec; +} + +void MappingTraits::mapping(IO &IO, CoffSectionHeader &Obj) { + IO.mapRequired("Name", Obj.Name); + IO.mapOptional("VirtualSize", Obj.VirtualSize); + IO.mapOptional("VirtualAddress", Obj.VirtualAddress); + IO.mapOptional("SizeOfRawData", Obj.SizeOfRawData); + IO.mapOptional("PointerToRawData", Obj.PointerToRawData); + IO.mapOptional("PointerToRelocations", Obj.PointerToRelocations); + IO.mapOptional("PointerToLinenumbers", Obj.PointerToLinenumbers); + IO.mapOptional("NumberOfRelocations", Obj.NumberOfRelocations); + IO.mapOptional("NumberOfLinenumbers", Obj.NumberOfLinenumbers); + IO.mapOptional("Characteristics", Obj.Characteristics); +} + void MappingTraits::mapping(IO &IO, StreamBlockList &SB) { IO.mapRequired("Stream", SB.Blocks); } @@ -163,6 +207,7 @@ void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) { IO.setContext(&Obj.FakeHeader); } IO.mapOptional("Modules", Obj.ModInfos); + IO.mapOptional("SectionHeaders", Obj.SectionHeaders); } void MappingTraits::mapping(IO &IO, diff --git a/llvm/tools/llvm-pdbutil/PdbYaml.h b/llvm/tools/llvm-pdbutil/PdbYaml.h index d5111a9e8d3a3..874667577218d 100644 --- a/llvm/tools/llvm-pdbutil/PdbYaml.h +++ b/llvm/tools/llvm-pdbutil/PdbYaml.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" #include "llvm/ObjectYAML/CodeViewYAMLTypes.h" @@ -40,6 +41,24 @@ struct MSFHeaders { uint64_t FileSize = 0; }; +struct CoffSectionHeader { + CoffSectionHeader(); + CoffSectionHeader(const object::coff_section &Section); + + object::coff_section toCoffSection() const; + + StringRef Name; + uint32_t VirtualSize = 0; + uint32_t VirtualAddress = 0; + uint32_t SizeOfRawData = 0; + uint32_t PointerToRawData = 0; + uint32_t PointerToRelocations = 0; + uint32_t PointerToLinenumbers = 0; + uint16_t NumberOfRelocations = 0; + uint16_t NumberOfLinenumbers = 0; + uint32_t Characteristics = 0; +}; + struct StreamBlockList { std::vector Blocks; }; @@ -82,6 +101,7 @@ struct PdbDbiStream { std::vector ModInfos; COFF::header FakeHeader; + std::vector SectionHeaders; }; struct PdbTpiStream { @@ -113,6 +133,7 @@ struct PdbObject { } } +LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::CoffSectionHeader) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::PdbObject) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(pdb::yaml::MSFHeaders) LLVM_YAML_DECLARE_MAPPING_TRAITS_PRIVATE(msf::SuperBlock) diff --git a/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp index ecb4c2175e49a..8fe7f600d173c 100644 --- a/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/YAMLOutputStyle.cpp @@ -285,6 +285,24 @@ Error YAMLOutputStyle::dumpDbiStream() { } } } + + if (opts::pdb2yaml::DumpSectionHeaders) { + for (const auto &Section : DS.getSectionHeaders()) { + yaml::CoffSectionHeader Hdr; + Hdr.Name = Section.Name; + Hdr.VirtualSize = Section.VirtualSize; + Hdr.VirtualAddress = Section.VirtualAddress; + Hdr.SizeOfRawData = Section.SizeOfRawData; + Hdr.PointerToRawData = Section.PointerToRawData; + Hdr.PointerToRelocations = Section.PointerToRelocations; + Hdr.PointerToLinenumbers = Section.PointerToLinenumbers; + Hdr.NumberOfRelocations = Section.NumberOfRelocations; + Hdr.NumberOfLinenumbers = Section.NumberOfLinenumbers; + Hdr.Characteristics = Section.Characteristics; + Obj.DbiStream->SectionHeaders.emplace_back(Hdr); + } + } + return Error::success(); } diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp index a5b8e8b7941d7..befd33171ed0a 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -716,6 +716,10 @@ cl::list DumpModuleSubsections( cl::opt DumpModuleSyms("module-syms", cl::desc("dump module symbols"), cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand)); +cl::opt DumpSectionHeaders("section-headers", + cl::desc("Dump section headers."), + cl::cat(FileOptions), + cl::sub(PdbToYamlSubcommand)); cl::list InputFilename(cl::Positional, cl::desc(""), cl::Required, @@ -865,6 +869,20 @@ static void yamlToPdb(StringRef Path) { } } + std::vector Sections; + if (!Dbi.SectionHeaders.empty()) { + for (const auto &Hdr : Dbi.SectionHeaders) + Sections.emplace_back(Hdr.toCoffSection()); + + DbiBuilder.createSectionMap(Sections); + ExitOnErr(DbiBuilder.addDbgStream( + pdb::DbgHeaderType::SectionHdr, + // FIXME: Downcasting to an ArrayRef should use a helper + // function in LLVM + ArrayRef{(const uint8_t *)Sections.data(), + Sections.size() * sizeof(object::coff_section)})); + } + auto &TpiBuilder = Builder.getTpiBuilder(); const auto &Tpi = YamlObj.TpiStream.value_or(DefaultTpiStream); TpiBuilder.setVersionHeader(Tpi.Version); @@ -1541,6 +1559,7 @@ int main(int Argc, const char **Argv) { opts::pdb2yaml::DumpModules = true; opts::pdb2yaml::DumpModuleFiles = true; opts::pdb2yaml::DumpModuleSyms = true; + opts::pdb2yaml::DumpSectionHeaders = true; opts::pdb2yaml::DumpModuleSubsections.push_back( opts::ModuleSubsection::All); } @@ -1551,6 +1570,9 @@ int main(int Argc, const char **Argv) { if (opts::pdb2yaml::DumpModules) opts::pdb2yaml::DbiStream = true; + + if (opts::pdb2yaml::DumpSectionHeaders) + opts::pdb2yaml::DbiStream = true; } llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h index b8c803324b39e..73ff2fe86f93a 100644 --- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.h @@ -201,6 +201,7 @@ extern llvm::cl::opt DumpModules; extern llvm::cl::opt DumpModuleFiles; extern llvm::cl::list DumpModuleSubsections; extern llvm::cl::opt DumpModuleSyms; +extern llvm::cl::opt DumpSectionHeaders; } // namespace pdb2yaml namespace explain {