]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf/x86: Place code after read-only data for --rosegment
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 18 Mar 2026 19:13:26 +0000 (12:13 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 30 Mar 2026 18:46:35 +0000 (11:46 -0700)
commit e8e10743f7b207b21a1efb0cc9e42487080db013
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Jun 13 15:10:15 2024 +0100

    Add --rosegment option to BFD linker to stop the '-z separate-code' from gen erating two read-only segments.

added --rosegment option to generate one read-only segment with
-z separate-code.  But it puts the read-only data, which contains ELF
headers and .note.gnu.build-id section, in the executable segment:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x00185 0x00185 R E 0x1000
  LOAD           0x001000 0x00001000 0x00001000 0x000d0 0x000d0 R   0x1000
  LOAD           0x001f78 0x00002f78 0x00002f78 0x0008c 0x0008c RW  0x1000
  DYNAMIC        0x001f78 0x00002f78 0x00002f78 0x00070 0x00070 RW  0x4
  NOTE           0x000154 0x00000154 0x00000154 0x00024 0x00024 R   0x4
  NOTE           0x00109c 0x0000109c 0x0000109c 0x00034 0x00034 R   0x4
  GNU_PROPERTY   0x00109c 0x0000109c 0x0000109c 0x00034 0x00034 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x001f78 0x00002f78 0x00002f78 0x00088 0x00088 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .text
   01     .gnu.hash .dynsym .dynstr .rela.dyn .rodata .eh_frame .note.gnu.property
   02     .dynamic .got.plt .data
   03     .dynamic
   04     .note.gnu.build-id
   05     .note.gnu.property
   06     .note.gnu.property
   07
   08     .dynamic .got.plt

which defeats the purpose of -z separate-code.  Update --rosegment to
place code after read-only data:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x00248 0x00248 R   0x1000
  LOAD           0x001000 0x00001000 0x00001000 0x00005 0x00005 R E 0x1000
  LOAD           0x001f78 0x00002f78 0x00002f78 0x0008c 0x0008c RW  0x1000
  DYNAMIC        0x001f78 0x00002f78 0x00002f78 0x00070 0x00070 RW  0x4
  NOTE           0x000154 0x00000154 0x00000154 0x00024 0x00024 R   0x4
  NOTE           0x000214 0x00000214 0x00000214 0x00034 0x00034 R   0x4
  GNU_PROPERTY   0x000214 0x00000214 0x00000214 0x00034 0x00034 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x001f78 0x00002f78 0x00002f78 0x00088 0x00088 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn .rodata .eh_frame .note.gnu.property
   01     .text
   02     .dynamic .got.plt .data
   03     .dynamic
   04     .note.gnu.build-id
   05     .note.gnu.property
   06     .note.gnu.property
   07
   08     .dynamic .got.plt

PR ld/23704
PR ld/30907
PR ld/32191
PR ld/34003
* emulparams/elf32_x86_64.sh (ALL_TEXT_AFTER_RO): New.
* emulparams/elf_i386.sh (ALL_TEXT_AFTER_RO): Likewise.
* emulparams/elf_i386_be.sh (ALL_TEXT_AFTER_RO): Likewise.
* emulparams/elf_i386_vxworks.sh (ALL_TEXT_AFTER_RO): Likewise.
* emulparams/elf_iamcu.sh (ALL_TEXT_AFTER_RO): Likewise.
* emulparams/elf_x86_64.sh (ALL_TEXT_AFTER_RO): Likewise.
* scripttempl/elf.sc (ALL_TEXT_AFTER_RO): New.  If set, place
code after read-only data for -z separate-code --rosegment.
* testsuite/ld-elf/pr30907-2.d: Skip x86 targets.
* testsuite/ld-elf/pr34003.d: New file.
* testsuite/ld-i386/pr32191.d: Updated.
* testsuite/ld-x86-64/pr32191-x32.d: Likewise.
* testsuite/ld-x86-64/pr32191.d: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
12 files changed:
ld/emulparams/elf32_x86_64.sh
ld/emulparams/elf_i386.sh
ld/emulparams/elf_i386_be.sh
ld/emulparams/elf_i386_vxworks.sh
ld/emulparams/elf_iamcu.sh
ld/emulparams/elf_x86_64.sh
ld/scripttempl/elf.sc
ld/testsuite/ld-elf/pr30907-2.d
ld/testsuite/ld-elf/pr34003.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr32191.d
ld/testsuite/ld-x86-64/pr32191-x32.d
ld/testsuite/ld-x86-64/pr32191.d

index 8a07f50e47f5f04fe6b1ada7516c4ed165ed1279..256ae31ed24d3d8adb6c8d75c581271bab07a44b 100644 (file)
@@ -35,6 +35,7 @@ OTHER_PLT_SECTIONS="
 "
 OTHER_GOT_RELOC_SECTIONS="
   .rela.tls    ${RELOCATING-0} : { *(.rela.tls) }"
+ALL_TEXT_AFTER_RO=yes
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
index 12d71f5ef9e67b5a147528e8aefc1f6bd72ea08e..d093afb9fa3ffd28c38c24dae6e694ed58afd0e2 100644 (file)
@@ -30,6 +30,7 @@ OTHER_PLT_SECTIONS="
 "
 OTHER_GOT_RELOC_SECTIONS="
   .rel.tls     ${RELOCATING-0} : { *(.rel.tls) }"
+ALL_TEXT_AFTER_RO=yes
 
 # Linux modify the default library search path to first include
 # a 32-bit specific directory.
index dbe68e99e635fde6a7108596605940251bc385b5..e13d07dec235d9f0ab7bbe806b70dcbd35139904 100644 (file)
@@ -13,3 +13,4 @@ TEMPLATE_NAME=elf
 EXTRA_EM_FILE="elf-x86"
 GENERATE_SHLIB_SCRIPT=yes
 NO_SMALL_DATA=yes
+ALL_TEXT_AFTER_RO=yes
index 40c809263d132bebee0c804c54e6ccf60d3424c3..347842909aa4e0c69e3e03f965e8cb8b03fedaff 100644 (file)
@@ -11,6 +11,7 @@ EXTRA_EM_FILE="elf-x86"
 GENERATE_SHLIB_SCRIPT=yes
 GENERATE_PIE_SCRIPT=yes
 NO_SMALL_DATA=yes
+ALL_TEXT_AFTER_RO=yes
 source_sh ${srcdir}/emulparams/vxworks.sh
 source_sh ${srcdir}/emulparams/extern_protected_data.sh
 source_sh ${srcdir}/emulparams/dynamic_undefined_weak.sh
index c1582235eda0faeb6ccbb7f4037a34e07dbffff2..7377ddee3504e9e16d870ee14ff0246cbbdd9182 100644 (file)
@@ -21,6 +21,7 @@ IREL_IN_PLT=
 OTHER_PLT_SECTIONS="
 .plt.got      ${RELOCATING-0} : { *(.plt.got) }
 "
+ALL_TEXT_AFTER_RO=yes
 
 # Linux modify the default library search path to first include
 # a 32-bit specific directory.
index 747114bc4b443c32bb314623ce23442b9540b416..63e2419184ce246fca928a300dcf375659c6b605 100644 (file)
@@ -37,6 +37,7 @@ OTHER_PLT_SECTIONS="
 "
 OTHER_GOT_RELOC_SECTIONS="
   .rela.tls    ${RELOCATING-0} : { *(.rela.tls) }"
+ALL_TEXT_AFTER_RO=yes
 
 if [ "x${host}" = "x${target}" ]; then
   case " $EMULATION_LIBPATH " in
index 8a0efc02c86440ca7ec634fd44506ada1d2b9d57..2ded3fa3ddda3d16210d31374555271ed54175f2 100644 (file)
@@ -82,6 +82,8 @@
 #               applied to every symbol definition
 #       ALL_TEXT_BEFORE_RO - put all code sections before read-only
 #               sections
+#       ALL_TEXT_AFTER_RO - put all code sections after read-only
+#               sections
 #
 # When adding sections, do note that the names of some sections are used
 # when specifying the start address of the next.
@@ -360,7 +362,11 @@ SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-
 if test -z "$TINY_READONLY_SECTION"; then
   case "$LD_FLAG" in
     *ro*textonly*)
