diff options
author | Nick Clifton <nickc@redhat.com> | 2024-06-13 15:10:15 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2024-06-13 15:10:15 +0100 |
commit | e8e10743f7b207b21a1efb0cc9e42487080db013 (patch) | |
tree | daeed5b3fb3bdadce5bc0b6297cca0c96aee37a7 /ld/scripttempl | |
parent | 888ff82e77d9ab8f04893a68cd6b4f518d6b50d9 (diff) | |
download | gdb-e8e10743f7b207b21a1efb0cc9e42487080db013.zip gdb-e8e10743f7b207b21a1efb0cc9e42487080db013.tar.gz gdb-e8e10743f7b207b21a1efb0cc9e42487080db013.tar.bz2 |
Add --rosegment option to BFD linker to stop the '-z separate-code' from generating two read-only segments.
PR 30907
Diffstat (limited to 'ld/scripttempl')
-rw-r--r-- | ld/scripttempl/elf.sc | 118 |
1 files changed, 100 insertions, 18 deletions
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index d5022fa..f1a61e7 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -80,6 +80,8 @@ # 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 +# sections # # When adding sections, do note that the names of some sections are used # when specifying the start address of the next. @@ -367,6 +369,11 @@ SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:- # between .plt and .text. if test -z "$TINY_READONLY_SECTION"; then case "$LD_FLAG" in + *ro*textonly*) + ALL_TEXT_BEFORE_RO=" " + SEPARATE_TEXT=" " + TEXT_SEGMENT_ALIGN= + ;; *textonly*) SEPARATE_TEXT=" " TEXT_SEGMENT_ALIGN=". = ALIGN(${MAXPAGESIZE});" @@ -387,6 +394,11 @@ else test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}" fi +# =========================================================================== +# Functions for generating parts of the linker script + +emit_header() +{ cat <<EOF /* Copyright (C) 2014-2024 Free Software Foundation, Inc. @@ -406,14 +418,8 @@ ${RELOCATING- /* For some reason, the Solaris linker makes bad executables if gld -r is used and the intermediate file has sections starting at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld bug. But for now assigning the zero vmas works. */} - -SECTIONS -{ - ${RELOCATING+${SEPARATE_TEXT-/* Read-only sections, merged into text segment: */}} - ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}} - ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}} - ${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}} EOF +} emit_early_ro() { @@ -423,10 +429,21 @@ emit_early_ro() EOF } -test -n "${SEPARATE_CODE}" || emit_early_ro +emit_executable_start() +{ +cat <<EOF + ${RELOCATING+${SEPARATE_TEXT-/* Read-only sections, merged into text segment: */}} + ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}} + ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}} + ${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}} +EOF +} +emit_dyn() +{ test -n "${RELOCATING+0}" || unset NON_ALLOC_DYN test -z "${NON_ALLOC_DYN}" || TEXT_DYNAMIC= + cat > ldscripts/dyntmp.$$ <<EOF ${TEXT_DYNAMIC+${DYNAMIC}} .hash ${RELOCATING-0} : { *(.hash) } @@ -443,6 +460,7 @@ if [ "x$COMBRELOC" = x ]; then else COMBRELOCCAT="cat > $COMBRELOC" fi + eval $COMBRELOCCAT <<EOF ${INITIAL_RELOC_SECTIONS} .rel.init ${RELOCATING-0} : { *(.rel.init) } @@ -518,8 +536,6 @@ cat >> ldscripts/dyntmp.$$ <<EOF ${OTHER_PLT_RELOC_SECTIONS} EOF -emit_dyn() -{ if test -z "${NO_REL_RELOCS}${NO_RELA_RELOCS}"; then cat ldscripts/dyntmp.$$ else @@ -530,17 +546,24 @@ emit_dyn() sed -e '/^[ ]*\.rel\.[^}]*$/,/}/d;/^[ ]*\.rel\./d;/__rel_iplt_/d' ldscripts/dyntmp.$$ fi fi + rm -f ldscripts/dyntmp.$$ + if test -n "${HAVE_DT_RELR}"; then echo " .relr.dyn : { *(.relr.dyn) }" fi } -test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn - +align_text() +{ cat <<EOF ${RELOCATING+${TEXT_SEGMENT_ALIGN}} +EOF +} +emit_text() +{ +cat <<EOF .init ${RELOCATING-0}${RELOCATING+${INIT_ADDR}} : { ${RELOCATING+${INIT_START}} @@ -549,7 +572,9 @@ cat <<EOF } ${FILL} ${TEXT_PLT+${PLT_NEXT_DATA-${PLT} ${OTHER_PLT_SECTIONS}}} + ${TINY_READONLY_SECTION} + .text ${RELOCATING-0} : { ${RELOCATING+${TEXT_START_SYMBOLS}} @@ -563,19 +588,25 @@ cat <<EOF *(.gnu.warning) ${RELOCATING+${OTHER_TEXT_SECTIONS}} } ${FILL} + .fini ${RELOCATING-0}${RELOCATING+${FINI_ADDR}} : { ${RELOCATING+${FINI_START}} KEEP (*(SORT_NONE(.fini))) ${RELOCATING+${FINI_END}} } ${FILL} + ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (__${ETEXT_NAME} = .);}} ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (_${ETEXT_NAME} = .);}} ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT-PROVIDE (${ETEXT_NAME} = .);}} ${RELOCATING+${TEXT_SEGMENT_ALIGN}} EOF +} +align_rodata() +{ if test -n "${SEPARATE_CODE}${SEPARATE_TEXT}"; then + if test -n "${RODATA_ADDR}"; then RODATA_ADDR="\ SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS" @@ -583,6 +614,7 @@ SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS" RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))" RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR})" fi + if test -n "${SHLIB_RODATA_ADDR}"; then SHLIB_RODATA_ADDR="\ SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS" @@ -590,6 +622,7 @@ SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS" SHLIB_RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))" SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR})" fi + cat <<EOF ${RELOCATING+/* Adjust the address for the rodata segment. We want to adjust up to the same address within the page on the next page up. */ @@ -597,12 +630,11 @@ SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS" ${CREATE_SHLIB+. = ${SHLIB_RODATA_ADDR};} ${CREATE_PIE+. = ${SHLIB_RODATA_ADDR};}} EOF - if test -n "${SEPARATE_CODE}"; then - emit_early_ro - emit_dyn - fi fi +} +emit_rodata() +{ cat <<EOF ${WRITABLE_RODATA-${RODATA}} .${RODATA_NAME}1 ${RELOCATING-0} : { *(.${RODATA_NAME}1) } @@ -621,7 +653,12 @@ cat <<EOF ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (__${ETEXT_NAME} = .);}} ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (_${ETEXT_NAME} = .);}} ${RELOCATING+${ETEXT_LAST_IN_RODATA_SEGMENT+PROVIDE (${ETEXT_NAME} = .);}} +EOF +} +emit_data() +{ +cat <<EOF ${RELOCATING+/* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */} ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}} @@ -712,7 +749,10 @@ cat <<EOF ${NOINIT} ${RELOCATING+. = ALIGN(${ALIGNMENT});} EOF +} +emit_large_data() +{ LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${LARGE_DATA_ADDR-.});" SHLIB_LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${SHLIB_LARGE_DATA_ADDR-.});" @@ -730,9 +770,10 @@ cat <<EOF ${TINY_BSS_SECTION} ${STACK_ADDR+${STACK}} EOF +} -test -z "${NON_ALLOC_DYN}" || emit_dyn - +emit_misc() +{ source_sh $srcdir/scripttempl/misc-sections.sc source_sh $srcdir/scripttempl/DWARF.sc @@ -741,5 +782,46 @@ cat <<EOF ${OTHER_SECTIONS} ${RELOCATING+${OTHER_SYMBOLS}} ${RELOCATING+${DISCARDED}} +EOF +} + +# =========================================================================== +# The script: + +emit_header + +cat <<EOF +SECTIONS +{ +EOF + + emit_executable_start + + if test -z "${ALL_TEXT_BEFORE_RO}"; then + test -n "${SEPARATE_CODE}" || emit_early_ro + test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn + fi + + align_text + emit_text + + align_rodata + + 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 + emit_rodata + + emit_data + emit_large_data + + test -z "${NON_ALLOC_DYN}" || emit_dyn + emit_misc + +cat <<EOF } EOF |