[lld][COFF] Add /discard-section option to discard input sections by name (#189542)

This provides a general mechanism similar to ELF linker scripts'
/DISCARD/ for COFF. Though the intention is to explicitly discard
.llvmbc and .llvmcmd sections. (See discussion in #150897, #188398
for more details.)
This commit is contained in:
Haohai Wen
2026-04-04 20:26:12 +08:00
committed by GitHub
parent 948a64720b
commit 6565e08c1e
5 changed files with 62 additions and 0 deletions

View File

@@ -216,6 +216,9 @@ struct Configuration {
// Used for /merge:from=to (e.g. /merge:.rdata=.text)
std::map<StringRef, StringRef> merge;
// Used for /discard-section:.name
llvm::StringSet<> discardSection;
// Used for /section=.name,{DEKPRSW} to set section attributes.
std::map<StringRef, uint32_t> section;
// Used for /sectionlayout: to layout sections in specified order.

View File

@@ -2103,6 +2103,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
for (auto *arg : args.filtered(OPT_merge))
parseMerge(arg->getValue());
// Handle /discard-section
for (auto *arg : args.filtered(OPT_discard_section))
config->discardSection.insert(arg->getValue());
// Add default section merging rules after user rules. User rules take
// precedence, but we will emit a warning if there is a conflict.
parseMerge(".idata=.rdata");

View File

@@ -404,6 +404,9 @@ SectionChunk *ObjFile::readSection(uint32_t sectionNumber,
return nullptr;
}
if (symtab.ctx.config.discardSection.contains(name))
return nullptr;
// Object files may have DWARF debug info or MS CodeView debug info
// (or both).
//

View File

@@ -45,6 +45,7 @@ def color_diagnostics_eq: Joined<["--"], "color-diagnostics=">,
def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
def delayload : P<"delayload", "Delay loaded DLL name">;
def diasdkdir : P<"diasdkdir", "Set the location of the DIA SDK">;
def discard_section : P<"discard-section", "Discard input sections by name">;
def dwodir : P<"dwodir",
"Directory to store .dwo files when LTO and debug fission are used">;
def entry : P<"entry", "Name of entry point symbol">;

View File

@@ -0,0 +1,51 @@
# RUN: yaml2obj %s -o %t.obj
## By default, all sections are preserved.
# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj
# RUN: llvm-readobj -S %t.exe | FileCheck --check-prefix=PRESERVE %s
# PRESERVE: Name: .rdata
# PRESERVE: Name: .llvmbc
# PRESERVE: Name: .llvmcmd
## /discard-section discards sections by name.
# RUN: lld-link /entry:main /subsystem:console /discard-section:.llvmbc /discard-section:.llvmcmd /out:%t-stripped.exe %t.obj
# RUN: llvm-readobj -S %t-stripped.exe | FileCheck --check-prefix=NOBC %s
# NOBC: Name: .rdata
# NOBC-NOT: Name: .llvmbc
# NOBC-NOT: Name: .llvmcmd
# RUN: lld-link /entry:main /subsystem:console /discard-section:.rdata /out:%t-nordata.exe %t.obj
# RUN: llvm-readobj -S %t-nordata.exe | FileCheck --check-prefix=NORDATA %s
# NORDATA-NOT: Name: .rdata
# NORDATA: Name: .llvmbc
# NORDATA: Name: .llvmcmd
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
SectionData: "C3"
- Name: .rdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
SectionData: "00000000"
- Name: .llvmbc
Characteristics: [ IMAGE_SCN_MEM_DISCARDABLE ]
SectionData: "4243C0DE"
- Name: .llvmcmd
Characteristics: [ IMAGE_SCN_MEM_DISCARDABLE ]
SectionData: "2D63633100"
symbols:
- Name: main
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...