Index: lld/COFF/PDB.cpp =================================================================== --- lld/COFF/PDB.cpp +++ lld/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/RecordName.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" @@ -460,7 +461,78 @@ S.OpeningRecord->PtrEnd = CurOffset; } +static bool symbolGoesInModuleStream(const CVSymbol &Sym) { + switch (Sym.kind()) { + case SymbolKind::S_GDATA32: + case SymbolKind::S_CONSTANT: + case SymbolKind::S_UDT: + // We really should not be seeing S_PROCREF and S_LPROCREF in the first place + // since they are synthesized by the linker in response to S_GPROC32 and + // S_LPROC32, but if we do see them, don't put them in the module stream I + // guess. + case SymbolKind::S_PROCREF: + case SymbolKind::S_LPROCREF: + return false; + // S_GDATA32 does not go in the module stream, but S_LDATA32 does. + case SymbolKind::S_LDATA32: + default: + return true; + } +} + +static bool symbolGoesInGlobalsStream(const CVSymbol &Sym) { + switch (Sym.kind()) { + case SymbolKind::S_CONSTANT: + case SymbolKind::S_UDT: + case SymbolKind::S_GDATA32: + // S_LDATA32 goes in both the module stream and the globals stream. + case SymbolKind::S_LDATA32: + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + // We really should not be seeing S_PROCREF and S_LPROCREF in the first place + // since they are synthesized by the linker in response to S_GPROC32 and + // S_LPROC32, but if we do see them, copy them straight through. + case SymbolKind::S_PROCREF: + case SymbolKind::S_LPROCREF: + return true; + default: + return false; + } +} + +static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, ObjFile &File, + const CVSymbol &Sym) { + switch (Sym.kind()) { + case SymbolKind::S_CONSTANT: + case SymbolKind::S_UDT: + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: + case SymbolKind::S_PROCREF: + case SymbolKind::S_LPROCREF: + Builder.addGlobalSymbol(Sym); + break; + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: { + SymbolRecordKind K = SymbolRecordKind::ProcRefSym; + if (Sym.kind() == SymbolKind::S_LPROC32) + K = SymbolRecordKind::LocalProcRef; + ProcRefSym PS(K); + PS.Module = static_cast(File.ModuleDBI->getModuleIndex()); + // For some reason, MSVC seems to add one to this value. + ++PS.Module; + PS.Name = getSymbolName(Sym); + PS.SumName = 0; + PS.SymOffset = File.ModuleDBI->getNextSymbolOffset(); + Builder.addGlobalSymbol(PS); + break; + } + default: + llvm_unreachable("Invalid symbol kind!"); + } +} + static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File, + pdb::GSIStreamBuilder &GsiBuilder, const CVIndexMap &IndexMap, const TypeTableBuilder &IDTable, BinaryStreamRef SymData) { @@ -500,8 +572,15 @@ else if (symbolEndsScope(NewKind)) scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); + // Add the symbol to the globals stream if necessary. Do this before adding + // the symbol to the module since we may need to get the next symbol offset, + // and writing to the module's symbol stream will update that offset. + if (symbolGoesInGlobalsStream(NewSym)) + addGlobalSymbol(GsiBuilder, *File, NewSym); + // Add the symbol to the module. - File->ModuleDBI->addSymbol(NewSym); + if (symbolGoesInModuleStream(NewSym)) + File->ModuleDBI->addSymbol(NewSym); } } @@ -567,7 +646,8 @@ File->ModuleDBI->addDebugSubsection(SS); break; case DebugSubsectionKind::Symbols: - mergeSymbolRecords(Alloc, File, IndexMap, IDTable, SS.getRecordData()); + mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap, + IDTable, SS.getRecordData()); break; default: // FIXME: Process the rest of the subsections. @@ -626,9 +706,10 @@ // Construct IPI stream contents. addTypeInfo(Builder.getIpiBuilder(), IDTable); - // Compute the public symbols. + // Compute the public and global symbols. + auto &GsiBuilder = Builder.getGsiBuilder(); std::vector Publics; - Symtab->forEachSymbol([&Publics](Symbol *S) { + Symtab->forEachSymbol([&Publics, &GsiBuilder](Symbol *S) { // Only emit defined, live symbols that have a chunk. auto *Def = dyn_cast(S->body()); if (Def && Def->isLive() && Def->getChunk()) @@ -641,7 +722,6 @@ [](const PublicSym32 &L, const PublicSym32 &R) { return L.Name < R.Name; }); - auto &GsiBuilder = Builder.getGsiBuilder(); for (const PublicSym32 &Pub : Publics) GsiBuilder.addPublicSymbol(Pub); } Index: lld/test/COFF/pdb-comdat.test =================================================================== --- lld/test/COFF/pdb-comdat.test +++ lld/test/COFF/pdb-comdat.test @@ -26,7 +26,7 @@ RUN: yaml2obj %S/Inputs/pdb_comdat_main.yaml -o pdb_comdat_main.obj RUN: yaml2obj %S/Inputs/pdb_comdat_bar.yaml -o pdb_comdat_bar.obj RUN: lld-link pdb_comdat_main.obj pdb_comdat_bar.obj -out:t.exe -debug -pdb:t.pdb -nodefaultlib -entry:main -RUN: llvm-pdbutil dump -l -symbols t.pdb | FileCheck %s +RUN: llvm-pdbutil dump -l -symbols -globals t.pdb | FileCheck %s CHECK: Lines CHECK: ============================================================ @@ -38,6 +38,20 @@ CHECK-NOT: c:\src\llvm-project\build\foo.h CHECK-LABEL: Mod 0002 | `* Linker *`: +CHECK-LABEL: Global Symbols +CHECK-NEXT: ============================================================ +CHECK-NEXT: Records +CHECK-NEXT: 84 | S_PROCREF [size = 20] `main` +CHECK-NEXT: module = 1, sum name = 0, offset = 120 +CHECK-NEXT: 128 | S_PROCREF [size = 20] `foo` +CHECK-NEXT: module = 1, sum name = 0, offset = 208 +CHECK-NEXT: 148 | S_PROCREF [size = 20] `bar` +CHECK-NEXT: module = 2, sum name = 0, offset = 120 +CHECK-NEXT: 104 | S_GDATA32 [size = 24] `global` +CHECK-NEXT: type = 0x0074 (int), addr = 0000:0000 +CHECK-NEXT: 168 | S_GDATA32 [size = 24] `global` +CHECK-NEXT: type = 0x0074 (int), addr = 0000:0000 + CHECK: Symbols CHECK: ============================================================ CHECK-LABEL: Mod 0000 | `{{.*}}pdb_comdat_main.obj`: @@ -54,17 +68,15 @@ CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 CHECK: flags = has async eh | opt speed CHECK: 196 | S_END [size = 4] -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 [size = 44] `foo` -CHECK: parent = 0, end = 308, addr = 0002:0032, code size = 15 +CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `0x100A` +CHECK: 208 | S_GPROC32 [size = 44] `foo` +CHECK: parent = 0, end = 284, addr = 0002:0032, code size = 15 CHECK: debug start = 0, debug end = 14, flags = none -CHECK: 276 | S_FRAMEPROC [size = 32] +CHECK: 252 | S_FRAMEPROC [size = 32] CHECK: size = 0, padding size = 0, offset to padding = 0 CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 CHECK: flags = marked inline | has async eh | opt speed -CHECK: 308 | S_END [size = 4] +CHECK: 284 | S_END [size = 4] CHECK-LABEL: Mod 0001 | `{{.*}}pdb_comdat_bar.obj`: CHECK: 4 | S_OBJNAME [size = 56] sig=0, `C:\src\llvm-project\build\pdb_comdat_bar.obj` CHECK: 60 | S_COMPILE3 [size = 60] @@ -79,9 +91,7 @@ CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 CHECK: flags = has async eh | opt speed CHECK: 196 | S_END [size = 4] -CHECK: 200 | S_GDATA32 [size = 24] `global` -CHECK: type = 0x0074 (int), addr = 0000:0000 -CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100D` +CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `0x100D` CHECK-NOT: S_GPROC32 {{.*}} `foo` CHECK-LABEL: Mod 0002 | `* Linker *`: Index: lld/test/COFF/pdb-global-gc.yaml =================================================================== --- lld/test/COFF/pdb-global-gc.yaml +++ lld/test/COFF/pdb-global-gc.yaml @@ -2,7 +2,7 @@ # RUN: llvm-mc %S/Inputs/pdb-global-gc.s -triple x86_64-windows-msvc -filetype=obj -o %t2.obj # RUN: lld-link %t.obj %t2.obj -debug -entry:main \ # RUN: -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb -verbose -# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s # This tests the case where an __imp_ chunk is discarded by linker GC. The debug # info may refer to the __imp_ symbol still. @@ -12,13 +12,17 @@ # int discarded() { return __wc_mb_cur; } # int main() { return g2; } -# CHECK: Symbols -# CHECK: ============================================================ -# CHECK: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`: -# CHECK: 4 | S_GDATA32 [size = 28] `__wc_mb_cur` -# CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 -# CHECK: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`: -# CHECK: Mod 0002 | `* Linker *`: +# CHECK: Global Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Records +# CHECK-NEXT: 20 | S_GDATA32 [size = 28] `__wc_mb_cur` +# CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 + +# CHECK: Symbols +# CHECK: ============================================================ +# CHECK-NEXT: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`: +# CHECK-NEXT: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`: +# CHECK-NEXT: Mod 0002 | `* Linker *`: --- !COFF header: Index: lld/test/COFF/pdb-import-gc.yaml =================================================================== --- lld/test/COFF/pdb-import-gc.yaml +++ lld/test/COFF/pdb-import-gc.yaml @@ -1,7 +1,7 @@ # RUN: yaml2obj %s -o %t.obj # RUN: lld-link %t.obj %S/Inputs/pdb-import-gc.lib -debug -entry:main \ # RUN: -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb -# RUN: llvm-pdbutil dump -publics -symbols %t.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -globals -symbols %t.pdb | FileCheck %s # This tests the case where an __imp_ chunk is discarded by linker GC. The debug # info may refer to the __imp_ symbol still. @@ -11,12 +11,16 @@ # int discarded() { return __wc_mb_cur; } # int main() { return g2; } -# CHECK: Symbols -# CHECK: ============================================================ -# CHECK: Mod 0000 | `{{.*}}pdb-import-gc.yaml.tmp.obj`: -# CHECK: 4 | S_GDATA32 [size = 32] `__imp___wc_mb_cur` -# CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 -# CHECK: Mod 0001 | `* Linker *`: +# CHECK: Global Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Records +# CHECK-NEXT: 20 | S_GDATA32 [size = 32] `__imp___wc_mb_cur` +# CHECK-NEXT: type = 0x0070 (char), addr = 0000:0000 + +# CHECK: Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Mod 0000 | `{{.*}}pdb-import-gc.yaml.tmp.obj`: +# CHECK-NEXT: Mod 0001 | `* Linker *`: --- !COFF header: Index: lld/test/COFF/pdb-safeseh.yaml =================================================================== --- lld/test/COFF/pdb-safeseh.yaml +++ lld/test/COFF/pdb-safeseh.yaml @@ -1,16 +1,17 @@ # RUN: yaml2obj %s -o %t.obj # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj -# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in # it in this debug info. This is similar to the relocations in the loadcfg.obj # file in the MSVC CRT. We need to make sure that our relocation logic matches # MSVC's for these absolute, linker-provided symbols. -# CHECK: Mod 0000 | -# CHECK-NEXT: 4 | S_GDATA32 [size = 40] `___safe_se_handler_table` -# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 -# CHECK-NEXT: Mod 0001 | `* Linker *`: +# CHECK: Global Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Records +# CHECK-NEXT: 20 | S_GDATA32 [size = 40] `___safe_se_handler_table` +# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 --- !COFF header: Index: lld/test/COFF/pdb-secrel-absolute.yaml =================================================================== --- lld/test/COFF/pdb-secrel-absolute.yaml +++ lld/test/COFF/pdb-secrel-absolute.yaml @@ -1,16 +1,17 @@ # RUN: yaml2obj %s -o %t.obj # RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj -# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s # There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in # it in this debug info. This is similar to the relocations in the loadcfg.obj # file in the MSVC CRT. We need to make sure that our relocation logic matches # MSVC's for these absolute, linker-provided symbols. -# CHECK: Mod 0000 | -# CHECK-NEXT: 4 | S_GDATA32 [size = 36] `__guard_fids_table` -# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 -# CHECK-NEXT: Mod 0001 | `* Linker *`: +# CHECK: Global Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Records +# CHECK-NEXT: 20 | S_GDATA32 [size = 36] `__guard_fids_table` +# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 --- !COFF header: Index: lld/test/COFF/pdb-symbol-types.yaml =================================================================== --- lld/test/COFF/pdb-symbol-types.yaml +++ lld/test/COFF/pdb-symbol-types.yaml @@ -1,6 +1,6 @@ # RUN: yaml2obj %s -o %t.obj # RUN: lld-link %t.obj -nodefaultlib -entry:main -debug -out:%t.exe -pdb:%t.pdb -# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s # To regenerate the object file: # $ cat symbol-types.c @@ -13,6 +13,18 @@ # Note that the type of 'global' goes from 0x1005 in the object file to 0x1004 # in the PDB because the LF_FUNC_ID is moved to the id stream. +# CHECK-LABEL: Global Symbols +# CHECK-NEXT: ============================================================ +# CHECK-NEXT: Records +# CHECK-NEXT: 48 | S_PROCREF [size = 20] `main` +# CHECK-NEXT: module = 1, sum name = 0, offset = 116 +# CHECK-NEXT: 96 | S_UDT [size = 16] `UDT_Foo` +# CHECK-NEXT: original type = 0x1004 +# CHECK-NEXT: 112 | S_UDT [size = 12] `Foo` +# CHECK-NEXT: original type = 0x1004 +# CHECK-NEXT: 68 | S_GDATA32 [size = 28] `global_foo` +# CHECK-NEXT: type = 0x1004 (Foo), addr = 0001:0000 + # CHECK: Symbols # CHECK: ============================================================ # CHECK-LABEL: Mod 0000 | `{{.*}}pdb-symbol-types.yaml.tmp.obj`: @@ -29,13 +41,7 @@ # CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 # CHECK: flags = has async eh | opt speed # CHECK: 192 | S_END [size = 4] -# CHECK: 196 | S_GDATA32 [size = 28] `global_foo` -# CHECK: type = 0x1004 (Foo), addr = 0001:0000 -# CHECK: 224 | S_UDT [size = 16] `UDT_Foo` -# CHECK: original type = 0x1004 -# CHECK: 240 | S_UDT [size = 12] `Foo` -# CHECK: original type = 0x1004 -# CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `0x100A` +# CHECK: 196 | S_BUILDINFO [size = 8] BuildId = `0x100A` # CHECK-LABEL: Mod 0001 | `* Linker *`: --- !COFF Index: lld/test/COFF/pdb-type-server-simple.test =================================================================== --- lld/test/COFF/pdb-type-server-simple.test +++ lld/test/COFF/pdb-type-server-simple.test @@ -21,7 +21,7 @@ RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib -RUN: llvm-pdbutil dump -symbols -types -ids %t/t.pdb | FileCheck %s +RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s CHECK-LABEL: Types (TPI Stream) @@ -59,6 +59,18 @@ CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28] CHECK: {{.*}}: `b.c` +CHECK-LABEL: Global Symbols +CHECK: ============================================================ +CHECK-NEXT: Records +CHECK-NEXT: 36 | S_PROCREF [size = 20] `main` +CHECK-NEXT: module = 1, sum name = 0, offset = 104 +CHECK-NEXT: 68 | S_PROCREF [size = 16] `g` +CHECK-NEXT: module = 2, sum name = 0, offset = 104 +CHECK-NEXT: 56 | S_UDT [size = 12] `Foo` +CHECK-NEXT: original type = 0x1006 +CHECK-NEXT: 84 | S_UDT [size = 12] `Foo` +CHECK-NEXT: original type = 0x1006 + CHECK-LABEL: Symbols CHECK: ============================================================ CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: @@ -66,9 +78,7 @@ 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` -CHECK: original type = [[FOO_COMPLETE]] -CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]` +CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]` CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`: CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj` CHECK: 44 | S_COMPILE3 [size = 60] @@ -85,7 +95,5 @@ CHECK: 180 | S_REGREL32 [size = 16] `p` CHECK: type = [[FOO_PTR]] (Foo*), register = rsp, offset = 8 CHECK: 196 | S_END [size = 4] -CHECK: 200 | S_UDT [size = 12] `Foo` -CHECK: original type = [[FOO_COMPLETE]] -CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` +CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` CHECK-LABEL: Mod 0002 | `* Linker *`: Index: llvm/include/llvm/DebugInfo/CodeView/RecordName.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/RecordName.h +++ llvm/include/llvm/DebugInfo/CodeView/RecordName.h @@ -1,4 +1,4 @@ -//===- TypeName.h --------------------------------------------- *- C++ --*-===// +//===- RecordName.h ------------------------------------------- *- C++ --*-===// // // The LLVM Compiler Infrastructure // @@ -7,16 +7,18 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H +#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H +#define LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" namespace llvm { namespace codeview { std::string computeTypeName(TypeCollection &Types, TypeIndex Index); -} +StringRef getSymbolName(CVSymbol Sym); +} // namespace codeview } // namespace llvm #endif Index: llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -54,14 +54,12 @@ 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); + CVType CVT(static_cast(K), Data); if (auto EC = deserializeAs(CVT, Record)) return std::move(EC); return Record; Index: llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -412,6 +412,10 @@ return (Options & ClassOptions::HasUniqueName) != ClassOptions::None; } + bool isNested() const { + return (Options & ClassOptions::Nested) != ClassOptions::None; + } + uint16_t getMemberCount() const { return MemberCount; } ClassOptions getOptions() const { return Options; } TypeIndex getFieldList() const { return FieldList; } Index: llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h @@ -58,6 +58,12 @@ void addPublicSymbol(const codeview::PublicSym32 &Pub); + void addGlobalSymbol(const codeview::ProcRefSym &Sym); + void addGlobalSymbol(const codeview::DataSym &Sym); + void addGlobalSymbol(const codeview::ConstantSym &Sym); + void addGlobalSymbol(const codeview::UDTSym &Sym); + void addGlobalSymbol(const codeview::CVSymbol &Sym); + private: uint32_t calculatePublicsHashStreamSize() const; uint32_t calculateGlobalsHashStreamSize() const; Index: llvm/lib/DebugInfo/CodeView/CMakeLists.txt =================================================================== --- llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -19,6 +19,7 @@ Formatters.cpp LazyRandomTypeCollection.cpp Line.cpp + RecordName.cpp RecordSerialization.cpp StringsAndChecksums.cpp SymbolRecordMapping.cpp @@ -27,7 +28,6 @@ TypeDumpVisitor.cpp TypeIndex.cpp TypeIndexDiscovery.cpp - TypeName.cpp TypeRecordMapping.cpp TypeSerializer.cpp TypeStreamMerger.cpp Index: llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -13,7 +13,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeName.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" Index: llvm/lib/DebugInfo/CodeView/RecordName.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/RecordName.cpp +++ llvm/lib/DebugInfo/CodeView/RecordName.cpp @@ -1,4 +1,4 @@ -//===- TypeName.cpp ------------------------------------------- *- C++ --*-===// +//===- RecordName.cpp ----------------------------------------- *- C++ --*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/TypeName.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/FormatVariadic.h" @@ -241,3 +243,78 @@ } return Computer.name(); } + +static int getSymbolNameOffset(CVSymbol Sym) { + switch (Sym.kind()) { + // See ProcSym + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_LPROC32_DPC: + case SymbolKind::S_LPROC32_DPC_ID: + return 35; + // See Thunk32Sym + case SymbolKind::S_THUNK32: + return 21; + // See SectionSym + case SymbolKind::S_SECTION: + return 16; + // See CoffGroupSym + case SymbolKind::S_COFFGROUP: + return 14; + // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym + case SymbolKind::S_PUB32: + case SymbolKind::S_FILESTATIC: + case SymbolKind::S_REGREL32: + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: + case SymbolKind::S_LMANDATA: + case SymbolKind::S_GMANDATA: + case SymbolKind::S_LTHREAD32: + case SymbolKind::S_GTHREAD32: + return 10; + // See RegisterSym and LocalSym + case SymbolKind::S_REGISTER: + case SymbolKind::S_LOCAL: + return 6; + // See BlockSym + case SymbolKind::S_BLOCK32: + return 18; + // See LabelSym + case SymbolKind::S_LABEL32: + return 7; + // See ObjNameSym, ExportSym, and UDTSym + case SymbolKind::S_OBJNAME: + case SymbolKind::S_EXPORT: + case SymbolKind::S_UDT: + return 4; + // See BPRelativeSym + case SymbolKind::S_BPREL32: + return 8; + default: + return -1; + } +} + +StringRef llvm::codeview::getSymbolName(CVSymbol Sym) { + if (Sym.kind() == SymbolKind::S_CONSTANT) { + // S_CONSTANT is preceded by an APSInt, which has a variable length. So we + // have to do a full deserialization. + BinaryStreamReader Reader(Sym.content(), llvm::support::little); + // The container doesn't matter for single records. + SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile); + ConstantSym Const(SymbolKind::S_CONSTANT); + cantFail(Mapping.visitSymbolBegin(Sym)); + cantFail(Mapping.visitKnownRecord(Sym, Const)); + cantFail(Mapping.visitSymbolEnd(Sym)); + return Const.Name; + } + + int Offset = getSymbolNameOffset(Sym); + if (Offset == -1) + return StringRef(); + + StringRef StringData = toStringRef(Sym.content()).drop_front(Offset); + return StringData.split('\0').first; +} Index: llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp @@ -10,7 +10,7 @@ #include "llvm/DebugInfo/CodeView/TypeTableCollection.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeName.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/BinaryStreamReader.h" Index: llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" @@ -27,13 +28,6 @@ using namespace llvm::pdb; using namespace llvm::codeview; -static StringRef getSymbolName(const CVSymbol &Sym) { - assert(Sym.kind() == S_PUB32 && "handle other kinds"); - PublicSym32 PSL = - cantFail(SymbolDeserializer::deserializeAs(Sym)); - return PSL.Name; -} - struct llvm::pdb::GSIHashStreamBuilder { std::vector Records; uint32_t StreamIndex; @@ -45,6 +39,13 @@ uint32_t calculateRecordByteSize() const; Error commit(BinaryStreamWriter &Writer); void finalizeBuckets(uint32_t RecordZeroOffset); + + template void addSymbol(const T &Symbol, MSFBuilder &Msf) { + T Copy(Symbol); + Records.push_back(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(), + CodeViewContainer::Pdb)); + } + void addSymbol(const CVSymbol &Symbol) { Records.push_back(Symbol); } }; uint32_t GSIHashStreamBuilder::calculateSerializedLength() const { @@ -222,9 +223,27 @@ } void GSIStreamBuilder::addPublicSymbol(const PublicSym32 &Pub) { - PublicSym32 Copy(Pub); - PSH->Records.push_back(SymbolSerializer::writeOneSymbol( - Copy, Msf.getAllocator(), CodeViewContainer::Pdb)); + PSH->addSymbol(Pub, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const ProcRefSym &Sym) { + GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const DataSym &Sym) { + GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) { + GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const UDTSym &Sym) { + GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Sym) { + GSH->addSymbol(Sym); } static Error writeRecords(BinaryStreamWriter &Writer,