Index: include/llvm/DebugInfo/CodeView/TypeDumper.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeDumper.h +++ include/llvm/DebugInfo/CodeView/TypeDumper.h @@ -25,7 +25,7 @@ class CVTypeDumper { public: CVTypeDumper(ScopedPrinter &W, bool PrintRecordBytes) - : W(W), PrintRecordBytes(PrintRecordBytes) {} + : W(&W), PrintRecordBytes(PrintRecordBytes) {} StringRef getTypeName(TypeIndex TI); void printTypeIndex(StringRef FieldName, TypeIndex TI); @@ -53,8 +53,11 @@ return TypeNames.insert(TypeName).first->getKey(); } + void setPrinter(ScopedPrinter *P); + ScopedPrinter *getPrinter() { return W; } + private: - ScopedPrinter &W; + ScopedPrinter *W; bool PrintRecordBytes = false; Index: lib/DebugInfo/CodeView/SymbolDumper.cpp =================================================================== --- lib/DebugInfo/CodeView/SymbolDumper.cpp +++ lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -599,9 +599,9 @@ void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind, ScopeEndSym &ScopeEnd) { if (Kind == SymbolKind::S_END) - W.startLine() << "BlockEnd\n"; + DictScope S(W, "BlockEnd"); else if (Kind == SymbolKind::S_PROC_ID_END) - W.startLine() << "ProcEnd\n"; + DictScope S(W, "ProcEnd"); else if (Kind == SymbolKind::S_INLINESITE_END) DictScope S(W, "InlineSiteEnd"); @@ -648,8 +648,8 @@ void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, ArrayRef Data) { DictScope S(W, "UnknownSym"); - W.printHex("Kind", unsigned(Kind)); - W.printHex("Size", Data.size()); + W.printEnum("Kind", Kind, makeArrayRef(SymbolTypeNames)); + W.printNumber("Length", Data.size()); } bool CVSymbolDumper::dump(const SymbolIterator::Record &Record) { Index: lib/DebugInfo/CodeView/TypeDumper.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeDumper.cpp +++ lib/DebugInfo/CodeView/TypeDumper.cpp @@ -656,19 +656,26 @@ if (!TI.isNoType()) TypeName = getTypeName(TI); if (!TypeName.empty()) - W.printHex(FieldName, TypeName, TI.getIndex()); + W->printHex(FieldName, TypeName, TI.getIndex()); else - W.printHex(FieldName, TI.getIndex()); + W->printHex(FieldName, TI.getIndex()); } bool CVTypeDumper::dump(const TypeIterator::Record &Record) { - CVTypeDumperImpl Dumper(*this, W, PrintRecordBytes); + assert(W && "printer should not be null"); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); Dumper.visitTypeRecord(Record); return !Dumper.hadError(); } bool CVTypeDumper::dump(ArrayRef Data) { - CVTypeDumperImpl Dumper(*this, W, PrintRecordBytes); + assert(W && "printer should not be null"); + CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); Dumper.visitTypeStream(Data); return !Dumper.hadError(); } + +void CVTypeDumper::setPrinter(ScopedPrinter *P) { + static ScopedPrinter NullP(llvm::nulls()); + W = P ? P : &NullP; +} Index: test/DebugInfo/COFF/asm.ll =================================================================== --- test/DebugInfo/COFF/asm.ll +++ test/DebugInfo/COFF/asm.ll @@ -72,7 +72,8 @@ ; OBJ32: DisplayName: f ; OBJ32: LinkageName: _f ; OBJ32: } -; OBJ32: ProcEnd +; OBJ32: ProcEnd { +; OBJ32: } ; OBJ32-NEXT: ] ; OBJ32: FunctionLineTable [ ; OBJ32-NEXT: Name: _f @@ -162,7 +163,8 @@ ; OBJ64: DisplayName: f ; OBJ64: LinkageName: f ; OBJ64: } -; OBJ64-NEXT: ProcEnd +; OBJ64-NEXT: ProcEnd { +; OBJ64-NEXT: } ; OBJ64-NEXT: ] ; OBJ64: FunctionLineTable [ ; OBJ64-NEXT: Name: f Index: test/DebugInfo/COFF/multifile.ll =================================================================== --- test/DebugInfo/COFF/multifile.ll +++ test/DebugInfo/COFF/multifile.ll @@ -80,7 +80,8 @@ ; OBJ32: DisplayName: f ; OBJ32: LinkageName: _f ; OBJ32: } -; OBJ32-NEXT: ProcEnd +; OBJ32-NEXT: ProcEnd { +; OBJ32-NEXT: } ; OBJ32-NEXT: ] ; OBJ32: FunctionLineTable [ ; OBJ32-NEXT: Name: _f @@ -183,7 +184,8 @@ ; OBJ64: DisplayName: f ; OBJ64: LinkageName: f ; OBJ64: } -; OBJ64: ProcEnd +; OBJ64-NEXT: ProcEnd { +; OBJ64-NEXT: } ; OBJ64-NEXT: ] ; OBJ64: FunctionLineTable [ ; OBJ64-NEXT: Name: f Index: test/DebugInfo/COFF/multifunction.ll =================================================================== --- test/DebugInfo/COFF/multifunction.ll +++ test/DebugInfo/COFF/multifunction.ll @@ -157,7 +157,8 @@ ; OBJ32: DisplayName: x ; OBJ32: LinkageName: _x ; OBJ32: } -; OBJ32: ProcEnd +; OBJ32: ProcEnd { +; OBJ32: } ; OBJ32-NEXT: ] ; OBJ32: Subsection [ ; OBJ32-NEXT: SubSectionType: Lines (0xF2) @@ -170,7 +171,8 @@ ; OBJ32: DisplayName: y ; OBJ32: LinkageName: _y ; OBJ32: } -; OBJ32: ProcEnd +; OBJ32: ProcEnd { +; OBJ32: } ; OBJ32-NEXT: ] ; OBJ32: Subsection [ ; OBJ32-NEXT: SubSectionType: Lines (0xF2) @@ -183,7 +185,8 @@ ; OBJ32: DisplayName: f ; OBJ32: LinkageName: _f ; OBJ32: } -; OBJ32: ProcEnd +; OBJ32: ProcEnd { +; OBJ32: } ; OBJ32-NEXT: ] ; OBJ32: Subsection [ ; OBJ32-NEXT: SubSectionType: Lines (0xF2) @@ -419,7 +422,8 @@ ; OBJ64: DisplayName: x ; OBJ64: LinkageName: x ; OBJ64: } -; OBJ64: ProcEnd +; OBJ64: ProcEnd { +; OBJ64: } ; OBJ64-NEXT: ] ; OBJ64: Subsection [ ; OBJ64-NEXT: SubSectionType: Lines (0xF2) @@ -432,7 +436,8 @@ ; OBJ64: DisplayName: y ; OBJ64: LinkageName: y ; OBJ64: } -; OBJ64: ProcEnd +; OBJ64: ProcEnd { +; OBJ64: } ; OBJ64-NEXT: ] ; OBJ64: Subsection [ ; OBJ64-NEXT: SubSectionType: Lines (0xF2) @@ -445,7 +450,8 @@ ; OBJ64: DisplayName: f ; OBJ64: LinkageName: f ; OBJ64: } -; OBJ64: ProcEnd +; OBJ64: ProcEnd { +; OBJ64: } ; OBJ64-NEXT: ] ; OBJ64: Subsection [ ; OBJ64-NEXT: SubSectionType: Lines (0xF2) Index: test/DebugInfo/COFF/simple.ll =================================================================== --- test/DebugInfo/COFF/simple.ll +++ test/DebugInfo/COFF/simple.ll @@ -70,7 +70,8 @@ ; OBJ32: DisplayName: f ; OBJ32: LinkageName: _f ; OBJ32: } -; OBJ32-NEXT: ProcEnd +; OBJ32-NEXT: ProcEnd { +; OBJ32-NEXT: } ; OBJ32-NEXT: ] ; OBJ32: FunctionLineTable [ ; OBJ32-NEXT: Name: _f @@ -158,7 +159,8 @@ ; OBJ64: DisplayName: f ; OBJ64: LinkageName: f ; OBJ64: } -; OBJ64-NEXT: ProcEnd +; OBJ64-NEXT: ProcEnd { +; OBJ64-NEXT: } ; OBJ64-NEXT: ] ; OBJ64: FunctionLineTable [ ; OBJ64-NEXT: Name: f Index: test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- test/DebugInfo/PDB/pdbdump-headers.test +++ test/DebugInfo/PDB/pdbdump-headers.test @@ -1,5 +1,5 @@ ; RUN: llvm-pdbdump --dump-headers -dump-tpi-records -dump-tpi-record-bytes -dump-module-syms \ -; RUN: --dump-publics %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s +; RUN: -dump-sym-record-bytes --dump-publics %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s ; RUN: llvm-pdbdump --dump-headers %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s ; RUN: llvm-pdbdump --dump-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s @@ -31,7 +31,73 @@ ; EMPTY-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp ; EMPTY-NEXT: ] ; EMPTY-NEXT: } -; EMPTY-NEXT: DBI Stream { +; EMPTY-NEXT: Type Info Stream { +; EMPTY-NEXT: TPI Version: 20040203 +; EMPTY-NEXT: Record count: 75 +; EMPTY-NEXT: Records [ +; EMPTY-NEXT: { +; EMPTY-NEXT: ArgList (0x1000) { +; EMPTY-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) +; EMPTY-NEXT: NumArgs: 0 +; EMPTY-NEXT: Arguments [ +; EMPTY-NEXT: ] +; EMPTY-NEXT: } +; EMPTY-NEXT: Bytes ( +; EMPTY-NEXT: 0000: 00000000 |....| +; EMPTY-NEXT: ) +; EMPTY-NEXT: } +; EMPTY-NEXT: { +; EMPTY-NEXT: Procedure (0x1001) { +; EMPTY-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) +; EMPTY-NEXT: ReturnType: int (0x74) +; EMPTY-NEXT: CallingConvention: NearC (0x0) +; EMPTY-NEXT: FunctionOptions [ (0x0) +; EMPTY-NEXT: ] +; EMPTY-NEXT: NumParameters: 0 +; EMPTY-NEXT: ArgListType: () (0x1000) +; EMPTY-NEXT: } +; EMPTY-NEXT: Bytes ( +; EMPTY-NEXT: 0000: 74000000 00000000 00100000 |t...........| +; EMPTY-NEXT: ) +; EMPTY-NEXT: } +; EMPTY-NEXT: { +; EMPTY-NEXT: UnknownLeaf (0x1002) { +; EMPTY-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) +; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: AccessSpecifier: Public (0x3) +; EMPTY-NEXT: EnumValue: 1 +; EMPTY-NEXT: Name: apartment +; EMPTY-NEXT: } +; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: AccessSpecifier: Public (0x3) +; EMPTY-NEXT: EnumValue: 2 +; EMPTY-NEXT: Name: single +; EMPTY-NEXT: } +; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: AccessSpecifier: Public (0x3) +; EMPTY-NEXT: EnumValue: 3 +; EMPTY-NEXT: Name: free +; EMPTY-NEXT: } +; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: AccessSpecifier: Public (0x3) +; EMPTY-NEXT: EnumValue: 4 +; EMPTY-NEXT: Name: neutral +; EMPTY-NEXT: } +; EMPTY-NEXT: Enumerator { +; EMPTY-NEXT: AccessSpecifier: Public (0x3) +; EMPTY-NEXT: EnumValue: 5 +; EMPTY-NEXT: Name: both +; EMPTY-NEXT: } +; EMPTY-NEXT: } +; EMPTY-NEXT: Bytes ( +; EMPTY-NEXT: 0000: 02150300 01006170 6172746D 656E7400 |......apartment.| +; EMPTY-NEXT: 0010: 02150300 02007369 6E676C65 00F3F2F1 |......single....| +; EMPTY-NEXT: 0020: 02150300 03006672 656500F1 02150300 |......free......| +; EMPTY-NEXT: 0030: 04006E65 75747261 6C00F2F1 02150300 |..neutral.......| +; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..| +; EMPTY-NEXT: ) +; EMPTY-NEXT: } +; EMPTY: DBI Stream { ; EMPTY-NEXT: Dbi Version: 19990903 ; EMPTY-NEXT: Age: 1 ; EMPTY-NEXT: Incremental Linking: Yes @@ -59,8 +125,10 @@ ; EMPTY-NEXT: ] ; EMPTY-NEXT: Symbols [ ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1101 -; EMPTY-NEXT: Length: 54 +; EMPTY-NEXT: ObjectName { +; EMPTY-NEXT: Signature: 0x0 +; EMPTY-NEXT: ObjectName: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\| ; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P| @@ -69,8 +137,16 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x113C -; EMPTY-NEXT: Length: 58 +; EMPTY-NEXT: CompilerFlags { +; EMPTY-NEXT: Language: Cpp (0x1) +; EMPTY-NEXT: Flags [ (0x2000) +; EMPTY-NEXT: SecurityChecks (0x2000) +; EMPTY-NEXT: ] +; EMPTY-NEXT: Machine: Pentium3 (0x7) +; EMPTY-NEXT: FrontendVersion: 18.0.31101.0 +; EMPTY-NEXT: BackendVersion: 18.0.31101.0 +; EMPTY-NEXT: VersionName: Microsoft (R) Optimizing Compiler +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 01200000 07001200 00007D79 00001200 |. ........}y....| ; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft | @@ -79,8 +155,20 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1110 -; EMPTY-NEXT: Length: 42 +; EMPTY-NEXT: ProcStart { +; EMPTY-NEXT: PtrParent: 0x0 +; EMPTY-NEXT: PtrEnd: 0xC4 +; EMPTY-NEXT: PtrNext: 0x0 +; EMPTY-NEXT: CodeSize: 0xA +; EMPTY-NEXT: DbgStart: 0x3 +; EMPTY-NEXT: DbgEnd: 0x8 +; EMPTY-NEXT: FunctionType: int () (0x1001) +; EMPTY-NEXT: Segment: 0x1 +; EMPTY-NEXT: Flags [ (0x1) +; EMPTY-NEXT: HasFP (0x1) +; EMPTY-NEXT: ] +; EMPTY-NEXT: DisplayName: main +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000000 C4000000 00000000 0A000000 |................| ; EMPTY-NEXT: 0010: 03000000 08000000 01100000 10000000 |................| @@ -88,22 +176,33 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1012 -; EMPTY-NEXT: Length: 30 +; EMPTY-NEXT: FrameProc { +; EMPTY-NEXT: TotalFrameBytes: 0x0 +; EMPTY-NEXT: PaddingFrameBytes: 0x0 +; EMPTY-NEXT: OffsetToPadding: 0x0 +; EMPTY-NEXT: BytesOfCalleeSavedRegisters: 0x0 +; EMPTY-NEXT: OffsetOfExceptionHandler: 0x0 +; EMPTY-NEXT: SectionIdOfExceptionHandler: 0x0 +; EMPTY-NEXT: Flags [ (0x128200) +; EMPTY-NEXT: AsynchronousExceptionHandling (0x200) +; EMPTY-NEXT: OptimizedForSpeed (0x100000) +; EMPTY-NEXT: ] +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000000 00000000 00000000 00000000 |................| ; EMPTY-NEXT: 0010: 00000000 00000082 12000000 |............| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x6 -; EMPTY-NEXT: Length: 2 +; EMPTY-NEXT: BlockEnd { +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x114C -; EMPTY-NEXT: Length: 6 +; EMPTY-NEXT: BuildInfo { +; EMPTY-NEXT: BuildId: 4110 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 0E100000 |....| ; EMPTY-NEXT: ) @@ -126,15 +225,24 @@ ; EMPTY-NEXT: ] ; EMPTY-NEXT: Symbols [ ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1101 -; EMPTY-NEXT: Length: 18 +; EMPTY-NEXT: ObjectName { +; EMPTY-NEXT: Signature: 0x0 +; EMPTY-NEXT: ObjectName: * Linker * +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000000 2A204C69 6E6B6572 202A0000 |....* Linker *..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x113C -; EMPTY-NEXT: Length: 46 +; EMPTY-NEXT: CompilerFlags { +; EMPTY-NEXT: Language: Link (0x7) +; EMPTY-NEXT: Flags [ (0x0) +; EMPTY-NEXT: ] +; EMPTY-NEXT: Machine: Intel80386 (0x3) +; EMPTY-NEXT: FrontendVersion: 0.0.0.0 +; EMPTY-NEXT: BackendVersion: 12.0.31101.0 +; EMPTY-NEXT: VersionName: Microsoft (R) LINK +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 07000000 03000000 00000000 00000C00 |................| ; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft | @@ -142,8 +250,10 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x113D -; EMPTY-NEXT: Length: 170 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_ENVBLOCK (0x113D) +; EMPTY-NEXT: Length: 168 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00637764 00643A5C 7372635C 6C6C766D |.cwd.d:\src\llvm| ; EMPTY-NEXT: 0010: 5C746573 745C4465 62756749 6E666F5C |\test\DebugInfo\| @@ -159,79 +269,99 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x112C -; EMPTY-NEXT: Length: 18 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_TRAMPOLINE (0x112C) +; EMPTY-NEXT: Length: 16 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000500 05000000 10000000 01000100 |................| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1136 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_SECTION (0x1136) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 01000C00 00100000 1A100000 20000060 |............ ..`| ; EMPTY-NEXT: 0010: 2E746578 74000000 |.text...| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1137 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_COFFGROUP (0x1137) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 1A100000 20000060 00000000 01002E74 |.... ..`.......t| ; EMPTY-NEXT: 0010: 65787424 6D6E0000 |ext$mn..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1136 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_SECTION (0x1136) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 02000C00 00300000 B2020000 40000040 |.....0......@..@| ; EMPTY-NEXT: 0010: 2E726461 74610000 |.rdata..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1137 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_COFFGROUP (0x1137) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 43010000 40000040 00000000 02002E72 |C...@..@.......r| ; EMPTY-NEXT: 0010: 64617461 00000000 |data....| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1137 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_COFFGROUP (0x1137) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 00000000 40000040 43010000 02002E65 |....@..@C......e| ; EMPTY-NEXT: 0010: 64617461 00000000 |data....| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1137 -; EMPTY-NEXT: Length: 30 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_COFFGROUP (0x1137) +; EMPTY-NEXT: Length: 28 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 6E010000 40000040 44010000 02002E72 |n...@..@D......r| ; EMPTY-NEXT: 0010: 64617461 24646562 75670000 |data$debug..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1136 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_SECTION (0x1136) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 03000C00 00400000 04000000 400000C0 |.....@......@...| ; EMPTY-NEXT: 0010: 2E646174 61000000 |.data...| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1137 -; EMPTY-NEXT: Length: 22 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_COFFGROUP (0x1137) +; EMPTY-NEXT: Length: 20 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 04000000 800000C0 00000000 03002E62 |...............b| ; EMPTY-NEXT: 0010: 73730000 |ss..| ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: { -; EMPTY-NEXT: Kind: 0x1136 -; EMPTY-NEXT: Length: 26 +; EMPTY-NEXT: UnknownSym { +; EMPTY-NEXT: Kind: S_SECTION (0x1136) +; EMPTY-NEXT: Length: 24 +; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( ; EMPTY-NEXT: 0000: 04000C00 00500000 08000000 40000042 |.....P......@..B| ; EMPTY-NEXT: 0010: 2E72656C 6F630000 |.reloc..| @@ -241,73 +371,6 @@ ; EMPTY-NEXT: } ; EMPTY-NEXT: ] ; EMPTY-NEXT: } -; EMPTY-NEXT: Type Info Stream { -; EMPTY-NEXT: TPI Version: 20040203 -; EMPTY-NEXT: Record count: 75 -; EMPTY-NEXT: Records [ -; EMPTY-NEXT: { -; EMPTY-NEXT: ArgList (0x1000) { -; EMPTY-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) -; EMPTY-NEXT: NumArgs: 0 -; EMPTY-NEXT: Arguments [ -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 |....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Procedure (0x1001) { -; EMPTY-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -; EMPTY-NEXT: ReturnType: int (0x74) -; EMPTY-NEXT: CallingConvention: NearC (0x0) -; EMPTY-NEXT: FunctionOptions [ (0x0) -; EMPTY-NEXT: ] -; EMPTY-NEXT: NumParameters: 0 -; EMPTY-NEXT: ArgListType: () (0x1000) -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 74000000 00000000 00100000 |t...........| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UnknownLeaf (0x1002) { -; EMPTY-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 1 -; EMPTY-NEXT: Name: apartment -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 2 -; EMPTY-NEXT: Name: single -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 3 -; EMPTY-NEXT: Name: free -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 4 -; EMPTY-NEXT: Name: neutral -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 5 -; EMPTY-NEXT: Name: both -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 02150300 01006170 6172746D 656E7400 |......apartment.| -; EMPTY-NEXT: 0010: 02150300 02007369 6E676C65 00F3F2F1 |......single....| -; EMPTY-NEXT: 0020: 02150300 03006672 656500F1 02150300 |......free......| -; EMPTY-NEXT: 0030: 04006E65 75747261 6C00F2F1 02150300 |..neutral.......| -; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } - ; EMPTY: Publics Stream { ; EMPTY-NEXT: Stream number: 7 ; EMPTY-NEXT: SymHash: 556 Index: tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- tools/llvm-pdbdump/llvm-pdbdump.cpp +++ tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" +#include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDumper.h" #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" @@ -126,6 +127,10 @@ cl::opt DumpPublics("dump-publics", cl::desc("dump Publics stream data"), cl::cat(NativeOtions)); +cl::opt + DumpSymRecordBytes("dump-sym-record-bytes", + cl::desc("dump CodeView symbol record raw bytes"), + cl::cat(NativeOtions)); cl::list ExcludeTypes("exclude-types", @@ -299,7 +304,8 @@ return Error::success(); } -static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File) { +static Error dumpDbiStream(ScopedPrinter &P, PDBFile &File, + codeview::CVTypeDumper &TD) { auto DbiS = File.getPDBDbiStream(); if (auto EC = DbiS.takeError()) return EC; @@ -346,40 +352,41 @@ for (auto File : Modi.SourceFiles) P.printString(File); } - if (opts::DumpModuleSyms) { + if (opts::DumpModuleSyms || opts::DumpSymRecordBytes) { ListScope SS(P, "Symbols"); ModStream ModS(File, Modi.Info); if (auto EC = ModS.reload()) return EC; + codeview::CVSymbolDumper SD(P, TD, nullptr, false); for (auto &S : ModS.symbols()) { - DictScope SD(P); - P.printHex("Kind", static_cast(S.Type)); - P.printNumber("Length", static_cast(S.Length)); - P.printBinaryBlock("Bytes", S.Data); + DictScope DD(P, ""); + + if (opts::DumpModuleSyms) + SD.dump(S); + if (opts::DumpSymRecordBytes) + P.printBinaryBlock("Bytes", S.Data); } } } return Error::success(); } -static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File) { - if (!opts::DumpTpiRecordBytes && !opts::DumpTpiRecords) - return Error::success(); +static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File, + codeview::CVTypeDumper &TD) { - DictScope D(P, "Type Info Stream"); + if (opts::DumpTpiRecordBytes || opts::DumpTpiRecords) { + DictScope D(P, "Type Info Stream"); - auto TpiS = File.getPDBTpiStream(); - if (auto EC = TpiS.takeError()) - return EC; - TpiStream &Tpi = TpiS.get(); + auto TpiS = File.getPDBTpiStream(); + if (auto EC = TpiS.takeError()) + return EC; + TpiStream &Tpi = TpiS.get(); - P.printNumber("TPI Version", Tpi.getTpiVersion()); - P.printNumber("Record count", Tpi.NumTypeRecords()); + P.printNumber("TPI Version", Tpi.getTpiVersion()); + P.printNumber("Record count", Tpi.NumTypeRecords()); - if (opts::DumpTpiRecordBytes || opts::DumpTpiRecords) { ListScope L(P, "Records"); - codeview::CVTypeDumper TD(P, false); bool HadError = false; for (auto &Type : Tpi.types(&HadError)) { @@ -394,7 +401,29 @@ if (HadError) return make_error(raw_error_code::corrupt_file, "TPI stream contained corrupt record"); + } else if (opts::DumpModuleSyms) { + // Even if the user doesn't want to dump type records, we still need to + // iterate them in + // order to build the list of types so that we can print them when dumping + // module symbols. + // So when they want to dump symbols but not types, use a null output + // stream. + ScopedPrinter *OldP = TD.getPrinter(); + TD.setPrinter(nullptr); + auto TpiS = File.getPDBTpiStream(); + if (auto EC = TpiS.takeError()) + return EC; + TpiStream &Tpi = TpiS.get(); + bool HadError = false; + for (auto &Type : Tpi.types(&HadError)) + TD.dump(Type); + + TD.setPrinter(OldP); + if (HadError) + return make_error(raw_error_code::corrupt_file, + "TPI stream contained corrupt record"); } + return Error::success(); } @@ -441,10 +470,11 @@ if (auto EC = dumpNamedStream(P, File, "/names")) return EC; - if (auto EC = dumpDbiStream(P, File)) + codeview::CVTypeDumper TD(P, false); + if (auto EC = dumpTpiStream(P, File, TD)) return EC; - if (auto EC = dumpTpiStream(P, File)) + if (auto EC = dumpDbiStream(P, File, TD)) return EC; if (auto EC = dumpPublicsStream(P, File))