[binutils-gdb] elf/x86: Place code after read-only data for --rosegment
"H.J. Lu via Binutils-cvs" <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=99600a4787910d4b1994b243473a7386dbee641d commit 99600a4787910d4b1994b243473a7386dbee641d Author: H.J. Lu <[email protected]> Date: Wed Mar 18 12:13:26 2026 -0700 elf/x86: Place code after read-only data for --rosegment commit e8e10743f7b207b21a1efb0cc9e42487080db013 Author: Nick Clifton <[email protected]> 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 <[email protected]> Diff: --- ld/emulparams/elf32_x86_64.sh | 1 + ld/emulparams/elf_i386.sh | 1 + ld/emulparams/elf_i386_be.sh | 1 + ld/emulparams/elf_i386_vxworks.sh | 1 + ld/emulparams/elf_iamcu.sh | 1 + ld/emulparams/elf_x86_64.sh | 1 + ld/scripttempl/elf.sc | 39 ++++++++++++++++++++++-------------- ld/testsuite/ld-elf/pr30907-2.d | 1 + ld/testsuite/ld-elf/pr34003.d | 13 ++++++++++++ ld/testsuite/ld-i386/pr32191.d | 4 +++- ld/testsuite/ld-x86-64/pr32191-x32.d | 4 +++- ld/testsuite/ld-x86-64/pr32191.d | 4 +++- 12 files changed, 53 insertions(+), 18 deletions(-) diff --git a/ld/emulparams/elf32_x86_64.sh b/ld/emulparams/elf32_x86_64.sh index 8a07f50e47f..256ae31ed24 100644 --- a/ld/emulparams/elf32_x86_64.sh +++ b/ld/emulparams/elf32_x86_64.sh @@ -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 diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh index 12d71f5ef9e..d093afb9fa3 100644 --- a/ld/emulparams/elf_i386.sh +++ b/ld/emulparams/elf_i386.sh @@ -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. diff --git a/ld/emulparams/elf_i386_be.sh b/ld/emulparams/elf_i386_be.sh index dbe68e99e63..e13d07dec23 100644 --- a/ld/emulparams/elf_i386_be.sh +++ b/ld/emulparams/elf_i386_be.sh @@ -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 diff --git a/ld/emulparams/elf_i386_vxworks.sh b/ld/emulparams/elf_i386_vxworks.sh index 40c809263d1..347842909aa 100644 --- a/ld/emulparams/elf_i386_vxworks.sh +++ b/ld/emulparams/elf_i386_vxworks.sh @@ -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 diff --git a/ld/emulparams/elf_iamcu.sh b/ld/emulparams/elf_iamcu.sh index c1582235eda..7377ddee350 100644 --- a/ld/emulparams/elf_iamcu.sh +++ b/ld/emulparams/elf_iamcu.sh @@ -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. diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index 747114bc4b4..63e2419184c 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -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 diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index 8a0efc02c86..2ded3fa3ddd 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -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 ---------------------------------------------------- diff --git a/ld/testsuite/ld-elf/pr30907-2.d b/ld/testsuite/ld-elf/pr30907-2.d index fed957e760e..f6254d3ab25 100644 --- a/ld/testsuite/ld-elf/pr30907-2.d +++ b/ld/testsuite/ld-elf/pr30907-2.d @@ -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 index 00000000000..9e04914e647 --- /dev/null +++ b/ld/testsuite/ld-elf/pr34003.d @@ -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.* +#... 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