]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
bfd: have objcopy retain unknown ELF section flags
authorJan Beulich <jbeulich@suse.com>
Fri, 15 Aug 2025 10:16:22 +0000 (12:16 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 15 Aug 2025 10:16:22 +0000 (12:16 +0200)
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.

bfd/elf.c
binutils/testsuite/binutils-all/copy-7.d [new file with mode: 0644]
binutils/testsuite/binutils-all/copy-7.s [new file with mode: 0644]
binutils/testsuite/binutils-all/objcopy.exp

index 4f6bcde236545b20fabd5c2a8ae6b5d0c16a7e8d..596c1ec3de20599d83d077a42aa2edf4a7e13a3e 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -8434,9 +8434,28 @@ _bfd_elf_copy_private_section_data (bfd *ibfd,
                  & ~(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);
+      if (elf_section_flags (osec) & ~(SHF_MASKOS | SHF_MASKPROC))
+       _bfd_error_handler
+         (_("%pB:%pA: warning: retaining unknown section flag(s) %#" PRIx64),
+          ibfd, isec,
+          (uint64_t) (elf_section_flags (osec)
+                      & ~(SHF_MASKOS | SHF_MASKPROC)));
+    }
 
   /* Copy sh_info from input for mbind section.  */
   if ((elf_tdata (ibfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0
diff --git a/binutils/testsuite/binutils-all/copy-7.d b/binutils/testsuite/binutils-all/copy-7.d
new file mode 100644 (file)
index 0000000..ac8e756
--- /dev/null
@@ -0,0 +1,14 @@
+#PROG: objcopy
+#readelf: -tW
+#name: copy with unknown section flag
+#warning: .*/copy-7[.].*:[.]special: warning: retaining .* 0x10000
+
+There are .* section headers, starting at offset .*
+
+Section Headers:
+  \[Nr\].*
+#...
+  \[ [1-9]\] .special
+       PROGBITS .*
+       \[0+10000\]: UNKNOWN \(0+10000\)
+#...
diff --git a/binutils/testsuite/binutils-all/copy-7.s b/binutils/testsuite/binutils-all/copy-7.s
new file mode 100644 (file)
index 0000000..0861c3c
--- /dev/null
@@ -0,0 +1,7 @@
+       .globl text_symbol
+       .text
+text_symbol:
+       .nop
+
+       .section .special,"0x10000", %progbits
+       .long -1
index 89370bc893aedf17b24096748d292ae175ff214e..ac8978fef2b04bbf4c0b331f3c3b6dae4cfa4776 100644 (file)
@@ -1313,6 +1313,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] {