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