-      ALL_TEXT_BEFORE_RO=" "
+      if test -n "${ALL_TEXT_AFTER_RO}"; then
+        TEXT_AFTER_RO=" "
+      else
+        ALL_TEXT_BEFORE_RO=" "
+      fi
       SEPARATE_TEXT=" "
       TEXT_SEGMENT_ALIGN=". = ALIGN(${MAXPAGESIZE});"
       ;;
@@ -1021,7 +1027,7 @@ EOF
 
   #------Early Read Only Data -----------------------------------------------
 
-  if test -z "${ALL_TEXT_BEFORE_RO}"; then
+  if test -n "${TEXT_AFTER_RO}" || test -z "${ALL_TEXT_BEFORE_RO}"; then
     # We are allowed to put R/O sections before code sections.
     # Doing so either puts read only data into the code segment, if the data
     # and code sections are contiguous, or creates a data segment followed by
@@ -1033,6 +1039,7 @@ EOF
 
     test -n "${SEPARATE_CODE}" || emit_early_ro
     test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
+    test -z "${TEXT_AFTER_RO}" || emit_rodata
 
     # We only need the alignment if we have emitted some sections.
     if test -z "${SEPARATE_CODE}"; then
@@ -1058,24 +1065,26 @@ EOF
 
   align_text
 
