diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -110,6 +110,7 @@ bool showSummary = false; unsigned debugTypes = static_cast(DebugType::None); std::vector natvisFiles; + llvm::StringMap namedStreams; llvm::SmallString<128> pdbAltPath; llvm::SmallString<128> pdbPath; llvm::SmallString<128> pdbSourcePath; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1273,6 +1273,14 @@ config->pdbAltPath = arg->getValue(); if (args.hasArg(OPT_natvis)) config->natvisFiles = args.getAllArgValues(OPT_natvis); + if (args.hasArg(OPT_pdbstream)) { + for (const StringRef value : args.getAllArgValues(OPT_pdbstream)) { + const std::pair nameFile = value.split("="); + const StringRef name = nameFile.first; + const std::string file = nameFile.second.str(); + config->namedStreams[name] = file; + } + } if (auto *arg = args.getLastArg(OPT_pdb_source_path)) config->pdbSourcePath = arg->getValue(); diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -66,6 +66,9 @@ def pdb : P<"pdb", "PDB file path">; def pdbstripped : P<"pdbstripped", "Stripped PDB file path">; def pdbaltpath : P<"pdbaltpath", "PDB file path to embed in the image">; +def pdbstream : Joined<["/", "-", "/?", "-?"], "pdbstream:">, + MetaVarName<"=">, + HelpText<"Embed the contents of in the PDB as named stream ">; def section : P<"section", "Specify section attributes">; def stack : P<"stack", "Size of the stack">; def stub : P<"stub", "Specify DOS stub file">; diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -100,6 +100,9 @@ /// Add natvis files specified on the command line. void addNatvisFiles(); + /// Add named streams specified on the command line. + void addNamedStreams(); + /// Link CodeView from each object file in the symbol table into the PDB. void addObjectsToPDB(); @@ -1437,6 +1440,19 @@ } } +void PDBLinker::addNamedStreams() { + for (const auto &streamFile : config->namedStreams) { + const StringRef stream = streamFile.getKey(), file = streamFile.getValue(); + ErrorOr> dataOrErr = + MemoryBuffer::getFile(file); + if (!dataOrErr) { + warn("Cannot open input file: " + file); + continue; + } + exitOnErr(builder.addNamedStream(stream, (*dataOrErr)->getBuffer())); + } +} + static codeview::CPUType toCodeViewMachine(COFF::MachineTypes machine) { switch (machine) { case COFF::IMAGE_FILE_MACHINE_AMD64: @@ -1692,6 +1708,7 @@ pdb.addImportFilesToPDB(outputSections); pdb.addSections(outputSections, sectionTable); pdb.addNatvisFiles(); + pdb.addNamedStreams(); ScopedTimer t2(diskCommitTimer); codeview::GUID guid; diff --git a/lld/test/COFF/Inputs/stream.txt b/lld/test/COFF/Inputs/stream.txt new file mode 100644 --- /dev/null +++ b/lld/test/COFF/Inputs/stream.txt @@ -0,0 +1,3 @@ +Stream contents +Line 2 +Line 3 diff --git a/lld/test/COFF/pdbstream.test b/lld/test/COFF/pdbstream.test new file mode 100644 --- /dev/null +++ b/lld/test/COFF/pdbstream.test @@ -0,0 +1,8 @@ +# RUN: yaml2obj %p/Inputs/empty.yaml > %t.obj + +# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbstream:srcsrv=%p/Inputs/stream.txt +# RUN: llvm-pdbutil export -stream=srcsrv -out=- %t.pdb | FileCheck %s + +CHECK: Stream contents +CHECK-NEXT: Line 2 +CHECK-NEXT: Line 3