From: Zachary Turner Date: Tue, 17 Apr 2018 20:06:43 +0000 (+0000) Subject: [llvm-pdbutil] Dump first section contribution for each module. X-Git-Tag: llvmorg-7.0.0-rc1~8032 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bee6c22414cd084df26621a1edf07ae1baa3002b;p=platform%2Fupstream%2Fllvm.git [llvm-pdbutil] Dump first section contribution for each module. The DBI stream contains a list of module descriptors. At the beginning of each descriptor is a structure representing the first section contribution in the output file for that module. LLD currently doesn't fill out this structure at all, but link.exe does. So as a precursor to emitting this data in LLD, we first need a way to dump it so that it can be checked. This patch adds support for the dumping, and verifies via a test that LLD emits bogus information. llvm-svn: 330208 --- diff --git a/lld/test/COFF/pdb.test b/lld/test/COFF/pdb.test index 20629f5..68ced0d 100644 --- a/lld/test/COFF/pdb.test +++ b/lld/test/COFF/pdb.test @@ -120,14 +120,20 @@ RAW: Modules RAW-NEXT: ============================================================ RAW-NEXT: Mod 0000 | `{{.*}}pdb.test.tmp1.obj`: +RAW-NEXT: SC[???] | mod = 0, 0000:0000, size = 0, data crc = 0, reloc crc = 0 +RAW-NEXT: none RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: RAW-NEXT: debug stream: 11, # files: 1, has ec info: false RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` RAW-NEXT: Mod 0001 | `{{.*}}pdb.test.tmp2.obj`: +RAW-NEXT: SC[???] | mod = 1, 0000:0000, size = 0, data crc = 0, reloc crc = 0 +RAW-NEXT: none RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: RAW-NEXT: debug stream: 12, # files: 1, has ec info: false RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` RAW-NEXT: Mod 0002 | `* Linker *`: +RAW-NEXT: SC[???] | mod = 2, 0000:0000, size = 0, data crc = 0, reloc crc = 0 +RAW-NEXT: none RAW-NEXT: Obj: ``: RAW-NEXT: debug stream: 13, # files: 0, has ec info: false RAW-NEXT: pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 `` diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h index 8200f51..9eef404 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -47,6 +47,8 @@ public: uint32_t getRecordLength() const; + const SectionContrib &getSectionContrib() const; + private: StringRef ModuleName; StringRef ObjFileName; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 04ea10d..19f592d 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -177,18 +177,6 @@ struct DbiStreamHeader { }; static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); -struct SectionContribEntry { - support::ulittle16_t Section; - char Padding1[2]; - support::little32_t Offset; - support::little32_t Size; - support::ulittle32_t Characteristics; - support::ulittle16_t ModuleIndex; - char Padding2[2]; - support::ulittle32_t DataCrc; - support::ulittle32_t RelocCrc; -}; - /// The header preceeding the File Info Substream of the DBI stream. struct FileInfoSubstreamHeader { /// Total # of modules, should match number of records in the ModuleInfo @@ -230,7 +218,7 @@ struct ModuleInfoHeader { support::ulittle32_t Mod; /// First section contribution of this module. - SectionContribEntry SC; + SectionContrib SC; /// See ModInfoFlags definition. support::ulittle16_t Flags; diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp index dabcc34..931ac7bb 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp @@ -49,6 +49,10 @@ uint16_t DbiModuleDescriptor::getTypeServerIndex() const { ModInfoFlags::TypeServerIndexShift; } +const SectionContrib &DbiModuleDescriptor::getSectionContrib() const { + return Layout->SC; +} + uint16_t DbiModuleDescriptor::getModuleStreamIndex() const { return Layout->ModDiStream; } diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index d765485..1da2c39 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -90,7 +90,7 @@ uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const { } void DbiModuleDescriptorBuilder::finalize() { - Layout.SC.ModuleIndex = Layout.Mod; + Layout.SC.Imod = Layout.Mod; Layout.FileNameOffs = 0; // TODO: Fix this Layout.Flags = 0; // TODO: Fix this Layout.C11Bytes = 0; diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index 23a250e..26c2b1bb 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -65,10 +65,15 @@ ALL-NEXT: 134 | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = ' ALL: Modules ALL-NEXT: ============================================================ ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: SC[.text] | mod = 0, 0001:0016, size = 10, data crc = 3617027124, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | +ALL-NEXT: IMAGE_SCN_MEM_READ ALL-NEXT: Obj: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: ALL-NEXT: debug stream: 12, # files: 1, has ec info: false ALL-NEXT: pdb file ni: 0 ``, src file ni: 0 `` ALL-NEXT: Mod 0001 | `* Linker *`: +ALL-NEXT: SC[.text] | mod = 1, 0001:0000, size = 10, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ ALL-NEXT: Obj: ``: ALL-NEXT: debug stream: 14, # files: 0, has ec info: false ALL-NEXT: pdb file ni: 1 `{{.*empty.pdb}}`, src file ni: 0 `` diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index eec1a74..eb17188 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -440,6 +440,86 @@ static void iterateModuleSubsections( }); } +static Expected, + ArrayRef>> +loadSectionHeaders(PDBFile &File, DbgHeaderType Type) { + if (!File.hasPDBDbiStream()) + return make_error( + "Section headers require a DBI Stream, which could not be loaded", + inconvertibleErrorCode()); + + auto &Dbi = cantFail(File.getPDBDbiStream()); + uint32_t SI = Dbi.getDebugStreamIndex(Type); + + if (SI == kInvalidStreamIndex) + return make_error( + "PDB does not contain the requested image section header type", + inconvertibleErrorCode()); + + auto Stream = File.createIndexedStream(SI); + if (!Stream) + return make_error("Could not load the required stream data", + inconvertibleErrorCode()); + + ArrayRef Headers; + if (Stream->getLength() % sizeof(object::coff_section) != 0) + return make_error( + "Section header array size is not a multiple of section header size", + inconvertibleErrorCode()); + + uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section); + BinaryStreamReader Reader(*Stream); + cantFail(Reader.readArray(Headers, NumHeaders)); + return std::make_pair(std::move(Stream), Headers); +} + +static std::vector getSectionNames(PDBFile &File) { + auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr); + if (!ExpectedHeaders) + return {}; + + std::unique_ptr Stream; + ArrayRef Headers; + std::tie(Stream, Headers) = std::move(*ExpectedHeaders); + std::vector Names; + for (const auto &H : Headers) + Names.push_back(H.Name); + return Names; +} + +static void dumpSectionContrib(LinePrinter &P, const SectionContrib &SC, + ArrayRef SectionNames, + uint32_t FieldWidth) { + std::string NameInsert; + if (SC.ISect > 0 && SC.ISect < SectionNames.size()) { + StringRef SectionName = SectionNames[SC.ISect - 1]; + NameInsert = formatv("[{0}]", SectionName).str(); + } else + NameInsert = "[???]"; + P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc " + "crc = {4}", + formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), + fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc), + fmt_align(NameInsert, AlignStyle::Left, FieldWidth + 2)); + AutoIndent Indent(P, FieldWidth + 2); + P.formatLine(" {0}", + formatSectionCharacteristics(P.getIndentLevel() + 6, + SC.Characteristics, 3, " | ")); +} + +static void dumpSectionContrib(LinePrinter &P, const SectionContrib2 &SC, + ArrayRef SectionNames, + uint32_t FieldWidth) { + P.formatLine("SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc " + "crc = {4}, coff section = {5}", + formatSegmentOffset(SC.Base.ISect, SC.Base.Off), + 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, 3, " | ")); +} + Error DumpOutputStyle::dumpModules() { printHeader(P, "Modules"); AutoIndent Indent(P); @@ -462,6 +542,10 @@ Error DumpOutputStyle::dumpModules() { iterateSymbolGroups( File, PrintScope{P, 11}, [&](uint32_t Modi, const SymbolGroup &Strings) { auto Desc = Modules.getModuleDescriptor(Modi); + if (opts::dump::DumpSectionContribs) { + std::vector Sections = getSectionNames(getPdb()); + dumpSectionContrib(P, Desc.getSectionContrib(), Sections, 0); + } P.formatLine("Obj: `{0}`: ", Desc.getObjFileName()); P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}", Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(), @@ -1435,39 +1519,6 @@ Error DumpOutputStyle::dumpSectionHeaders() { return Error::success(); } -static Expected, - ArrayRef>> -loadSectionHeaders(PDBFile &File, DbgHeaderType Type) { - if (!File.hasPDBDbiStream()) - return make_error( - "Section headers require a DBI Stream, which could not be loaded", - inconvertibleErrorCode()); - - auto &Dbi = cantFail(File.getPDBDbiStream()); - uint32_t SI = Dbi.getDebugStreamIndex(Type); - - if (SI == kInvalidStreamIndex) - return make_error( - "PDB does not contain the requested image section header type", - inconvertibleErrorCode()); - - auto Stream = File.createIndexedStream(SI); - if (!Stream) - return make_error("Could not load the required stream data", - inconvertibleErrorCode()); - - ArrayRef Headers; - if (Stream->getLength() % sizeof(object::coff_section) != 0) - return make_error( - "Section header array size is not a multiple of section header size", - inconvertibleErrorCode()); - - uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section); - BinaryStreamReader Reader(*Stream); - cantFail(Reader.readArray(Headers, NumHeaders)); - return std::make_pair(std::move(Stream), Headers); -} - void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) { printHeader(P, Label); @@ -1514,20 +1565,6 @@ void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) { return; } -std::vector getSectionNames(PDBFile &File) { - auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr); - if (!ExpectedHeaders) - return {}; - - std::unique_ptr Stream; - ArrayRef Headers; - std::tie(Stream, Headers) = std::move(*ExpectedHeaders); - std::vector Names; - for (const auto &H : Headers) - Names.push_back(H.Name); - return Names; -} - Error DumpOutputStyle::dumpSectionContribs() { printHeader(P, "Section Contributions"); @@ -1556,33 +1593,10 @@ Error DumpOutputStyle::dumpSectionContribs() { MaxNameLen = (Max == Names.end() ? 0 : Max->size()); } void visit(const SectionContrib &SC) override { - assert(SC.ISect > 0); - std::string NameInsert; - if (SC.ISect < Names.size()) { - StringRef SectionName = Names[SC.ISect - 1]; - NameInsert = formatv("[{0}]", SectionName).str(); - } else - NameInsert = "[???]"; - P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc " - "crc = {4}", - formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), - fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc), - fmt_align(NameInsert, AlignStyle::Left, MaxNameLen + 2)); - AutoIndent Indent(P, MaxNameLen + 2); - P.formatLine(" {0}", - formatSectionCharacteristics(P.getIndentLevel() + 6, - SC.Characteristics, 3, " | ")); + dumpSectionContrib(P, SC, Names, MaxNameLen); } void visit(const SectionContrib2 &SC) override { - P.formatLine( - "SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc " - "crc = {4}, coff section = {5}", - formatSegmentOffset(SC.Base.ISect, SC.Base.Off), 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, 3, " | ")); + dumpSectionContrib(P, SC, Names, MaxNameLen); } private: