Skip to content

Commit 4d9020c

Browse files
authored
[ELF] Implement --force-group-allocation
GNU ld's relocatable linking behaviors: * Sections with the `SHF_GROUP` flag are handled like sections matched by the `--unique=pattern` option. They are processed like orphan sections and ignored by input section descriptions. * Section groups' (usually named `.group`) content is updated as the section indexes are updated. Section groups can be discarded with `/DISCARD/ : { *(.group) }`. `-r --force-group-allocation` discards section groups and allows sections with the `SHF_GROUP` flag to be matched like normal sections. If two section group members are placed into the same output section, their relocation sections (if present) are combined as well. This behavior can be useful when -r output is used as a pseudo shared object (e.g., FreeBSD's amd64 kernel modules, CHERIoT compartments). This patch implements --force-group-allocation: * Input SHT_GROUP sections are discarded. * Input sections do not get the SHF_GROUP flag, so `addInputSec` will combine relocation sections if their relocated section group members are combined. The default behavior is: * Input SHT_GROUP sections are retained. * Input SHF_GROUP sections can be matched (unlike GNU ld) * Input SHF_GROUP sections keep the SHF_GROUP flag, so `addInputSec` will create different OutputDesc copies. GNU ld provides the `FORCE_GROUP_ALLOCATION` command, which is not implemented. Pull Request: #94704
1 parent 37e309f commit 4d9020c

File tree

9 files changed

+28
-5
lines changed

9 files changed

+28
-5
lines changed

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ struct Config {
286286
bool relax;
287287
bool relaxGP;
288288
bool relocatable;
289+
bool resolveGroups;
289290
bool relrGlibc = false;
290291
bool relrPackDynRelocs = false;
291292
llvm::DenseSet<llvm::StringRef> saveTempsArgs;

lld/ELF/Driver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,8 @@ static void readConfigs(opt::InputArgList &args) {
13841384
config->relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false);
13851385
config->rpath = getRpath(args);
13861386
config->relocatable = args.hasArg(OPT_relocatable);
1387+
config->resolveGroups =
1388+
!args.hasArg(OPT_relocatable) || args.hasArg(OPT_force_group_allocation);
13871389

13881390
if (args.hasArg(OPT_save_temps)) {
13891391
// --save-temps implies saving all temps.

lld/ELF/InputFiles.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
676676
symtab.comdatGroups.try_emplace(CachedHashStringRef(signature), this)
677677
.second;
678678
if (keepGroup) {
679-
if (config->relocatable)
679+
if (!config->resolveGroups)
680680
this->sections[i] = createInputSection(
681681
i, sec, check(obj.getSectionName(sec, shstrtab)));
682682
continue;

lld/ELF/InputSection.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
7676
invokeELFT(parseCompressedHeader,);
7777
}
7878

79-
// Drop SHF_GROUP bit unless we are producing a re-linkable object file.
80-
// SHF_GROUP is a marker that a section belongs to some comdat group.
81-
// That flag doesn't make sense in an executable.
79+
// SHF_INFO_LINK and SHF_GROUP are normally resolved and not copied to the
80+
// output section. However, for relocatable linking without
81+
// --force-group-allocation, the SHF_GROUP flag and section groups are retained.
8282
static uint64_t getFlags(uint64_t flags) {
8383
flags &= ~(uint64_t)SHF_INFO_LINK;
84-
if (!config->relocatable)
84+
if (config->resolveGroups)
8585
flags &= ~(uint64_t)SHF_GROUP;
8686
return flags;
8787
}

lld/ELF/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,
254254
def fix_cortex_a8: F<"fix-cortex-a8">,
255255
HelpText<"Apply fixes for ARM Cortex-A8 erratum 657417">;
256256

257+
def force_group_allocation: FF<"force-group-allocation">,
258+
HelpText<"Only meaningful for -r. Section groups are discarded. If two section group members are placed to the same output section, combine their relocations as well">;
259+
257260
defm format: Eq<"format", "Change the input format of the inputs following this option">,
258261
MetaVarName<"[default,elf,binary]">;
259262

lld/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ ELF Improvements
4444
(typical for embedded). It also makes full LTO feasible in such cases, since
4545
IR merging currently prevents the linker script from referring to input
4646
files. (`#90007 <https://github.com/llvm/llvm-project/pull/90007>`_)
47+
* ``--force-group-allocation`` is implemented to discard ``SHT_GROUP`` sections
48+
and combine relocation sections if their relocated section group members are
49+
placed to the same output section.
50+
(`#94704 <https://github.com/llvm/llvm-project/pull/94704>`_)
4751

4852
Breaking changes
4953
----------------

lld/docs/ld.lld.1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ Set the
278278
field to the specified value.
279279
.It Fl -fini Ns = Ns Ar symbol
280280
Specify a finalizer function.
281+
.It Fl -force-group-allocation
282+
Only meaningful for -r. Section groups are discarded. If two section group members are placed to the same output section, combine their relocations as well.
281283
.It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format
282284
Specify the format of the inputs following this option.
283285
.Ar input-format

lld/test/ELF/comdat.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// RUN: ld.lld -shared %t.o %t2.o -o %t
55
// RUN: llvm-objdump -d %t | FileCheck %s
66
// RUN: llvm-readelf -S -s %t | FileCheck --check-prefix=READ %s
7+
// RUN: ld.lld -shared --force-group-allocation %t.o %t2.o -o - | cmp - %t
78

89
// Check that we don't crash with --gc-section and that we print a list of
910
// reclaimed sections on stderr.

lld/test/ELF/relocatable-comdat.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@
4747
# COMBINE-NEXT: .rela.text
4848
# COMBINE-NEXT: .rela.text
4949

50+
## If --force-group-allocation is specified, discard .group and combine .rela.* if their relocated sections are combined.
51+
# RUN: ld.lld -r -T combine.lds a.o a.o --force-group-allocation -o combine-a.ro
52+
# RUN: llvm-readelf -g -S combine-a.ro | FileCheck %s --check-prefix=COMBINE-A
53+
54+
# COMBINE-A: Name Type Address Off Size ES Flg Lk Inf Al
55+
# COMBINE-A: .rodata PROGBITS 0000000000000000 {{.*}} 000002 00 A 0 0 1
56+
# COMBINE-A-NEXT: .text PROGBITS 0000000000000000 {{.*}} 000010 00 AX 0 0 4
57+
# COMBINE-A-NEXT: .rela.text RELA 0000000000000000 {{.*}} 000030 18 I [[#]] [[#]] 8
58+
# COMBINE-A-NEXT: .note.GNU-stack
59+
5060
# RUN: echo 'SECTIONS { /DISCARD/ : {*(.rodata.*)} }' > discard-rodata.lds
5161
# RUN: ld.lld -r -T discard-rodata.lds a.o a.o -o discard-rodata.ro
5262
# RUN: llvm-readelf -g -S discard-rodata.ro | FileCheck %s --check-prefix=NO-RODATA

0 commit comments

Comments
 (0)