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: 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()).take_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,