llvm.org GIT mirror llvm / 8995c86
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@330208 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 5 months ago
6 changed file(s) with 99 addition(s) and 86 deletion(s). Raw diff Collapse all Expand all
4646
4747 uint32_t getRecordLength() const;
4848
49 const SectionContrib &getSectionContrib() const;
50
4951 private:
5052 StringRef ModuleName;
5153 StringRef ObjFileName;
176176 };
177177 static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
178178
179 struct SectionContribEntry {
180 support::ulittle16_t Section;
181 char Padding1[2];
182 support::little32_t Offset;
183 support::little32_t Size;
184 support::ulittle32_t Characteristics;
185 support::ulittle16_t ModuleIndex;
186 char Padding2[2];
187 support::ulittle32_t DataCrc;
188 support::ulittle32_t RelocCrc;
189 };
190
191179 /// The header preceeding the File Info Substream of the DBI stream.
192180 struct FileInfoSubstreamHeader {
193181 /// Total # of modules, should match number of records in the ModuleInfo
229217 support::ulittle32_t Mod;
230218
231219 /// First section contribution of this module.
232 SectionContribEntry SC;
220 SectionContrib SC;
233221
234222 /// See ModInfoFlags definition.
235223 support::ulittle16_t Flags;
4848 ModInfoFlags::TypeServerIndexShift;
4949 }
5050
51 const SectionContrib &DbiModuleDescriptor::getSectionContrib() const {
52 return Layout->SC;
53 }
54
5155 uint16_t DbiModuleDescriptor::getModuleStreamIndex() const {
5256 return Layout->ModDiStream;
5357 }
8989 }
9090
9191 void DbiModuleDescriptorBuilder::finalize() {
92 Layout.SC.ModuleIndex = Layout.Mod;
92 Layout.SC.Imod = Layout.Mod;
9393 Layout.FileNameOffs = 0; // TODO: Fix this
9494 Layout.Flags = 0; // TODO: Fix this
9595 Layout.C11Bytes = 0;
6464 ALL: Modules
6565 ALL-NEXT: ============================================================
6666 ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
67 ALL-NEXT: SC[.text] | mod = 0, 0001:0016, size = 10, data crc = 3617027124, reloc crc = 0
68 ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
69 ALL-NEXT: IMAGE_SCN_MEM_READ
6770 ALL-NEXT: Obj: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
6871 ALL-NEXT: debug stream: 12, # files: 1, has ec info: false
6972 ALL-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
7073 ALL-NEXT: Mod 0001 | `* Linker *`:
74 ALL-NEXT: SC[.text] | mod = 1, 0001:0000, size = 10, data crc = 0, reloc crc = 0
75 ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
7176 ALL-NEXT: Obj: ``:
7277 ALL-NEXT: debug stream: 14, # files: 0, has ec info: false
7378 ALL-NEXT: pdb file ni: 1 `{{.*empty.pdb}}`, src file ni: 0 ``
439439 });
440440 }
441441
442 static Expected,
443 ArrayRef>>
444 loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
445 if (!File.hasPDBDbiStream())
446 return make_error(
447 "Section headers require a DBI Stream, which could not be loaded",
448 inconvertibleErrorCode());
449
450 auto &Dbi = cantFail(File.getPDBDbiStream());
451 uint32_t SI = Dbi.getDebugStreamIndex(Type);
452
453 if (SI == kInvalidStreamIndex)
454 return make_error(
455 "PDB does not contain the requested image section header type",
456 inconvertibleErrorCode());
457
458 auto Stream = File.createIndexedStream(SI);
459 if (!Stream)
460 return make_error("Could not load the required stream data",
461 inconvertibleErrorCode());
462
463 ArrayRef Headers;
464 if (Stream->getLength() % sizeof(object::coff_section) != 0)
465 return make_error(
466 "Section header array size is not a multiple of section header size",
467 inconvertibleErrorCode());
468
469 uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
470 BinaryStreamReader Reader(*Stream);
471 cantFail(Reader.readArray(Headers, NumHeaders));
472 return std::make_pair(std::move(Stream), Headers);
473 }
474
475 static std::vector getSectionNames(PDBFile &File) {
476 auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
477 if (!ExpectedHeaders)
478 return {};
479
480 std::unique_ptr Stream;
481 ArrayRef Headers;
482 std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
483 std::vector Names;
484 for (const auto &H : Headers)
485 Names.push_back(H.Name);
486 return Names;
487 }
488
489 static void dumpSectionContrib(LinePrinter &P, const SectionContrib &SC,
490 ArrayRef SectionNames,
491 uint32_t FieldWidth) {
492 std::string NameInsert;
493 if (SC.ISect > 0 && SC.ISect < SectionNames.size()) {
494 StringRef SectionName = SectionNames[SC.ISect - 1];
495 NameInsert = formatv("[{0}]", SectionName).str();
496 } else
497 NameInsert = "[???]";
498 P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
499 "crc = {4}",
500 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
501 fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
502 fmt_align(NameInsert, AlignStyle::Left, FieldWidth + 2));
503 AutoIndent Indent(P, FieldWidth + 2);
504 P.formatLine(" {0}",
505 formatSectionCharacteristics(P.getIndentLevel() + 6,
506 SC.Characteristics, 3, " | "));
507 }
508
509 static void dumpSectionContrib(LinePrinter &P, const SectionContrib2 &SC,
510 ArrayRef SectionNames,
511 uint32_t FieldWidth) {
512 P.formatLine("SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
513 "crc = {4}, coff section = {5}",
514 formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
515 fmtle(SC.Base.Size), fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc),
516 fmtle(SC.Base.RelocCrc), fmtle(SC.ISectCoff));
517 P.formatLine(" {0}",
518 formatSectionCharacteristics(P.getIndentLevel() + 6,
519 SC.Base.Characteristics, 3, " | "));
520 }
521
442522 Error DumpOutputStyle::dumpModules() {
443523 printHeader(P, "Modules");
444524 AutoIndent Indent(P);
461541 iterateSymbolGroups(
462542 File, PrintScope{P, 11}, [&](uint32_t Modi, const SymbolGroup &Strings) {
463543 auto Desc = Modules.getModuleDescriptor(Modi);
544 if (opts::dump::DumpSectionContribs) {
545 std::vector Sections = getSectionNames(getPdb());
546 dumpSectionContrib(P, Desc.getSectionContrib(), Sections, 0);
547 }
464548 P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
465549 P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
466550 Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
14341518 return Error::success();
14351519 }
14361520
1437 static Expected,
1438 ArrayRef>>
1439 loadSectionHeaders(PDBFile &File, DbgHeaderType Type) {
1440 if (!File.hasPDBDbiStream())
1441 return make_error(
1442 "Section headers require a DBI Stream, which could not be loaded",
1443 inconvertibleErrorCode());
1444
1445 auto &Dbi = cantFail(File.getPDBDbiStream());
1446 uint32_t SI = Dbi.getDebugStreamIndex(Type);
1447
1448 if (SI == kInvalidStreamIndex)
1449 return make_error(
1450 "PDB does not contain the requested image section header type",
1451 inconvertibleErrorCode());
1452
1453 auto Stream = File.createIndexedStream(SI);
1454 if (!Stream)
1455 return make_error("Could not load the required stream data",
1456 inconvertibleErrorCode());
1457
1458 ArrayRef Headers;
1459 if (Stream->getLength() % sizeof(object::coff_section) != 0)
1460 return make_error(
1461 "Section header array size is not a multiple of section header size",
1462 inconvertibleErrorCode());
1463
1464 uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
1465 BinaryStreamReader Reader(*Stream);
1466 cantFail(Reader.readArray(Headers, NumHeaders));
1467 return std::make_pair(std::move(Stream), Headers);
1468 }
1469
14701521 void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
14711522 printHeader(P, Label);
14721523
15131564 return;
15141565 }
15151566
1516 std::vector getSectionNames(PDBFile &File) {
1517 auto ExpectedHeaders = loadSectionHeaders(File, DbgHeaderType::SectionHdr);
1518 if (!ExpectedHeaders)
1519 return {};
1520
1521 std::unique_ptr Stream;
1522 ArrayRef Headers;
1523 std::tie(Stream, Headers) = std::move(*ExpectedHeaders);
1524 std::vector Names;
1525 for (const auto &H : Headers)
1526 Names.push_back(H.Name);
1527 return Names;
1528 }
1529
15301567 Error DumpOutputStyle::dumpSectionContribs() {
15311568 printHeader(P, "Section Contributions");
15321569
15551592 MaxNameLen = (Max == Names.end() ? 0 : Max->size());
15561593 }
15571594 void visit(const SectionContrib &SC) override {
1558 assert(SC.ISect > 0);
1559 std::string NameInsert;
1560 if (SC.ISect < Names.size()) {
1561 StringRef SectionName = Names[SC.ISect - 1];
1562 NameInsert = formatv("[{0}]", SectionName).str();
1563 } else
1564 NameInsert = "[???]";
1565 P.formatLine("SC{5} | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1566 "crc = {4}",
1567 formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size),
1568 fmtle(SC.Imod), fmtle(SC.DataCrc), fmtle(SC.RelocCrc),
1569 fmt_align(NameInsert, AlignStyle::Left, MaxNameLen + 2));
1570 AutoIndent Indent(P, MaxNameLen + 2);
1571 P.formatLine(" {0}",
1572 formatSectionCharacteristics(P.getIndentLevel() + 6,
1573 SC.Characteristics, 3, " | "));
1595 dumpSectionContrib(P, SC, Names, MaxNameLen);
15741596 }
15751597 void visit(const SectionContrib2 &SC) override {
1576 P.formatLine(
1577 "SC2[{6}] | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
1578 "crc = {4}, coff section = {5}",
1579 formatSegmentOffset(SC.Base.ISect, SC.Base.Off), fmtle(SC.Base.Size),
1580 fmtle(SC.Base.Imod), fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
1581 fmtle(SC.ISectCoff));
1582 P.formatLine(" {0}", formatSectionCharacteristics(
1583 P.getIndentLevel() + 6,
1584 SC.Base.Characteristics, 3, " | "));
1598 dumpSectionContrib(P, SC, Names, MaxNameLen);
15851599 }
15861600
15871601 private: