Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -17,6 +17,7 @@ #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" @@ -298,6 +299,7 @@ static void remapTypesInSymbolRecord(ObjFile *File, MutableArrayRef Contents, const CVIndexMap &IndexMap, + const TypeTableBuilder &IDTable, ArrayRef TypeRefs) { for (const TiReference &Ref : TypeRefs) { unsigned ByteSize = Ref.Count * sizeof(TypeIndex); @@ -322,11 +324,55 @@ } } -/// MSVC translates S_PROC_ID_END to S_END. -uint16_t canonicalizeSymbolKind(SymbolKind Kind) { - if (Kind == SymbolKind::S_PROC_ID_END) - return SymbolKind::S_END; - return Kind; +static SymbolKind symbolKind(ArrayRef RecordData) { + const RecordPrefix *Prefix = + reinterpret_cast(RecordData.data()); + return static_cast(uint16_t(Prefix->RecordKind)); +} + +/// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32 +static void translateIdSymbols(MutableArrayRef &RecordData, + const TypeTableBuilder &IDTable) { + RecordPrefix *Prefix = reinterpret_cast(RecordData.data()); + + SymbolKind Kind = symbolKind(RecordData); + + if (Kind == SymbolKind::S_PROC_ID_END) { + Prefix->RecordKind = SymbolKind::S_END; + return; + } + + // In an object file, GPROC32_ID has an embedded reference which refers to the + // single object file type index namespace. This has already been translated + // to the PDB file's ID stream index space, but we need to convert this to a + // symbol that refers to the type stream index space. So we remap again from + // ID index space to type index space. + if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) { + SmallVector Refs; + auto Content = RecordData.drop_front(sizeof(RecordPrefix)); + CVSymbol Sym(Kind, RecordData); + discoverTypeIndicesInSymbol(Sym, Refs); + assert(Refs.size() == 1); + assert(Refs.front().Count == 1); + + TypeIndex *TI = + reinterpret_cast(Content.data() + Refs[0].Offset); + // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in + // the IPI stream, whose `FunctionType` member refers to the TPI stream. + // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and + // in both cases we just need the second type index. + if (!TI->isSimple() && !TI->isNoneType()) { + ArrayRef FuncIdData = IDTable.records()[TI->toArrayIndex()]; + SmallVector Indices; + discoverTypeIndices(FuncIdData, Indices); + assert(Indices.size() == 2); + *TI = Indices[1]; + } + + Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32 + : SymbolKind::S_LPROC32; + Prefix->RecordKind = uint16_t(Kind); + } } /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. @@ -344,10 +390,8 @@ memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); // Update the record prefix length. It should point to the beginning of the - // next record. MSVC does some canonicalization of the record kind, so we do - // that as well. + // next record. auto *Prefix = reinterpret_cast(Mem); - Prefix->RecordKind = canonicalizeSymbolKind(Sym.kind()); Prefix->RecordLen = Size - 2; return NewData; } @@ -418,6 +462,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File, const CVIndexMap &IndexMap, + const TypeTableBuilder &IDTable, BinaryStreamRef SymData) { // FIXME: Improve error recovery by warning and skipping records when // possible. @@ -425,11 +470,11 @@ BinaryStreamReader Reader(SymData); ExitOnErr(Reader.readArray(Syms, Reader.getLength())); SmallVector Scopes; - for (const CVSymbol &Sym : Syms) { + for (CVSymbol Sym : Syms) { // Discover type index references in the record. Skip it if we don't know // where they are. SmallVector TypeRefs; - if (!discoverTypeIndices(Sym, TypeRefs)) { + if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) { log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind())); continue; } @@ -440,13 +485,19 @@ // Re-map all the type index references. MutableArrayRef Contents = NewData.drop_front(sizeof(RecordPrefix)); - remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs); + remapTypesInSymbolRecord(File, Contents, IndexMap, IDTable, TypeRefs); + + // An object file may have S_xxx_ID symbols, but these get converted to + // "real" symbols in a PDB. + translateIdSymbols(NewData, IDTable); + + SymbolKind NewKind = symbolKind(NewData); // Fill in "Parent" and "End" fields by maintaining a stack of scopes. - CVSymbol NewSym(Sym.kind(), NewData); - if (symbolOpensScope(Sym.kind())) + CVSymbol NewSym(NewKind, NewData); + if (symbolOpensScope(NewKind)) scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), NewSym); - else if (symbolEndsScope(Sym.kind())) + else if (symbolEndsScope(NewKind)) scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); // Add the symbol to the module. @@ -516,7 +567,7 @@ File->ModuleDBI->addDebugSubsection(SS); break; case DebugSubsectionKind::Symbols: - mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData()); + mergeSymbolRecords(Alloc, File, IndexMap, IDTable, SS.getRecordData()); break; default: // FIXME: Process the rest of the subsections. Index: lld/trunk/test/COFF/pdb-comdat.test =================================================================== --- lld/trunk/test/COFF/pdb-comdat.test +++ lld/trunk/test/COFF/pdb-comdat.test @@ -46,7 +46,7 @@ CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 CHECK: flags = security checks | hot patchable -CHECK: 120 | S_GPROC32_ID [size = 44] `main` +CHECK: 120 | S_GPROC32 [size = 44] `main` CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 24 CHECK: debug start = 4, debug end = 19, flags = none CHECK: 164 | S_FRAMEPROC [size = 32] @@ -57,7 +57,7 @@ CHECK: 200 | S_GDATA32 [size = 24] `global` CHECK: type = 0x0074 (int), addr = 0000:0000 CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100A` -CHECK: 232 | S_GPROC32_ID [size = 44] `foo` +CHECK: 232 | S_GPROC32 [size = 44] `foo` CHECK: parent = 0, end = 308, addr = 0002:0032, code size = 15 CHECK: debug start = 0, debug end = 14, flags = none CHECK: 276 | S_FRAMEPROC [size = 32] @@ -71,7 +71,7 @@ CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 CHECK: flags = security checks | hot patchable -CHECK: 120 | S_GPROC32_ID [size = 44] `bar` +CHECK: 120 | S_GPROC32 [size = 44] `bar` CHECK: parent = 0, end = 196, addr = 0002:0048, code size = 14 CHECK: debug start = 4, debug end = 9, flags = none CHECK: 164 | S_FRAMEPROC [size = 32] @@ -82,7 +82,7 @@ CHECK: 200 | S_GDATA32 [size = 24] `global` CHECK: type = 0x0074 (int), addr = 0000:0000 CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100D` -CHECK-NOT: S_GPROC32_ID {{.*}} `foo` +CHECK-NOT: S_GPROC32 {{.*}} `foo` CHECK-LABEL: Mod 0002 | `* Linker *`: Reorder the object files and verify that the other table is selected. Index: lld/trunk/test/COFF/pdb-invalid-func-type.yaml =================================================================== --- lld/trunk/test/COFF/pdb-invalid-func-type.yaml +++ lld/trunk/test/COFF/pdb-invalid-func-type.yaml @@ -7,7 +7,7 @@ # RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s # CHECK: Mod 0000 | `{{.*}}pdb-invalid-func-type.yaml.tmp.obj`: -# CHECK: 4 | S_GPROC32_ID [size = 44] `main` +# CHECK: 4 | S_GPROC32 [size = 44] `main` # CHECK: parent = 0, end = 80, addr = 0001:0000, code size = 3 # CHECK: 48 | S_FRAMEPROC [size = 32] # CHECK: 80 | S_END [size = 4] Index: lld/trunk/test/COFF/pdb-procid-remapping.test =================================================================== --- lld/trunk/test/COFF/pdb-procid-remapping.test +++ lld/trunk/test/COFF/pdb-procid-remapping.test @@ -0,0 +1,29 @@ +# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj +# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj +# RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ +# RUN: %t1.obj %t2.obj + +# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s + +CHECK: Symbols +CHECK-NEXT: ============================================================ +CHECK-LABEL: Mod 0000 | +CHECK: 92 | S_GPROC32 [size = 44] `main` +CHECK-NEXT: parent = 0, end = 168, addr = 0002:0000, code size = 14 +CHECK-NEXT: type = `0x1004 (int ())`, debug start = 4, debug end = 9, flags = none +CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] +CHECK-NEXT: size = 40, padding size = 0, offset to padding = 0 +CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 +CHECK-NEXT: flags = has async eh | opt speed +CHECK-NEXT: 168 | S_END [size = 4] +CHECK-LABEL: Mod 0001 | +CHECK: 92 | S_GPROC32 [size = 44] `foo` +CHECK-NEXT: parent = 0, end = 168, addr = 0002:0016, code size = 6 +CHECK-NEXT: type = `0x1001 (int ())`, debug start = 0, debug end = 5, flags = none +CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] +CHECK-NEXT: size = 0, padding size = 0, offset to padding = 0 +CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 +CHECK-NEXT: flags = has async eh | opt speed +CHECK-NEXT: 168 | S_END [size = 4] +CHECK-LABEL: Mod 0002 | +CHECK: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *` Index: lld/trunk/test/COFF/pdb-scopes.test =================================================================== --- lld/trunk/test/COFF/pdb-scopes.test +++ lld/trunk/test/COFF/pdb-scopes.test @@ -34,12 +34,12 @@ RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s CHECK-LABEL: Mod 0000 | `{{.*}}pdb-scopes.test.tmp-a.obj`: -CHECK: 104 | S_GPROC32_ID [size = 44] `g` +CHECK: 104 | S_GPROC32 [size = 44] `g` CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 5 CHECK: debug start = 4, debug end = 4, flags = none CHECK: 180 | S_REGREL32 [size = 16] `x` CHECK: 196 | S_END [size = 4] -CHECK: 200 | S_GPROC32_ID [size = 44] `main` +CHECK: 200 | S_GPROC32 [size = 44] `main` CHECK: parent = 0, end = 384, addr = 0002:0016, code size = 58 CHECK: debug start = 8, debug end = 53, flags = none CHECK: 276 | S_REGREL32 [size = 20] `argc` @@ -56,7 +56,7 @@ CHECK: 384 | S_END [size = 4] CHECK-LABEL: Mod 0001 | `{{.*}}pdb-scopes.test.tmp-b.obj`: -CHECK: 104 | S_GPROC32_ID [size = 44] `f` +CHECK: 104 | S_GPROC32 [size = 44] `f` CHECK: parent = 0, end = 284, addr = 0002:0080, code size = 62 CHECK: debug start = 8, debug end = 57, flags = none CHECK: 180 | S_REGREL32 [size = 16] `x` Index: lld/trunk/test/COFF/pdb-symbol-types.yaml =================================================================== --- lld/trunk/test/COFF/pdb-symbol-types.yaml +++ lld/trunk/test/COFF/pdb-symbol-types.yaml @@ -21,7 +21,7 @@ # CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c # CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 # CHECK: flags = security checks | hot patchable -# CHECK: 116 | S_GPROC32_ID [size = 44] `main` +# CHECK: 116 | S_GPROC32 [size = 44] `main` # CHECK: parent = 0, end = 192, addr = 0002:0000, code size = 7 # CHECK: debug start = 0, debug end = 6, flags = none # CHECK: 160 | S_FRAMEPROC [size = 32] Index: lld/trunk/test/COFF/pdb-type-server-simple.test =================================================================== --- lld/trunk/test/COFF/pdb-type-server-simple.test +++ lld/trunk/test/COFF/pdb-type-server-simple.test @@ -63,7 +63,7 @@ CHECK: ============================================================ CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj` -CHECK: 104 | S_GPROC32_ID [size = 44] `main` +CHECK: 104 | S_GPROC32 [size = 44] `main` CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27 CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none CHECK: 200 | S_UDT [size = 12] `Foo` @@ -75,7 +75,7 @@ CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 CHECK: flags = security checks | hot patchable -CHECK: 104 | S_GPROC32_ID [size = 44] `g` +CHECK: 104 | S_GPROC32 [size = 44] `g` CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13 CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none CHECK: 148 | S_FRAMEPROC [size = 32] Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -52,6 +52,21 @@ return Error::success(); } + template + static Expected deserializeAs(ArrayRef Data) { + CVType CVT; + CVT.RecordData = Data; + MappingInfo I(CVT.content()); + const RecordPrefix *Prefix = + reinterpret_cast(Data.data()); + TypeRecordKind K = + static_cast(uint16_t(Prefix->RecordKind)); + T Record(K); + if (auto EC = deserializeAs(CVT, Record)) + return std::move(EC); + return Record; + } + Error visitTypeBegin(CVType &Record) override { assert(!Mapping && "Already in a type mapping!"); Mapping = llvm::make_unique(Record.content()); Index: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h @@ -30,11 +30,17 @@ SmallVectorImpl &Refs); void discoverTypeIndices(const CVType &Type, SmallVectorImpl &Indices); +void discoverTypeIndices(ArrayRef RecordData, + SmallVectorImpl &Indices); /// Discover type indices in symbol records. Returns false if this is an unknown /// record. -bool discoverTypeIndices(const CVSymbol &Symbol, - SmallVectorImpl &Refs); +bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol, + SmallVectorImpl &Refs); +bool discoverTypeIndicesInSymbol(ArrayRef RecordData, + SmallVectorImpl &Refs); +bool discoverTypeIndicesInSymbol(ArrayRef RecordData, + SmallVectorImpl &Indices); } } Index: llvm/trunk/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -395,6 +395,7 @@ case SymbolKind::S_CONSTANT: Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type break; + case SymbolKind::S_BPREL32: case SymbolKind::S_REGREL32: Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type break; @@ -450,17 +451,17 @@ ::discoverTypeIndices(Type.content(), Type.kind(), Refs); } -void llvm::codeview::discoverTypeIndices(const CVType &Type, - SmallVectorImpl &Indices) { - +static void resolveTypeIndexReferences(ArrayRef RecordData, + ArrayRef Refs, + SmallVectorImpl &Indices) { Indices.clear(); - SmallVector Refs; - discoverTypeIndices(Type, Refs); if (Refs.empty()) return; - BinaryStreamReader Reader(Type.content(), support::little); + RecordData = RecordData.drop_front(sizeof(RecordPrefix)); + + BinaryStreamReader Reader(RecordData, support::little); for (const auto &Ref : Refs) { Reader.setOffset(Ref.Offset); FixedStreamArray Run; @@ -469,6 +470,18 @@ } } +void llvm::codeview::discoverTypeIndices(const CVType &Type, + SmallVectorImpl &Indices) { + return discoverTypeIndices(Type.RecordData, Indices); +} + +void llvm::codeview::discoverTypeIndices(ArrayRef RecordData, + SmallVectorImpl &Indices) { + SmallVector Refs; + discoverTypeIndices(RecordData, Refs); + resolveTypeIndexReferences(RecordData, Refs, Indices); +} + void llvm::codeview::discoverTypeIndices(ArrayRef RecordData, SmallVectorImpl &Refs) { const RecordPrefix *P = @@ -477,8 +490,26 @@ ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs); } -bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym, - SmallVectorImpl &Refs) { +bool llvm::codeview::discoverTypeIndicesInSymbol( + const CVSymbol &Sym, SmallVectorImpl &Refs) { SymbolKind K = Sym.kind(); return ::discoverTypeIndices(Sym.content(), K, Refs); } + +bool llvm::codeview::discoverTypeIndicesInSymbol( + ArrayRef RecordData, SmallVectorImpl &Refs) { + const RecordPrefix *P = + reinterpret_cast(RecordData.data()); + SymbolKind K = static_cast(uint16_t(P->RecordKind)); + return ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, + Refs); +} + +bool llvm::codeview::discoverTypeIndicesInSymbol( + ArrayRef RecordData, SmallVectorImpl &Indices) { + SmallVector Refs; + if (!discoverTypeIndicesInSymbol(RecordData, Refs)) + return false; + resolveTypeIndexReferences(RecordData, Refs, Indices); + return true; +} Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -837,6 +837,7 @@ ExitOnError Err("Unexpected error processing symbols: "); + auto &Ids = Err(initializeTypes(StreamIPI)); auto &Types = Err(initializeTypes(StreamTPI)); iterateModules( @@ -852,7 +853,8 @@ SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb); - MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types); + MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Ids, + Types); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); @@ -936,9 +938,13 @@ auto ExpectedTypes = initializeTypes(StreamTPI); if (!ExpectedTypes) return ExpectedTypes.takeError(); + auto ExpectedIds = initializeTypes(StreamIPI); + if (!ExpectedIds) + return ExpectedIds.takeError(); SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb); - MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedTypes); + MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedIds, + *ExpectedTypes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); Index: llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.h =================================================================== --- llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.h +++ llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.h @@ -23,8 +23,9 @@ class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks { public: MinimalSymbolDumper(LinePrinter &P, bool RecordBytes, + codeview::LazyRandomTypeCollection &Ids, codeview::LazyRandomTypeCollection &Types) - : P(P), Types(Types) {} + : P(P), Ids(Ids), Types(Types) {} Error visitSymbolBegin(codeview::CVSymbol &Record) override; Error visitSymbolBegin(codeview::CVSymbol &Record, uint32_t Offset) override; @@ -37,12 +38,16 @@ #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" private: + std::string typeOrIdIndex(codeview::TypeIndex TI, bool IsType) const; + std::string typeIndex(codeview::TypeIndex TI) const; + std::string idIndex(codeview::TypeIndex TI) const; LinePrinter &P; + codeview::LazyRandomTypeCollection &Ids; codeview::LazyRandomTypeCollection &Types; }; } // namespace pdb } // namespace llvm #endif \ No newline at end of file Index: llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ llvm/trunk/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -389,10 +389,12 @@ return Error::success(); } -std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const { +std::string MinimalSymbolDumper::typeOrIdIndex(codeview::TypeIndex TI, + bool IsType) const { if (TI.isSimple()) return formatv("{0}", TI).str(); - StringRef Name = Types.getTypeName(TI); + auto &Container = IsType ? Types : Ids; + StringRef Name = Container.getTypeName(TI); if (Name.size() > 32) { Name = Name.take_front(32); return formatv("{0} ({1}...)", TI, Name); @@ -400,6 +402,14 @@ return formatv("{0} ({1})", TI, Name); } +std::string MinimalSymbolDumper::idIndex(codeview::TypeIndex TI) const { + return typeOrIdIndex(TI, false); +} + +std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const { + return typeOrIdIndex(TI, true); +} + Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { P.format(" `{0}`", Block.Name); AutoIndent Indent(P, 7); @@ -727,9 +737,19 @@ Proc.Parent, Proc.End, formatSegmentOffset(Proc.Segment, Proc.CodeOffset), Proc.CodeSize); - // FIXME: It seems FunctionType is sometimes an id and sometimes a type. + bool IsType = true; + switch (Proc.getKind()) { + case SymbolRecordKind::GlobalProcIdSym: + case SymbolRecordKind::ProcIdSym: + case SymbolRecordKind::DPCProcIdSym: + IsType = false; + break; + default: + break; + } P.formatLine("type = `{0}`, debug start = {1}, debug end = {2}, flags = {3}", - typeIndex(Proc.FunctionType), Proc.DbgStart, Proc.DbgEnd, + typeOrIdIndex(Proc.FunctionType, IsType), Proc.DbgStart, + Proc.DbgEnd, formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags)); return Error::success(); } Index: llvm/trunk/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp =================================================================== --- llvm/trunk/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp +++ llvm/trunk/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp @@ -131,7 +131,7 @@ void discoverTypeIndicesInSymbols() { Refs.resize(Symbols.size()); for (uint32_t I = 0; I < Symbols.size(); ++I) - discoverTypeIndices(Symbols[I], Refs[I]); + discoverTypeIndicesInSymbol(Symbols[I], Refs[I]); } // Helper function to write out a field list record with the given list