[ms] Add new /PDBSTREAM option to lld-link allowing injection of streams into PDB files.

Summary:
/PDBSTREAM:<name>=<file> adds the contents of <file> to stream <name> in the resulting PDB.

This allows native uses with workflows that (for example) add srcsrv streams to PDB files to provide a location for the build's source files.

Results should be equivalent to linking with lld-link, then running Microsoft's pdbstr tool with the command line:
pdbstr.exe -w -p:<PDB LOCATION> -s:<name> -i:<file>
except in cases where the named stream overlaps with a default named stream, such as "/names". In those cases, the added stream will be overridden, making the /pdbstream option a no-op.

Reviewers: thakis, rnk

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D77310
This commit is contained in:
Eric Astor 2020-04-07 16:16:22 -04:00
parent 3fefda6e57
commit a39b14f0b4
6 changed files with 40 additions and 0 deletions

View File

@ -110,6 +110,7 @@ struct Configuration {
bool showSummary = false; bool showSummary = false;
unsigned debugTypes = static_cast<unsigned>(DebugType::None); unsigned debugTypes = static_cast<unsigned>(DebugType::None);
std::vector<std::string> natvisFiles; std::vector<std::string> natvisFiles;
llvm::StringMap<std::string> namedStreams;
llvm::SmallString<128> pdbAltPath; llvm::SmallString<128> pdbAltPath;
llvm::SmallString<128> pdbPath; llvm::SmallString<128> pdbPath;
llvm::SmallString<128> pdbSourcePath; llvm::SmallString<128> pdbSourcePath;

View File

@ -1273,6 +1273,14 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
config->pdbAltPath = arg->getValue(); config->pdbAltPath = arg->getValue();
if (args.hasArg(OPT_natvis)) if (args.hasArg(OPT_natvis))
config->natvisFiles = args.getAllArgValues(OPT_natvis); config->natvisFiles = args.getAllArgValues(OPT_natvis);
if (args.hasArg(OPT_pdbstream)) {
for (const StringRef value : args.getAllArgValues(OPT_pdbstream)) {
const std::pair<StringRef, StringRef> 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)) if (auto *arg = args.getLastArg(OPT_pdb_source_path))
config->pdbSourcePath = arg->getValue(); config->pdbSourcePath = arg->getValue();

View File

@ -66,6 +66,9 @@ def no_color_diagnostics: F<"no-color-diagnostics">,
def pdb : P<"pdb", "PDB file path">; def pdb : P<"pdb", "PDB file path">;
def pdbstripped : P<"pdbstripped", "Stripped PDB file path">; def pdbstripped : P<"pdbstripped", "Stripped PDB file path">;
def pdbaltpath : P<"pdbaltpath", "PDB file path to embed in the image">; def pdbaltpath : P<"pdbaltpath", "PDB file path to embed in the image">;
def pdbstream : Joined<["/", "-", "/?", "-?"], "pdbstream:">,
MetaVarName<"<name>=<file>">,
HelpText<"Embed the contents of <file> in the PDB as named stream <name>">;
def section : P<"section", "Specify section attributes">; def section : P<"section", "Specify section attributes">;
def stack : P<"stack", "Size of the stack">; def stack : P<"stack", "Size of the stack">;
def stub : P<"stub", "Specify DOS stub file">; def stub : P<"stub", "Specify DOS stub file">;

View File

@ -100,6 +100,9 @@ public:
/// Add natvis files specified on the command line. /// Add natvis files specified on the command line.
void addNatvisFiles(); 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. /// Link CodeView from each object file in the symbol table into the PDB.
void addObjectsToPDB(); void addObjectsToPDB();
@ -1437,6 +1440,19 @@ void PDBLinker::addNatvisFiles() {
} }
} }
void PDBLinker::addNamedStreams() {
for (const auto &streamFile : config->namedStreams) {
const StringRef stream = streamFile.getKey(), file = streamFile.getValue();
ErrorOr<std::unique_ptr<MemoryBuffer>> 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) { static codeview::CPUType toCodeViewMachine(COFF::MachineTypes machine) {
switch (machine) { switch (machine) {
case COFF::IMAGE_FILE_MACHINE_AMD64: case COFF::IMAGE_FILE_MACHINE_AMD64:
@ -1692,6 +1708,7 @@ void lld::coff::createPDB(SymbolTable *symtab,
pdb.addImportFilesToPDB(outputSections); pdb.addImportFilesToPDB(outputSections);
pdb.addSections(outputSections, sectionTable); pdb.addSections(outputSections, sectionTable);
pdb.addNatvisFiles(); pdb.addNatvisFiles();
pdb.addNamedStreams();
ScopedTimer t2(diskCommitTimer); ScopedTimer t2(diskCommitTimer);
codeview::GUID guid; codeview::GUID guid;

View File

@ -0,0 +1,3 @@
Stream contents
Line 2
Line 3

View File

@ -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