[lld] [LLD][COFF] Add -build-id flag to genrate .buildid section. (PR #71433)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 6 11:35:22 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld

Author: Zequan Wu (ZequanWu)

<details>
<summary>Changes</summary>

[RFC](https://discourse.llvm.org/t/rfc-add-build-id-flag-to-lld-link/74661)

With this change, lld-link generates `.buildid` section that contains build id hash under two cases:
1. `/buildid` flag is given.
2. `/lldmingw` and `/debug` are given and not generating PDB.

So, it will generate duplicated debug directories when `/buildid` and `/pdb:` are given, one in `.buildid` section and another one in `.rdata` section.

---
Full diff: https://github.com/llvm/llvm-project/pull/71433.diff


6 Files Affected:

- (modified) lld/COFF/Config.h (+1) 
- (modified) lld/COFF/Driver.cpp (+5) 
- (modified) lld/COFF/Options.td (+2) 
- (modified) lld/COFF/Writer.cpp (+15-7) 
- (modified) lld/MinGW/Options.td (+1-1) 
- (modified) lld/test/COFF/rsds.test (+34-20) 


``````````diff
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 1c338cc63fa87d2..4e4811357d26a46 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -317,6 +317,7 @@ struct Configuration {
   bool writeCheckSum = false;
   EmitKind emit = EmitKind::Obj;
   bool allowDuplicateWeak = false;
+  bool buildID = false;
 };
 
 } // namespace lld::coff
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 5613c2e6993a5af..0fa6fd6d34cf6a7 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2332,6 +2332,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     }
   }
 
+  // Generate build id hash in .buildid section when:
+  // 1. /build-id
+  // 2. /lldmingw + /debug and not generating pdb file.
+  config->buildID = args.hasArg(OPT_build_id) ||
+                    (config->mingw && config->debug && !shouldCreatePDB);
   // Set default image base if /base is not given.
   if (config->imageBase == uint64_t(-1))
     config->imageBase = getDefaultImageBase();
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 977657a433dc581..cc7ce4fdbeea037 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -299,6 +299,8 @@ def : Flag<["--"], "time-trace">, Alias<time_trace_eq>,
 def time_trace_granularity_eq: Joined<["--"], "time-trace-granularity=">,
     HelpText<"Minimum time granularity (in microseconds) traced by time profiler">;
 
