Index: lld/trunk/COFF/Config.h =================================================================== --- lld/trunk/COFF/Config.h +++ lld/trunk/COFF/Config.h @@ -92,6 +92,7 @@ bool WriteSymtab = true; unsigned DebugTypes = static_cast(DebugType::None); llvm::SmallString<128> PDBPath; + std::vector Argv; // Symbols in this set are considered as live by the garbage collector. std::set GCRoot; Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -55,8 +55,8 @@ bool link(ArrayRef Args, raw_ostream &Diag) { ErrorCount = 0; ErrorOS = &Diag; - Argv0 = Args[0]; Config = make(); + Config->Argv = {Args.begin(), Args.end()}; Config->ColorDiagnostics = (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); Driver = make(); Index: lld/trunk/COFF/Error.h =================================================================== --- lld/trunk/COFF/Error.h +++ lld/trunk/COFF/Error.h @@ -18,7 +18,6 @@ extern uint64_t ErrorCount; extern llvm::raw_ostream *ErrorOS; -extern llvm::StringRef Argv0; void log(const Twine &Msg); void message(const Twine &Msg); Index: lld/trunk/COFF/Error.cpp =================================================================== --- lld/trunk/COFF/Error.cpp +++ lld/trunk/COFF/Error.cpp @@ -29,7 +29,6 @@ static std::mutex Mu; namespace coff { -StringRef Argv0; uint64_t ErrorCount; raw_ostream *ErrorOS; @@ -45,7 +44,7 @@ } static void print(StringRef S, raw_ostream::Colors C) { - *ErrorOS << Argv0 + ": "; + *ErrorOS << Config->Argv[0] << ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; @@ -58,7 +57,7 @@ void log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard Lock(Mu); - outs() << Argv0 << ": " << Msg << "\n"; + outs() << Config->Argv[0] << ": " << Msg << "\n"; outs().flush(); } } Index: lld/trunk/COFF/PDB.h =================================================================== --- lld/trunk/COFF/PDB.h +++ lld/trunk/COFF/PDB.h @@ -23,8 +23,7 @@ namespace coff { class SymbolTable; -void createPDB(llvm::StringRef Path, SymbolTable *Symtab, - llvm::ArrayRef SectionTable, +void createPDB(SymbolTable *Symtab, llvm::ArrayRef SectionTable, const llvm::codeview::DebugInfo *DI); } } Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -18,19 +18,20 @@ #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" @@ -396,9 +397,54 @@ addTypeInfo(Builder.getIpiBuilder(), IDTable); } +static void addLinkerModuleSymbols(StringRef Path, + pdb::DbiModuleDescriptorBuilder &Mod, + BumpPtrAllocator &Allocator) { + codeview::SymbolSerializer Serializer(Allocator, CodeViewContainer::Pdb); + codeview::ObjNameSym ONS(SymbolRecordKind::ObjNameSym); + codeview::Compile3Sym CS(SymbolRecordKind::Compile3Sym); + codeview::EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); + + ONS.Name = "* Linker *"; + ONS.Signature = 0; + + CS.Machine = Config->is64() ? CPUType::X64 : CPUType::Intel80386; + CS.Flags = CompileSym3Flags::None; + CS.VersionBackendBuild = 0; + CS.VersionBackendMajor = 0; + CS.VersionBackendMinor = 0; + CS.VersionBackendQFE = 0; + CS.VersionFrontendBuild = 0; + CS.VersionFrontendMajor = 0; + CS.VersionFrontendMinor = 0; + CS.VersionFrontendQFE = 0; + CS.Version = "LLVM Linker"; + CS.setLanguage(SourceLanguage::Link); + + ArrayRef Args = makeArrayRef(Config->Argv).drop_front(); + std::string ArgStr = llvm::join(Args, " "); + EBS.Fields.push_back("cwd"); + SmallString<64> cwd; + llvm::sys::fs::current_path(cwd); + EBS.Fields.push_back(cwd); + EBS.Fields.push_back("exe"); + std::string Exe = + llvm::sys::fs::getMainExecutable(Config->Argv[0].data(), nullptr); + EBS.Fields.push_back(Exe); + EBS.Fields.push_back("pdb"); + EBS.Fields.push_back(Path); + EBS.Fields.push_back("cmd"); + EBS.Fields.push_back(ArgStr); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ONS, Allocator, CodeViewContainer::Pdb)); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + CS, Allocator, CodeViewContainer::Pdb)); + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + EBS, Allocator, CodeViewContainer::Pdb)); +} + // Creates a PDB file. -void coff::createPDB(StringRef Path, SymbolTable *Symtab, - ArrayRef SectionTable, +void coff::createPDB(SymbolTable *Symtab, ArrayRef SectionTable, const llvm::codeview::DebugInfo *DI) { BumpPtrAllocator Alloc; pdb::PDBFileBuilder Builder(Alloc); @@ -413,7 +459,8 @@ auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); - llvm::SmallString<128> NativePath(Path.begin(), Path.end()); + llvm::SmallString<128> NativePath(Config->PDBPath.begin(), + Config->PDBPath.end()); llvm::sys::fs::make_absolute(NativePath); llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows); @@ -449,11 +496,12 @@ auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); LinkerModule.setPdbFilePathNI(PdbFilePathNI); + addLinkerModuleSymbols(NativePath, LinkerModule, Alloc); // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); // Write to a file. - ExitOnErr(Builder.commit(Path)); + ExitOnErr(Builder.commit(Config->PDBPath)); } Index: lld/trunk/COFF/Writer.cpp =================================================================== --- lld/trunk/COFF/Writer.cpp +++ lld/trunk/COFF/Writer.cpp @@ -239,7 +239,7 @@ const llvm::codeview::DebugInfo *DI = nullptr; if (Config->DebugTypes & static_cast(coff::DebugType::CV)) DI = BuildId->DI; - createPDB(Config->PDBPath, Symtab, SectionTable, DI); + createPDB(Symtab, SectionTable, DI); } writeMapFile(OutputSections); Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -97,6 +97,7 @@ llvm::StringRef ThinLTOCacheDir; std::string Rpath; std::vector VersionDefinitions; + std::vector Argv; std::vector AuxiliaryList; std::vector SearchPaths; std::vector SymbolOrderingFile; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -74,13 +74,13 @@ raw_ostream &Error) { ErrorCount = 0; ErrorOS = &Error; - Argv0 = Args[0]; InputSections.clear(); Tar = nullptr; Config = make(); Driver = make(); Script = make(); + Config->Argv = {Args.begin(), Args.end()}; Driver->main(Args, CanExitEarly); freeArena(); Index: lld/trunk/ELF/Error.h =================================================================== --- lld/trunk/ELF/Error.h +++ lld/trunk/ELF/Error.h @@ -37,7 +37,6 @@ extern uint64_t ErrorCount; extern llvm::raw_ostream *ErrorOS; -extern llvm::StringRef Argv0; void log(const Twine &Msg); void message(const Twine &Msg); Index: lld/trunk/ELF/Error.cpp =================================================================== --- lld/trunk/ELF/Error.cpp +++ lld/trunk/ELF/Error.cpp @@ -27,7 +27,6 @@ uint64_t elf::ErrorCount; raw_ostream *elf::ErrorOS; -StringRef elf::Argv0; // The functions defined in this file can be called from multiple threads, // but outs() or errs() are not thread-safe. We protect them using a mutex. @@ -46,7 +45,7 @@ } static void print(StringRef S, raw_ostream::Colors C) { - *ErrorOS << Argv0 + ": "; + *ErrorOS << Config->Argv[0] << ": "; if (Config->ColorDiagnostics) { ErrorOS->changeColor(C, true); *ErrorOS << S; @@ -59,7 +58,7 @@ void elf::log(const Twine &Msg) { if (Config->Verbose) { std::lock_guard Lock(Mu); - outs() << Argv0 << ": " << Msg << "\n"; + outs() << Config->Argv[0] << ": " << Msg << "\n"; outs().flush(); } } Index: lld/trunk/test/COFF/pdb-linker-module.test =================================================================== --- lld/trunk/test/COFF/pdb-linker-module.test +++ lld/trunk/test/COFF/pdb-linker-module.test @@ -0,0 +1,18 @@ +RUN: lld-link /debug /pdb:%t.pdb /nodefaultlib /entry:main %S/Inputs/pdb-diff.obj +RUN: llvm-pdbutil dump -modules -symbols %t.pdb | FileCheck %s + +CHECK: Mod 0001 | `* Linker *`: +CHECK-NEXT: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *` +CHECK-NEXT: 24 | S_COMPILE3 [size = 40] +CHECK-NEXT: machine = intel 80386, Ver = LLVM Linker, language = link +CHECK-NEXT: frontend = 0.0.0.0, backend = 0.0.0.0 +CHECK-NEXT: flags = none +CHECK-NEXT: 64 | S_ENVBLOCK +CHECK-NEXT: - cwd +CHECK-NEXT: - +CHECK-NEXT: - exe +CHECK-NEXT: - {{.*}}lld-link +CHECK-NEXT: - pdb +CHECK-NEXT: - {{.*}}pdb-linker-module{{.*}}pdb +CHECK-NEXT: - cmd +CHECK-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main {{.*}}pdb-diff.obj Index: llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -735,6 +735,10 @@ uint16_t VersionBackendQFE; StringRef Version; + void setLanguage(SourceLanguage Lang) { + Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang)); + } + uint8_t getLanguage() const { return static_cast(Flags) & 0xFF; } uint32_t getFlags() const { return static_cast(Flags) & ~0xFF; }