Skip to content

Commit

Permalink
lld-link: Implement support for %_PDB% and %_EXT% for /pdbaltpath:.
Browse files Browse the repository at this point in the history
Warn that references to regular env vars are ignored.

Fixes PR38940.

Differential Revision: https://reviews.llvm.org/D52942

llvm-svn: 344003
  • Loading branch information
nico committed Oct 8, 2018
1 parent 0f556f8 commit 9d75241
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
54 changes: 54 additions & 0 deletions lld/COFF/Driver.cpp
Expand Up @@ -830,6 +830,57 @@ static void findKeepUniqueSections() {
}
}

// link.exe replaces each %foo% in AltPath with the contents of environment
// variable foo, and adds the two magic env vars _PDB (expands to the basename
// of pdb's output path) and _EXT (expands to the extension of the output
// binary).
// lld only supports %_PDB% and %_EXT% and warns on references to all other env
// vars.
static void parsePDBAltPath(StringRef AltPath) {
SmallString<128> Buf;
StringRef PDBBasename =
sys::path::filename(Config->PDBPath, sys::path::Style::windows);
StringRef BinaryExtension =
sys::path::extension(Config->OutputFile, sys::path::Style::windows);
if (!BinaryExtension.empty())
BinaryExtension = BinaryExtension.substr(1); // %_EXT% does not include '.'.

// Invariant:
// +--------- Cursor ('a...' might be the empty string).
// | +----- FirstMark
// | | +- SecondMark
// v v v
// a...%...%...
size_t Cursor = 0;
while (Cursor < AltPath.size()) {
size_t FirstMark, SecondMark;
if ((FirstMark = AltPath.find('%', Cursor)) == StringRef::npos ||
(SecondMark = AltPath.find('%', FirstMark + 1)) == StringRef::npos) {
// Didn't find another full fragment, treat rest of string as literal.
Buf.append(AltPath.substr(Cursor));
break;
}

// Found a full fragment. Append text in front of first %, and interpret
// text between first and second % as variable name.
Buf.append(AltPath.substr(Cursor, FirstMark - Cursor));
StringRef Var = AltPath.substr(FirstMark, SecondMark - FirstMark + 1);
if (Var.equals_lower("%_pdb%"))
Buf.append(PDBBasename);
else if (Var.equals_lower("%_ext%"))
Buf.append(BinaryExtension);
else {
warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " +
Var + " as literal");
Buf.append(Var);
}

Cursor = SecondMark + 1;
}

Config->PDBAltPath = Buf;
}

void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// If the first command line argument is "/lib", link.exe acts like lib.exe.
// We call our own implementation of lib.exe that understands bitcode files.
Expand Down Expand Up @@ -1411,6 +1462,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// tools won't work correctly if these assumptions are not held.
sys::fs::make_absolute(Config->PDBAltPath);
sys::path::remove_dots(Config->PDBAltPath);
} else {
// Don't do this earlier, so that Config->OutputFile is ready.
parsePDBAltPath(Config->PDBAltPath);
}
}

Expand Down
67 changes: 67 additions & 0 deletions lld/test/COFF/Inputs/empty.yaml
@@ -0,0 +1,67 @@
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: 31C0C3
- Name: .data
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4
SectionData: ''
- Name: .bss
Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4
SectionData: ''
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 3
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 3963538403
Number: 1
- Name: .data
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 0
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 2
- Name: .bss
Value: 0
SectionNumber: 3
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 0
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 3
- Name: '@feat.00'
Value: 1
SectionNumber: -1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: _main
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...
39 changes: 39 additions & 0 deletions lld/test/COFF/pdbaltpath.test
@@ -0,0 +1,39 @@
# RUN: yaml2obj %p/Inputs/empty.yaml > %t.obj

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:hello.pdb
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix HELLO %s
# HELLO: PDBFileName: hello.pdb

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_Pdb%
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix PDBVAR %s
# PDBVAR: PDBFileName: pdbaltpath.test.tmp.pdb

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_ExT%.pdb
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix EXTVAR %s
# EXTVAR: PDBFileName: fooexe.pdb

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_PDB
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE %s
# NOCLOSE: PDBFileName: %_PDB

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE2 %s
# NOCLOSE2: PDBFileName: foo%_PDB

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSEONE %s
# CLOSEONE: PDBFileName: foopdbaltpath.test.tmp.pdbbar%_EXT

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT%
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO %s
# CLOSETWO: PDBFileName: foopdbaltpath.test.tmp.pdbbarexe

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT%a
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO2 %s
# CLOSETWO2: PDBFileName: foopdbaltpath.test.tmp.pdbbarexea

# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%FoO%bar%r%a 2>&1 | FileCheck --check-prefix UNKNOWN-WARN %s
# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix ENVVARS %s
# UNKNOWN-WARN: only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping %FoO% as literal
# UNKNOWN-WARN: only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping %r% as literal
# ENVVARS: PDBFileName: foo%FoO%bar%r%a

0 comments on commit 9d75241

Please sign in to comment.