+def build_id: F<"build-id">, HelpText<"Generate build ID">;
+
 // Flags for debugging
 def lldmap : F<"lldmap">;
 def lldmap_file : P_priv<"lldmap">;
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 43d8e7c1d530859..dca148a62e9d171 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1041,14 +1041,14 @@ void Writer::createMiscChunks() {
 
   // Create Debug Information Chunks
   OutputSection *debugInfoSec = config->mingw ? buildidSec : rdataSec;
-  if (config->debug || config->repro || config->cetCompat) {
+  if (config->buildID || config->debug || config->repro || config->cetCompat) {
     debugDirectory =
         make<DebugDirectoryChunk>(ctx, debugRecords, config->repro);
     debugDirectory->setAlignment(4);
     debugInfoSec->addChunk(debugDirectory);
   }
 
-  if (config->debug) {
+  if (config->debug || config->buildID) {
     // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified.  We
     // output a PDB no matter what, and this chunk provides the only means of
     // allowing a debugger to match a PDB and an executable.  So we need it even
@@ -1069,6 +1069,16 @@ void Writer::createMiscChunks() {
     debugInfoSec->addChunk(r.second);
   }
 
+  // If .buildid section was not chosen and /build-id is given, create .buildid
+  // section.
+  if (config->buildID && debugInfoSec != buildidSec) {
+    buildidSec->addChunk(debugDirectory);
+    for (std::pair<COFF::DebugType, Chunk *> r : debugRecords) {
+      r.second->setAlignment(4);
+      buildidSec->addChunk(r.second);
+    }
+  }
+
   // Create SEH table. x86-only.
   if (config->safeSEH)
     createSEHTable();
@@ -2028,7 +2038,7 @@ void Writer::writeBuildId() {
   // PE contents.
   Configuration *config = &ctx.config;
 
-  if (config->debug) {
+  if (config->debug || config->buildID) {
     assert(buildId && "BuildId is not set!");
     // BuildId->BuildId was filled in when the PDB was written.
   }
@@ -2043,16 +2053,14 @@ void Writer::writeBuildId() {
 
   uint32_t timestamp = config->timestamp;
   uint64_t hash = 0;
-  bool generateSyntheticBuildId =
-      config->mingw && config->debug && config->pdbPath.empty();
 
-  if (config->repro || generateSyntheticBuildId)
+  if (config->repro || config->buildID)
     hash = xxh3_64bits(outputFileData);
 
   if (config->repro)
     timestamp = static_cast<uint32_t>(hash);
 
-  if (generateSyntheticBuildId) {
+  if (config->buildID) {
     // For MinGW builds without a PDB file, we still generate a build id
     // to allow associating a crash dump to the executable.
     buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70;
diff --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td
index fa4c4ecc75d6543..87b5c4fff68cef6 100644
--- a/lld/MinGW/Options.td
+++ b/lld/MinGW/Options.td
@@ -196,6 +196,7 @@ defm guard_longjmp : B<"guard-longjmp",
   "Do not enable Control Flow Guard long jump hardening">;
 defm error_limit:
   EqLong<"error-limit", "Maximum number of errors to emit before stopping (0 = no limit)">;
+def build_id: F<"build-id">, HelpText<"Generate build ID">;
 
 // Alias
 def alias_Bdynamic_call_shared: Flag<["-"], "call_shared">, Alias<Bdynamic>;
@@ -213,7 +214,6 @@ def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
 // Ignored options
 def: Joined<["-"], "O">;
 def: F<"as-needed">;
-def: F<"build-id">;
 def: F<"disable-auto-image-base">;
 def: F<"enable-auto-image-base">;
 def: F<"end-group">;
diff --git a/lld/test/COFF/rsds.test b/lld/test/COFF/rsds.test
index 475249ca4056669..783ac08255c031b 100644
--- a/lld/test/COFF/rsds.test
+++ b/lld/test/COFF/rsds.test
@@ -22,9 +22,23 @@
 # RUN: lld-link /Brepro /debug /dll /out:%t.dll /entry:DllMain %t.obj
 # RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix REPRODEBUG %s
 
+# Generate .buildid section when /lldmingw + /debug:dwarf are given and not generating pdb file.
 # RUN: rm -f %t.dll %t.pdb
 # RUN: lld-link /lldmingw /debug:dwarf /dll /out:%t.dll /entry:DllMain %t.obj
-# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix MINGW %s
+# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix BUILDID %s
+
+# RUN: rm -f %t.dll %t.pdb
+# RUN: lld-link /lldmingw /debug:dwarf /build-id /dll /out:%t.dll /entry:DllMain %t.obj
+# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix BUILDID %s
+
+# Generate .buildid section when /build-id is given.
+# RUN: rm -f %t.dll %t.pdb
+# RUN: lld-link /build-id /dll /out:%t.dll /entry:DllMain %t.obj
+# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix BUILDID %s
+
+# RUN: rm -f %t.dll %t.pdb
+# RUN: lld-link /build-id /debug /dll /out:%t.dll /entry:DllMain %t.obj
+# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix BUILDID %s
 
 # CHECK: File: [[FILE:.*]].dll
 # CHECK: DebugDirectory [
@@ -148,25 +162,25 @@
 # REPRODEBUG:   }
 # REPRODEBUG: ]
 
-# MINGW: File: {{.*}}.dll
-# MINGW: DebugDirectory [
-# MINGW:   DebugEntry {
-# MINGW:     Characteristics: 0x0
-# MINGW:     TimeDateStamp:
-# MINGW:     MajorVersion: 0x0
-# MINGW:     MinorVersion: 0x0
-# MINGW:     Type: CodeView (0x2)
-# MINGW:     SizeOfData: 0x{{[^0]}}
-# MINGW:     AddressOfRawData: 0x{{[^0]}}
-# MINGW:     PointerToRawData: 0x{{[^0]}}
-# MINGW:     PDBInfo {
-# MINGW:       PDBSignature: 0x53445352
-# MINGW:       PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]]
-# MINGW:       PDBAge: 1
-# MINGW:       PDBFileName:
-# MINGW:     }
-# MINGW:   }
-# MINGW: ]
+# BUILDID: File: {{.*}}.dll
+# BUILDID: DebugDirectory [
+# BUILDID:   DebugEntry {
+# BUILDID:     Characteristics: 0x0
+# BUILDID:     TimeDateStamp:
+# BUILDID:     MajorVersion: 0x0
+# BUILDID:     MinorVersion: 0x0
+# BUILDID:     Type: CodeView (0x2)
+# BUILDID:     SizeOfData: 0x{{[^0]}}
+# BUILDID:     AddressOfRawData: 0x{{[^0]}}
+# BUILDID:     PointerToRawData: 0x{{[^0]}}
+# BUILDID:     PDBInfo {
+# BUILDID:       PDBSignature: 0x53445352
+# BUILDID:       PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]]
+# BUILDID:       PDBAge: 1
+# BUILDID:       PDBFileName:
+# BUILDID:     }
+# BUILDID:   }
+# BUILDID: ]
 --- !COFF
 header:
   Machine:         IMAGE_FILE_MACHINE_I386

``````````

</details>


https://github.com/llvm/llvm-project/pull/71433


More information about the llvm-commits mailing list