diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index d4a2f5767a2e8..4e334e290145a 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2382,6 +2382,9 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { ctx.symtab.addAbsolute(mangle("__CTOR_LIST__"), 0); ctx.symtab.addAbsolute(mangle("__DTOR_LIST__"), 0); } + if (config->debug || config->buildIDHash != BuildIDHash::None) + if (ctx.symtab.findUnderscore("__buildid")) + ctx.symtab.addUndefined(mangle("__buildid")); // This code may add new undefined symbols to the link, which may enqueue more // symbol resolution tasks, so we need to continue executing tasks until we diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 750269fd0bbba..ca69fb2d05270 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -269,8 +269,8 @@ class DefinedAbsolute : public Defined { // __safe_se_handler_table. class DefinedSynthetic : public Defined { public: - explicit DefinedSynthetic(StringRef name, Chunk *c) - : Defined(DefinedSyntheticKind, name), c(c) {} + explicit DefinedSynthetic(StringRef name, Chunk *c, uint32_t offset = 0) + : Defined(DefinedSyntheticKind, name), c(c), offset(offset) {} static bool classof(const Symbol *s) { return s->kind() == DefinedSyntheticKind; @@ -278,11 +278,12 @@ class DefinedSynthetic : public Defined { // A null chunk indicates that this is __ImageBase. Otherwise, this is some // other synthesized chunk, like SEHTableChunk. - uint32_t getRVA() { return c ? c->getRVA() : 0; } + uint32_t getRVA() { return c ? c->getRVA() + offset : 0; } Chunk *getChunk() { return c; } private: Chunk *c; + uint32_t offset; }; // This class represents a symbol defined in an archive file. It is diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 4eeb6ba804bdf..45fcb51e19acd 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1121,6 +1121,9 @@ void Writer::createMiscChunks() { // if we're ultimately not going to write CodeView data to the PDB. buildId = make(ctx); debugRecords.emplace_back(COFF::IMAGE_DEBUG_TYPE_CODEVIEW, buildId); + if (Symbol *buildidSym = ctx.symtab.findUnderscore("__buildid")) + replaceSymbol(buildidSym, buildidSym->getName(), + buildId, 4); } if (config->cetCompat) { diff --git a/lld/docs/windows_support.rst b/lld/docs/windows_support.rst index 620040ee8196a..e4640b4a5259a 100644 --- a/lld/docs/windows_support.rst +++ b/lld/docs/windows_support.rst @@ -95,3 +95,14 @@ Using Ninja 1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror), #. run ``cmake -G ninja `` from VS command prompt, #. run ``ninja lld`` + +Extensions +========== + +LLD flags +--------- + +* ``/build-id``: Always generate GUID hash. When PDB is generated, LLD uses PDB + content hash for GUID. Otherwise, LLD uses output binary content hash for GUID. + LLD also provides ``__buildid`` symbol pointing to the 16 bytes GUID hash if + there is a reference to it. diff --git a/lld/test/COFF/build-id-sym.s b/lld/test/COFF/build-id-sym.s new file mode 100644 index 0000000000000..faed7bc40fd06 --- /dev/null +++ b/lld/test/COFF/build-id-sym.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 +# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s +# RUN: lld-link -debug:symtab -entry:main %t.obj -build-id -Brepro -out:%t.exe +# RUN: llvm-objdump -s -t %t.exe | FileCheck %s + +# Check __buildid points to 0x14000203c which is after the signature RSDS. + +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: 0x0000003c __buildid +# CHECK: Contents of section .rdata: +# CHECK-NEXT: 140002000 +# CHECK-NEXT: 140002010 +# CHECK-NEXT: 140002020 +# CHECK-NEXT: 140002030 {{.*}} {{.*}} 52534453 {{.*}} +# CHECK-NEXT: 140002040 + +.globl main +main: + nop + +.section .bss,"bw",discard,__buildid +.global __buildid +__buildid: