[PATCH RFC] bfd: have objcopy retain unknown ELF section flags

Jan Beulich jbeulich@suse.com
Fri Jun 13 13:27:28 GMT 2025


Silently zapping them is certainly wrong. When they're not replaced due
to user request, simply keeping them may not always be correct (we don't
know what such a flag means, after all), but is certainly at least
closer to having the output object still represent what the input object
had.

This introduces new binutils/ testsuite failures, but only for two
targets where most of the tests there fail anyway (amdgcn-elf and
nfp-elf), due to there not being an assembler available.
---
Should we warn about any flags (outside of MASKOS/MASKPROC) being
retained this way? (For context: The original observation was years ago
with old enough binutils losing SHF_COMPRESSED on debug info, obviously
causing issues when later those objects were handed to the linker. The
errors raised by the linker weren't really straightforward to connect
back to the root cause. Hence my main requirement going forward is: Any
loss of information should not go silently.)

The heuristic comparing BFD section flags is fragile (here as much as in
the handling of section type): If with --set-section-flags the user ends
up specifying what was already there, we'd behave as if the option
wasn't specified.

The situation with unknown SHT_* is quite a bit worse. While there is a
FIXME comment in bfd_section_from_shdr(), the diagnostic recorded there
isn't ever emitted on e.g. a default x86_64-linux build, where the
default target isn't the last on in the list of targets. Instead the
user gets to see "Unable to recognise the format of the input file ...",
which is pretty misleading.

--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -8414,9 +8414,19 @@ _bfd_elf_init_private_section_data (bfd
 		  & ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC)) == 0)))
     elf_section_type (osec) = elf_section_type (isec);
 
-  /* FIXME: Is this correct for all OS/PROC specific flags?  */
-  elf_section_flags (osec) = (elf_section_flags (isec)
-			      & (SHF_MASKOS | SHF_MASKPROC));
+  elf_section_flags (osec) = elf_section_flags (isec);
+  /* Like for type, retain flags for objcopy (yet unlike for type, don't do so
+     for relocatable link).  Same heuristic as there: If the BFD section flags
+     are different, assume --set-section-flags is in use for the section.
+
+     FIXME: Is this correct for all OS/PROC specific flags?  */
+  if (link_info != NULL || osec->flags != isec->flags)
+    elf_section_flags (osec) &= (SHF_MASKOS | SHF_MASKPROC);
+  else /* Clear only flags which are set below or elsewhere.  */
+    elf_section_flags (osec) &= ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR
+				  | SHF_MERGE | SHF_STRINGS | SHF_LINK_ORDER
+				  | SHF_INFO_LINK | SHF_GROUP | SHF_TLS
+				  | SHF_COMPRESSED);
 
   /* Copy sh_info from input for mbind section.  */
   if ((elf_tdata (ibfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0
--- /dev/null
+++ b/binutils/testsuite/binutils-all/copy-7.d
@@ -0,0 +1,13 @@
+#PROG: objcopy
+#readelf: -tW
+#name: copy with unknown section flag
+
+There are .* section headers, starting at offset .*
+
+Section Headers:
+  \[Nr\].*
+#...
+  \[ [1-9]\] .special
+       PROGBITS .*
+       \[0+10000\]: UNKNOWN \(0+10000\)
+#...
--- /dev/null
+++ b/binutils/testsuite/binutils-all/copy-7.s
@@ -0,0 +1,7 @@
+	.globl text_symbol
+	.text
+text_symbol:
+	.nop
+
+	.section .special,"0x10000", %progbits
+	.long -1
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1232,6 +1232,7 @@ if [is_elf_format] {
     run_dump_test "group-7b"
     run_dump_test "group-7c"
     run_dump_test "copy-1"
+    run_dump_test "copy-7"
     run_dump_test "note-1"
     # Use copytest.o from the note-1 test to determine ELF32 or ELF64
     if [is_elf64 tmpdir/copytest.o] {


More information about the Binutils mailing list