diff options
author | Jan Beulich <jbeulich@suse.com> | 2025-08-26 10:42:03 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2025-08-26 10:42:03 +0200 |
commit | 74f045d47ab9060bc4e8b82e62bdf2d0ef730cb5 (patch) | |
tree | 423637cc79b9ca83357b9006399c5a16b4b7768f | |
parent | 5319c8dec64aa5e37c56da2b0cfe77a1886231ca (diff) | |
download | binutils-74f045d47ab9060bc4e8b82e62bdf2d0ef730cb5.zip binutils-74f045d47ab9060bc4e8b82e62bdf2d0ef730cb5.tar.gz binutils-74f045d47ab9060bc4e8b82e62bdf2d0ef730cb5.tar.bz2 |
ld: entry size and merge/strings attributes propagation
While commit 9c0adb10c7fc ("elf: Clear entsize when clearing
SEC_MERGE|SEC_STRINGS") addressed the particular issue reported in
PR ld/33291, it didn't go quite far enough to deal with related aspects
as well:
As indicated in other recent commits, the three properties can be
largely independent (ELF generally being the target here): Entry size
doesn't require either of merge/strings, and strings also doesn't
require merge. Commit 98e6d3f5bd4e ("gas/ELF: allow specifying entity
size for arbitrary sections") uncovered issues with ld's handling.
Zap entry size when it doesn't match between input sections. In that
case SEC_MERGE and SEC_STRINGS also need to be removed, as their
underlying granularity is lost. Then deal with SEC_MERGE and
SEC_STRINGS separately.
Otoh record entry size from the first input independent of SEC_MERGE.
-rw-r--r-- | ld/ldlang.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 0bb4a17..54292a8 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2854,15 +2854,24 @@ lang_add_section (lang_statement_list_type *ptr, /* Only set SEC_READONLY flag on the first input section. */ flags &= ~ SEC_READONLY; - /* Keep SEC_MERGE and SEC_STRINGS only if they are the same. */ - if ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS)) - != (flags & (SEC_MERGE | SEC_STRINGS)) - || ((flags & SEC_MERGE) != 0 - && output->bfd_section->entsize != section->entsize)) + /* Keep entry size, SEC_MERGE, and SEC_STRINGS only if entry sizes are + the same. */ + if (output->bfd_section->entsize != section->entsize) { - output->bfd_section->flags &= ~ (SEC_MERGE | SEC_STRINGS); output->bfd_section->entsize = 0; - flags &= ~ (SEC_MERGE | SEC_STRINGS); + flags &= ~(SEC_MERGE | SEC_STRINGS); + } + + /* Keep SEC_MERGE and SEC_STRINGS (each) only if they are the same. */ + if ((output->bfd_section->flags ^ flags) & SEC_MERGE) + { + output->bfd_section->flags &= ~SEC_MERGE; + flags &= ~SEC_MERGE; + } + if ((output->bfd_section->flags ^ flags) & SEC_STRINGS) + { + output->bfd_section->flags &= ~SEC_STRINGS; + flags &= ~SEC_STRINGS; } } output->bfd_section->flags |= flags; @@ -2877,8 +2886,7 @@ lang_add_section (lang_statement_list_type *ptr, link_info.output_bfd, output->bfd_section, &link_info); - if ((flags & SEC_MERGE) != 0) - output->bfd_section->entsize = section->entsize; + output->bfd_section->entsize = section->entsize; } if ((flags & SEC_TIC54X_BLOCK) != 0 |