-  #------Read Only Data -----------------------------------------------------
+  if test -z "${TEXT_AFTER_RO}"; then
+    #------Read Only Data ------------------------------------------------
 
-  align_rodata
+    align_rodata
 
-  # If we have not already emitted the early read only data sections then do
-  # so now.  Also if the dynamic section has not already been emitted and we
-  # can put it into the data segment, then do that here as well.
+    # If we have not already emitted the early read only data sections then do
+    # so now.  Also if the dynamic section has not already been emitted and we
+    # can put it into the data segment, then do that here as well.
 
-  if test -n "${ALL_TEXT_BEFORE_RO}"; then
-    test -n "${SEPARATE_CODE}" || emit_early_ro
-    test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
-  fi
-  test -z "${SEPARATE_CODE}" || emit_early_ro
-  test -z "${SEPARATE_CODE}" || emit_dyn
+    if test -n "${ALL_TEXT_BEFORE_RO}"; then
+      test -n "${SEPARATE_CODE}" || emit_early_ro
+      test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
+    fi
+    test -z "${SEPARATE_CODE}" || emit_early_ro
+    test -z "${SEPARATE_CODE}" || emit_dyn
 
-  # Now emit the rest of the read only data.
+    # Now emit the rest of the read only data.
 
-  emit_rodata
+    emit_rodata
+  fi
 
   #------Read Write Data ----------------------------------------------------
 
index fed957e760e340ffcc21a0985873cb63c83d2cb8..f6254d3ab251e79fbb238bb7195bb09dbc22b5d8 100644 (file)
@@ -2,6 +2,7 @@
 #source: pr22393-1.s
 #ld: -shared -z separate-code -z relro --rosegment
 #readelf: -l --wide
+#notarget: i?86-*-* x86_64-*-*
 #target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
 #xfail: ![check_shared_lib_support] 
 #xfail: ![check_relro_support]
diff --git a/ld/testsuite/ld-elf/pr34003.d b/ld/testsuite/ld-elf/pr34003.d
new file mode 100644 (file)
index 0000000..9e04914
--- /dev/null
@@ -0,0 +1,13 @@
+#name: --rosegment (has at least one R, one RX and one RW segments)
+#source: pr22393-1.s
+#ld: -shared -z separate-code -z relro --rosegment
+#readelf: -l --wide
+#target: i?86-*-* x86_64-*-*
+
+#...
+[ ]+LOAD[      ]+0x[0-9a-f x]+R[ ]+0x.*
+#...
+[ ]+LOAD[      ]+0x[0-9a-f x]+R E[ ]+0x.*
+#...
+[ ]+LOAD[      ]+0x[0-9a-f x]+RW[ ]+0x.*
+#...
index 8d7838a13113cff20a42ecda0129b52b3acaf890..5558da1b0b8159a66a6d7b7f2a032a19437114a3 100644 (file)
@@ -4,6 +4,8 @@
 #readelf: -lW
 
 #...
- +[0-9]+ +\.note\.gnu\.build-id \.text 
+ +[0-9]+ +\.note\.gnu\.build-id .*
+ +[0-9]+ +\.text 
+#...
  +[0-9]+ +\..* \.note\.gnu\.property .*
 #pass
index 19e06a26c112d93d160f87660219e67b0a14bf46..b574e05f6c95c59b12189bfeec97bc92b3a8b631 100644 (file)
@@ -4,6 +4,8 @@
 #readelf: -lW
 
 #...
- +[0-9]+ +\.note\.gnu\.build-id \.text 
+ +[0-9]+ +\.note\.gnu\.build-id .*
+ +[0-9]+ +\.text 
+#...
  +[0-9]+ +\..* \.note\.gnu\.property .*
 #pass
index 9038ccd9b359e71212e093bd33c28d21107eb1ff..2a0c03391653be4cfb619df5cac0b80f1572c11a 100644 (file)
@@ -4,6 +4,8 @@
 #readelf: -lW
 
 #...
- +[0-9]+ +\.note\.gnu\.build-id \.text 
+ +[0-9]+ +\.note\.gnu\.build-id .*
+ +[0-9]+ +\.text 
+#...
  +[0-9]+ +\..* \.note\.gnu\.property .*
 #pass