elf: Place code after read-only data for --rosegment
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
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 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/30907
PR ld/32191
PR ld/34003
* scripttempl/elf.sc (ALL_TEXT_BEFORE_RO): Removed.
(ALL_TEXT_AFTER_RO): New. Set for -z separate-code --rosegment.
Place code after read-only data for -z separate-code --rosegment.
* testsuite/ld-elf/pr30907-2.d: Updated.
* testsuite/ld-i386/pr32191.d: Likewise.
* 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>
---
ld/scripttempl/elf.sc | 65 +++++++++++++---------------
ld/testsuite/ld-elf/pr30907-2.d | 4 +-
ld/testsuite/ld-i386/pr32191.d | 4 +-
ld/testsuite/ld-x86-64/pr32191-x32.d | 4 +-
ld/testsuite/ld-x86-64/pr32191.d | 4 +-
5 files changed, 42 insertions(+), 39 deletions(-)
Comments
On Wed, Mar 18, 2026 at 12:24 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> 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 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
Any feedback on this patch?
> PR ld/30907
> PR ld/32191
> PR ld/34003
> * scripttempl/elf.sc (ALL_TEXT_BEFORE_RO): Removed.
> (ALL_TEXT_AFTER_RO): New. Set for -z separate-code --rosegment.
> Place code after read-only data for -z separate-code --rosegment.
> * testsuite/ld-elf/pr30907-2.d: Updated.
> * testsuite/ld-i386/pr32191.d: Likewise.
> * 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>
> ---
> ld/scripttempl/elf.sc | 65 +++++++++++++---------------
> ld/testsuite/ld-elf/pr30907-2.d | 4 +-
> ld/testsuite/ld-i386/pr32191.d | 4 +-
> ld/testsuite/ld-x86-64/pr32191-x32.d | 4 +-
> ld/testsuite/ld-x86-64/pr32191.d | 4 +-
> 5 files changed, 42 insertions(+), 39 deletions(-)
>
> diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
> index 8a0efc02c86..f992dac2ccb 100644
> --- a/ld/scripttempl/elf.sc
> +++ b/ld/scripttempl/elf.sc
> @@ -80,7 +80,7 @@
> # for standard sections, without initial "." or suffixes.
> # SYMBOL_ABI_ALIGNMENT - minimum alignment in bytes which needs to be
> # applied to every symbol definition
> -# ALL_TEXT_BEFORE_RO - put all code sections before read-only
> +# 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
> @@ -360,7 +360,7 @@ 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=" "
> + ALL_TEXT_AFTER_RO=" "
> SEPARATE_TEXT=" "
> TEXT_SEGMENT_ALIGN=". = ALIGN(${MAXPAGESIZE});"
> ;;
> @@ -1021,25 +1021,24 @@ EOF
>
> #------Early Read Only Data -----------------------------------------------
>
> - if 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
> - # a code segment, followed by another data segment (for read/write data).
> - # Having three segments like this makes the binary bigger, which is a
> - # problem for some scenarios, eg containers. On the other hand, having
> - # data in an executable code segment means that it might provide an
> - # avenue of attack for bad actors, which is a security risk.
> -
> - test -n "${SEPARATE_CODE}" || emit_early_ro
> - test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
> -
> - # We only need the alignment if we have emitted some sections.
> - if test -z "${SEPARATE_CODE}"; then
> - align_text
> - elif test -z "${NON_ALLOC_DYN}${SEPARATE_CODE}"; then
> - align_text
> - fi
> + # 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
> + # a code segment, followed by another data segment (for read/write data).
> + # Having three segments like this makes the binary bigger, which is a
> + # problem for some scenarios, eg containers. On the other hand, having
> + # data in an executable code segment means that it might provide an
> + # avenue of attack for bad actors, which is a security risk.
> +
> + test -n "${SEPARATE_CODE}" || emit_early_ro
> + test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
> + test -z "${ALL_TEXT_AFTER_RO}" || emit_rodata
> +
> + # We only need the alignment if we have emitted some sections.
> + if test -z "${SEPARATE_CODE}"; then
> + align_text
> + elif test -z "${NON_ALLOC_DYN}${SEPARATE_CODE}"; then
> + align_text
> fi
>
> #------Executable Code ----------------------------------------------------
> @@ -1058,24 +1057,22 @@ EOF
>
> align_text
>
> - #------Read Only Data -----------------------------------------------------
> + if test -z "${ALL_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
> + 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 ----------------------------------------------------
>
> diff --git a/ld/testsuite/ld-elf/pr30907-2.d b/ld/testsuite/ld-elf/pr30907-2.d
> index fed957e760e..1ac8d4951da 100644
> --- a/ld/testsuite/ld-elf/pr30907-2.d
> +++ b/ld/testsuite/ld-elf/pr30907-2.d
> @@ -6,10 +6,10 @@
> #xfail: ![check_shared_lib_support]
> #xfail: ![check_relro_support]
>
> -#...
> -[ ]+LOAD[ ]+0x[0-9a-f x]+R E[ ]+0x.*
> #...
> [ ]+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.*
> #...
> diff --git a/ld/testsuite/ld-i386/pr32191.d b/ld/testsuite/ld-i386/pr32191.d
> index 8d7838a1311..5558da1b0b8 100644
> --- a/ld/testsuite/ld-i386/pr32191.d
> +++ b/ld/testsuite/ld-i386/pr32191.d
> @@ -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
> diff --git a/ld/testsuite/ld-x86-64/pr32191-x32.d b/ld/testsuite/ld-x86-64/pr32191-x32.d
> index 19e06a26c11..b574e05f6c9 100644
> --- a/ld/testsuite/ld-x86-64/pr32191-x32.d
> +++ b/ld/testsuite/ld-x86-64/pr32191-x32.d
> @@ -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
> diff --git a/ld/testsuite/ld-x86-64/pr32191.d b/ld/testsuite/ld-x86-64/pr32191.d
> index 9038ccd9b35..2a0c0339165 100644
> --- a/ld/testsuite/ld-x86-64/pr32191.d
> +++ b/ld/testsuite/ld-x86-64/pr32191.d
> @@ -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
> --
> 2.53.0
>
@@ -80,7 +80,7 @@
# for standard sections, without initial "." or suffixes.
# SYMBOL_ABI_ALIGNMENT - minimum alignment in bytes which needs to be
# applied to every symbol definition
-# ALL_TEXT_BEFORE_RO - put all code sections before read-only
+# 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
@@ -360,7 +360,7 @@ 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=" "
+ ALL_TEXT_AFTER_RO=" "
SEPARATE_TEXT=" "
TEXT_SEGMENT_ALIGN=". = ALIGN(${MAXPAGESIZE});"
;;
@@ -1021,25 +1021,24 @@ EOF
#------Early Read Only Data -----------------------------------------------
- if 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
- # a code segment, followed by another data segment (for read/write data).
- # Having three segments like this makes the binary bigger, which is a
- # problem for some scenarios, eg containers. On the other hand, having
- # data in an executable code segment means that it might provide an
- # avenue of attack for bad actors, which is a security risk.
-
- test -n "${SEPARATE_CODE}" || emit_early_ro
- test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
-
- # We only need the alignment if we have emitted some sections.
- if test -z "${SEPARATE_CODE}"; then
- align_text
- elif test -z "${NON_ALLOC_DYN}${SEPARATE_CODE}"; then
- align_text
- fi
+ # 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
+ # a code segment, followed by another data segment (for read/write data).
+ # Having three segments like this makes the binary bigger, which is a
+ # problem for some scenarios, eg containers. On the other hand, having
+ # data in an executable code segment means that it might provide an
+ # avenue of attack for bad actors, which is a security risk.
+
+ test -n "${SEPARATE_CODE}" || emit_early_ro
+ test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
+ test -z "${ALL_TEXT_AFTER_RO}" || emit_rodata
+
+ # We only need the alignment if we have emitted some sections.
+ if test -z "${SEPARATE_CODE}"; then
+ align_text
+ elif test -z "${NON_ALLOC_DYN}${SEPARATE_CODE}"; then
+ align_text
fi
#------Executable Code ----------------------------------------------------
@@ -1058,24 +1057,22 @@ EOF
align_text
- #------Read Only Data -----------------------------------------------------
+ if test -z "${ALL_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
+ 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 ----------------------------------------------------
@@ -6,10 +6,10 @@
#xfail: ![check_shared_lib_support]
#xfail: ![check_relro_support]
-#...
-[ ]+LOAD[ ]+0x[0-9a-f x]+R E[ ]+0x.*
#...
[ ]+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.*
#...
@@ -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
@@ -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
@@ -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