diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 1c0f874ddfd7..6ac6355d976c 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -216,6 +216,9 @@ struct Configuration { // Used for /merge:from=to (e.g. /merge:.rdata=.text) std::map merge; + // Used for /discard-section:.name + llvm::StringSet<> discardSection; + // Used for /section=.name,{DEKPRSW} to set section attributes. std::map section; // Used for /sectionlayout: to layout sections in specified order. diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index df76f05ed5a0..23aa756cf6ae 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2103,6 +2103,10 @@ void LinkerDriver::linkerMain(ArrayRef 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"); diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 4320a3964461..e797da6effb3 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -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). // diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index fb762b880c2c..bc1902d093a0 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -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">; diff --git a/lld/test/COFF/discard-section.test b/lld/test/COFF/discard-section.test new file mode 100644 index 000000000000..89197d9fbb85 --- /dev/null +++ b/lld/test/COFF/discard-section.test @@ -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 +...