[lld] 67244da - [LLD][COFF] Add /nodbgdirmerge to control debug directory section (#159235)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 19 14:20:36 PDT 2025


Author: kkent030315
Date: 2025-09-20T00:20:32+03:00
New Revision: 67244da08e1aa83f34358a32e3fa3b2e1722bc65

URL: https://github.com/llvm/llvm-project/commit/67244da08e1aa83f34358a32e3fa3b2e1722bc65
DIFF: https://github.com/llvm/llvm-project/commit/67244da08e1aa83f34358a32e3fa3b2e1722bc65.diff

LOG: [LLD][COFF] Add /nodbgdirmerge to control debug directory section (#159235)

Resolves #141712.

As described in the issue, this PR adds support for `/nodbgdirmerge`
flag in LLD to align with MS link. When the flag is specified, the
linker will emit the debug directory section in `.cvinfo` section,
instead of merging it to the `.rdata`. The flag will be ignored on
MinGW.

---------

Co-authored-by: namazso <admin at namazso.eu>

Added: 
    lld/test/COFF/nodbgdirmerge.test

Modified: 
    lld/COFF/Config.h
    lld/COFF/Driver.cpp
    lld/COFF/Options.td
    lld/COFF/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index a71476adcc493..76b7c1f61cd25 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -322,6 +322,7 @@ struct Configuration {
   bool largeAddressAware = false;
   bool highEntropyVA = false;
   bool appContainer = false;
+  bool mergeDebugDirectory = true;
   bool mingw = false;
   bool warnMissingOrderSymbol = true;
   bool warnLocallyDefinedImported = true;

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index acba156ce341d..948dd7a96c7a5 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2338,6 +2338,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
       config->is64() &&
       args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);
 
+  // Handle /nodbgdirmerge
+  config->mergeDebugDirectory = !args.hasArg(OPT_nodbgdirmerge);
+
   if (!config->dynamicBase &&
       (config->machine == ARMNT || isAnyArm64(config->machine)))
     Err(ctx) << "/dynamicbase:no is not compatible with "

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index b5334de87b6a7..485db5a8b21c1 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -90,6 +90,8 @@ def machine : P<"machine", "Specify target platform">;
 def merge   : P<"merge", "Combine sections">;
 def mllvm   : P<"mllvm", "Options to pass to LLVM">;
 def nodefaultlib : P<"nodefaultlib", "Remove a default library">;
+def nodbgdirmerge : F<"nodbgdirmerge">,
+                      HelpText<"Emit the debug directory in a separate section">;
 def opt     : P<"opt", "Control optimizations">;
 def order   : P<"order", "Put functions in order">;
 def out     : P<"out", "Path to file to write output">;

diff  --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index e0d0ac18ea5d5..b4f00996319b1 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -324,6 +324,7 @@ class Writer {
   OutputSection *bssSec;
   OutputSection *rdataSec;
   OutputSection *buildidSec;
+  OutputSection *cvinfoSec;
   OutputSection *dataSec;
   OutputSection *pdataSec;
   OutputSection *idataSec;
@@ -1092,6 +1093,7 @@ void Writer::createSections() {
   bssSec = createSection(".bss", bss | r | w);
   rdataSec = createSection(".rdata", data | r);
   buildidSec = createSection(".buildid", data | r);
+  cvinfoSec = createSection(".cvinfo", data | r);
   dataSec = createSection(".data", data | r | w);
   pdataSec = createSection(".pdata", data | r);
   idataSec = createSection(".idata", data | r);
@@ -1228,7 +1230,13 @@ void Writer::createMiscChunks() {
   });
 
   // Create Debug Information Chunks
-  debugInfoSec = config->mingw ? buildidSec : rdataSec;
+  if (config->mingw) {
+    debugInfoSec = buildidSec;
+  } else if (!config->mergeDebugDirectory) {
+    debugInfoSec = cvinfoSec;
+  } else {
+    debugInfoSec = rdataSec;
+  }
   if (config->buildIDHash != BuildIDHash::None || config->debug ||
       config->repro || config->cetCompat || config->cetCompatStrict ||
       config->cetCompatIpValidationRelaxed ||

diff  --git a/lld/test/COFF/nodbgdirmerge.test b/lld/test/COFF/nodbgdirmerge.test
new file mode 100644
index 0000000000000..1ad697402a6a2
--- /dev/null
+++ b/lld/test/COFF/nodbgdirmerge.test
@@ -0,0 +1,33 @@
+RUN: yaml2obj %p/Inputs/pdb1.yaml -o %t1.obj
+RUN: yaml2obj %p/Inputs/pdb2.yaml -o %t2.obj
+RUN: rm -f %t.dll %t.pdb
+
+## Check that it emits the debug directory in .cvinfo section when
+## /nodbgdirmerge is specified
+RUN: lld-link /debug /pdb:%t.pdb /pdbaltpath:test.pdb /dll /out:%t.dll \
+RUN:   /entry:main /nodefaultlib /nodbgdirmerge %t1.obj %t2.obj
+RUN: llvm-readobj --sections %t.dll | FileCheck -check-prefix=CHECKNOTMERGED %s
+
+CHECKNOTMERGED:   Section {
+CHECKNOTMERGED:     Number: 3
+CHECKNOTMERGED-NEXT:     Name: .cvinfo
+CHECKNOTMERGED-NEXT:     VirtualSize: 0x3D
+CHECKNOTMERGED-NEXT:     VirtualAddress: 0x3000
+CHECKNOTMERGED-NEXT:     RawDataSize: 512
+CHECKNOTMERGED-NEXT:     PointerToRawData: 0x800
+CHECKNOTMERGED-NEXT:     PointerToRelocations: 0
+CHECKNOTMERGED-NEXT:     PointerToLineNumbers: 0
+CHECKNOTMERGED-NEXT:     RelocationCount: 0
+CHECKNOTMERGED-NEXT:     LineNumberCount: 0
+CHECKNOTMERGED-NEXT:     Characteristics [ (0x40000040)
+CHECKNOTMERGED-NEXT:       IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+CHECKNOTMERGED-NEXT:       IMAGE_SCN_MEM_READ (0x40000000)
+CHECKNOTMERGED-NEXT:     ]
+CHECKNOTMERGED-NEXT:   }
+
+## Check that it triggers merge on when /nodbgdirmerge is not specified
+RUN: lld-link /debug /pdb:%t.pdb /pdbaltpath:test.pdb /dll /out:%t.dll \
+RUN:   /entry:main /nodefaultlib %t1.obj %t2.obj
+RUN: llvm-readobj --sections %t.dll | FileCheck -check-prefix=CHECKMERGED %s
+
+CHECKMERGED-NOT:     Name: .cvinfo


        


More information about the llvm-commits mailing list