diff options
author | Nick Clifton <nickc@redhat.com> | 2024-11-27 11:23:38 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2024-11-27 11:23:38 +0000 |
commit | fe217087a4b8aa214a221ca9f033c5fcdbcee90e (patch) | |
tree | 48d30bcfcc0cbab5ad029e35c6b96a74ab844f65 | |
parent | 7a55d8e4df2ead7f71706459adc708da2691fd5b (diff) | |
download | binutils-fe217087a4b8aa214a221ca9f033c5fcdbcee90e.zip binutils-fe217087a4b8aa214a221ca9f033c5fcdbcee90e.tar.gz binutils-fe217087a4b8aa214a221ca9f033c5fcdbcee90e.tar.bz2 |
Tidy up the default ELF linker script
-rw-r--r-- | ld/scripttempl/elf.sc | 474 |
1 files changed, 352 insertions, 122 deletions
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index 84b4332..82d6ddb 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -115,6 +115,48 @@ # # Each of these can also have corresponding .rel.* and .rela.* sections. +# ------------------------------------------------------------------------ +# The multiple forms of conditional shell script syntax that are used in +# this file can be confusing, so here is a quick explanation of how they +# work: +# +# The following all mean "if foo is defined then do/insert <stuff>": +# +# test -z "$foo" || <stuff> +# test -n "$foo" && <stuff> +# if test -n "$foo"; then <stuff> +# if [ -n "$foo" ]; then <stuff> +# ${foo-<stuff>} +# +# Whereas the following all mean "if foo is undefined then do/insert <stuff>": +# +# test -n "$foo" || <stuff> +# test -z "$foo" && <stuff> +# if test -z "$foo"; then <stuff> +# if [ -z "$foo" ]; then <stuff> +# ${foo+<stuff>} +# +# If multiple symbols are tested together then they operate as an IOR for +# positive tests and a NOR for negative tests. ie, the following all do +# <stuff> if either or both of <foo> and <bar> are defined: +# +# test -z "$foo$bar" || <stuff> +# test -n "$foo$bar" && <stuff> +# if test -n "$foo$bar"; then <stuff> +# +# Whilst the following only do <stuff> if neither <foo> nor <bar> are defined: +# +# test -n "$foo$bar" || <stuff> +# if -z "$foo$bar"; then <stuff> +# test -z "$foo$bar" && <stuff> +# +# Also: +# foo=${foo-${bar-${baz}}} +# means: +# If foo is defined, leave it unchanged. Otherwise if bar is defined +# then set foo equal to bar, otherwise set foo equal to baz. +# ------------------------------------------------------------------------ + if test -n "$NOP"; then FILL="=$NOP" else @@ -136,6 +178,7 @@ test "$LD_FLAG" = "N" && DATA_ADDR=. test -z "${ETEXT_NAME}" && ETEXT_NAME=${USER_LABEL_PREFIX}etext test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }" + if test -z "$DATA_SEGMENT_ALIGN"; then test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE="" test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE="" @@ -144,7 +187,8 @@ if test -z "$DATA_SEGMENT_ALIGN"; then DATA_SEGMENT_END="" if test -n "${COMMONPAGESIZE}"; then if test "${SEGMENT_SIZE}" != "${MAXPAGESIZE}"; then - DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})" + DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); \ + . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})" else DATA_SEGMENT_ALIGN="DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})" fi @@ -152,15 +196,19 @@ if test -z "$DATA_SEGMENT_ALIGN"; then DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT-0}, .);" fi fi + if test -z "${INITIAL_READONLY_SECTIONS}${CREATE_SHLIB}"; then INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }" fi + if test -z "$PLT"; then IPLT=".iplt ${RELOCATING-0} : { *(.iplt) }" PLT=".plt ${RELOCATING-0} : { *(.plt)${RELOCATING+${IREL_IN_PLT+ *(.iplt)}} } ${IREL_IN_PLT-$IPLT}" fi + test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT= + if test -z "$GOT"; then if test -z "$SEPARATE_GOTPLT"; then GOT=".got ${RELOCATING-0} : {${RELOCATING+ *(.got.plt) *(.igot.plt)} *(.got)${RELOCATING+ *(.igot)} }" @@ -233,17 +281,21 @@ if test -z "${NO_SMALL_DATA}"; then else NO_SMALL_DATA=" " fi + if test -z "${SDATA_GOT}${DATA_GOT}"; then if test -n "${NO_SMALL_DATA}"; then DATA_GOT=" " fi fi + if test -z "${SDATA_GOT}${DATA_GOT}"; then if test -z "${NO_SMALL_DATA}"; then SDATA_GOT=" " fi fi + test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" " + test "${LARGE_SECTIONS}" = "yes" && REL_LARGE=" .rel.ldata ${RELOCATING-0} : { *(.rel.ldata${RELOCATING+ .rel.ldata.* .rel.gnu.linkonce.l.*}) } .rela.ldata ${RELOCATING-0} : { *(.rela.ldata${RELOCATING+ .rela.ldata.* .rela.gnu.linkonce.l.*}) } @@ -251,23 +303,7 @@ test "${LARGE_SECTIONS}" = "yes" && REL_LARGE=" .rela.lbss ${RELOCATING-0} : { *(.rela.lbss${RELOCATING+ .rela.lbss.* .rela.gnu.linkonce.lb.*}) } .rel.lrodata ${RELOCATING-0} : { *(.rel.lrodata${RELOCATING+ .rel.lrodata.* .rel.gnu.linkonce.lr.*}) } .rela.lrodata ${RELOCATING-0} : { *(.rela.lrodata${RELOCATING+ .rela.lrodata.* .rela.gnu.linkonce.lr.*}) }" -test "${LARGE_SECTIONS}" = "yes" && LARGE_BSS=" - .lbss ${RELOCATING-0} : - { - ${RELOCATING+*(.dynlbss)} - *(.lbss${RELOCATING+ .lbss.* .gnu.linkonce.lb.*}) - ${RELOCATING+*(LARGE_COMMON)} - }" -test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS=" - .lrodata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} : - { - *(.lrodata${RELOCATING+ .lrodata.* .gnu.linkonce.lr.*}) - } - .ldata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} : - { - *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*}) - ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} - }" + if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))" SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))" @@ -279,26 +315,6 @@ else CTORS_IN_INIT_ARRAY= DTORS_IN_FINI_ARRAY= fi -PREINIT_ARRAY=".preinit_array : - { - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__preinit_array_start"));} - KEEP (*(.preinit_array)) - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__preinit_array_end"));} - }" -INIT_ARRAY=".init_array : - { - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__init_array_start"));} - ${SORT_INIT_ARRAY} - KEEP (*(.init_array ${CTORS_IN_INIT_ARRAY})) - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__init_array_end"));} - }" -FINI_ARRAY=".fini_array : - { - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__fini_array_start"));} - ${SORT_FINI_ARRAY} - KEEP (*(.fini_array ${DTORS_IN_FINI_ARRAY})) - ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__fini_array_end"));} - }" CTOR=".ctors ${CONSTRUCTING-0} : { ${CONSTRUCTING+${CTOR_START}} @@ -335,32 +351,6 @@ DTOR=".dtors ${CONSTRUCTING-0} : KEEP (*(.dtors)) ${CONSTRUCTING+${DTOR_END}} }" -STACK=".stack ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} : - { - ${RELOCATING+$(def_symbol "_stack");} - *(.stack) - ${RELOCATING+${STACK_SENTINEL}} - }" -test "${HAVE_NOINIT}" = "yes" && NOINIT=" - /* This section contains data that is not initialized during load, - or during the application's initialization sequence. */ - .noinit ${RELOCATING-0} (NOLOAD) : ${RELOCATING+ALIGN(${ALIGNMENT})} - { - ${RELOCATING+PROVIDE (__noinit_start = .);} - *(.noinit${RELOCATING+ .noinit.* .gnu.linkonce.n.*}) - ${RELOCATING+. = ALIGN(${ALIGNMENT});} - ${RELOCATING+PROVIDE (__noinit_end = .);} - }" -test "${HAVE_PERSISTENT}" = "yes" && PERSISTENT=" - /* This section contains data that is initialized during load, - but not during the application's initialization sequence. */ - .persistent ${RELOCATING-0} : ${RELOCATING+ALIGN(${ALIGNMENT})} - { - ${RELOCATING+PROVIDE (__persistent_start = .);} - *(.persistent${RELOCATING+ .persistent.* .gnu.linkonce.p.*}) - ${RELOCATING+. = ALIGN(${ALIGNMENT});} - ${RELOCATING+PROVIDE (__persistent_end = .);} - }" TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${TEXT_START_ADDR})" SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-0})" @@ -410,6 +400,20 @@ cat <<EOF EOF } +align_to_default_symbol_alignment() +{ +cat <<EOF + ${RELOCATING+. = ALIGN(${ALIGNMENT});} +EOF +} + +align_to_default_section_alignment() +{ +cat <<EOF + ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} +EOF +} + emit_header() { cat <<EOF @@ -419,8 +423,7 @@ cat <<EOF are permitted in any medium without royalty provided the copyright notice and this notice are preserved. */ -OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}", - "${LITTLE_OUTPUT_FORMAT}") +OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}", "${LITTLE_OUTPUT_FORMAT}") OUTPUT_ARCH(${OUTPUT_ARCH}) ${RELOCATING+ENTRY(${ENTRY})} @@ -436,20 +439,61 @@ EOF emit_early_ro() { - cat <<EOF +cat <<EOF ${INITIAL_READONLY_SECTIONS} EOF } +emit_noinit() +{ + if test "${HAVE_NOINIT}" != "yes"; then + return + fi +cat <<EOF + /* This section contains data that is not initialized during load, + or during the application's initialization sequence. */ + .noinit ${RELOCATING-0} (NOLOAD) : ${RELOCATING+ALIGN(${ALIGNMENT})} + { + ${RELOCATING+PROVIDE (__noinit_start = .);} + *(.noinit${RELOCATING+ .noinit.* .gnu.linkonce.n.*}) + $(align_to_default_symbol_alignment) + ${RELOCATING+PROVIDE (__noinit_end = .);} + } +EOF +} + +emit_persistent() +{ + if test "${HAVE_PERSISTENT}" != "yes"; then + return + fi +cat <<EOF + /* This section contains data that is initialized during load, + but not during the application's initialization sequence. */ + .persistent ${RELOCATING-0} : ${RELOCATING+ALIGN(${ALIGNMENT})} + { + ${RELOCATING+PROVIDE (__persistent_start = .);} + *(.persistent${RELOCATING+ .persistent.* .gnu.linkonce.p.*}) + $(align_to_default_symbol_alignment) + ${RELOCATING+PROVIDE (__persistent_end = .);} + } +EOF +} + 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-${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};}} - /* Place build-id as close to the ELF headers as possible. This + ${CREATE_PIE+${RELOCATING+PROVIDE (__executable_start = ${SHLIB_TEXT_START_ADDR}); + . = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}} + + /* Place the build-id as close to the ELF headers as possible. This maximises the chance the build-id will be present in core files, which GDB can then use to locate the associated debuginfo file. */ .note.gnu.build-id ${RELOCATING-0}: { *(.note.gnu.build-id) } @@ -458,8 +502,8 @@ EOF emit_dyn() { -test -n "${RELOCATING+0}" || unset NON_ALLOC_DYN -test -z "${NON_ALLOC_DYN}" || TEXT_DYNAMIC= + test -n "${RELOCATING+0}" || unset NON_ALLOC_DYN + test -z "${NON_ALLOC_DYN}" || TEXT_DYNAMIC= cat > ldscripts/dyntmp.$$ <<EOF ${TEXT_DYNAMIC+${DYNAMIC}} @@ -523,16 +567,21 @@ cat >> ldscripts/dyntmp.$$ <<EOF .rel.dyn ${RELOCATING-0} : { EOF + sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rela\./d;/__rela_iplt_/d;s/^.*: { *\(.*\)}$/ \1/' $COMBRELOC >> ldscripts/dyntmp.$$ + cat >> ldscripts/dyntmp.$$ <<EOF } .rela.dyn ${RELOCATING-0} : { EOF + sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rel\./d;/__rel_iplt_/d;s/^.*: { *\(.*\)}/ \1/' $COMBRELOC >> ldscripts/dyntmp.$$ + cat >> ldscripts/dyntmp.$$ <<EOF } EOF + fi cat >> ldscripts/dyntmp.$$ <<EOF @@ -565,7 +614,7 @@ EOF fi rm -f ldscripts/dyntmp.$$ - + if test -n "${HAVE_DT_RELR}"; then echo " .relr.dyn : { *(.relr.dyn) }" fi @@ -573,15 +622,18 @@ EOF align_text() { + if test -n "$TEXT_SEGMENT_ALIGN"; then cat <<EOF ${RELOCATING+/* Align the text segment. */} ${RELOCATING+${TEXT_SEGMENT_ALIGN}} EOF +fi } emit_text() { cat <<EOF + /* Start of the executable code region. */ .init ${RELOCATING-0}${RELOCATING+${INIT_ADDR}} : { ${RELOCATING+${INIT_START}} @@ -613,35 +665,41 @@ cat <<EOF KEEP (*(SORT_NONE(.fini))) ${RELOCATING+${FINI_END}} } ${FILL} - +EOF +} + +emit_text_end_symbols() +{ +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} = .);}} - ${RELOCATING+${TEXT_SEGMENT_ALIGN}} EOF } align_rodata() { +cat <<EOF + /* Start of the Read Only Data region. */ +EOF + if test -n "${SEPARATE_CODE}${SEPARATE_TEXT}"; then if test -n "${RODATA_ADDR}"; then - RODATA_ADDR="\ -SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS" + RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS" else 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" + SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS" else SHLIB_RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))" SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR})" fi - cat <<EOF +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. */ ${CREATE_SHLIB-${CREATE_PIE-. = ${RODATA_ADDR};}} @@ -664,12 +722,16 @@ cat <<EOF .sframe ${RELOCATING-0} : ONLY_IF_RO { *(.sframe)${RELOCATING+ *(.sframe.*)} } .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table${RELOCATING+ .gcc_except_table.*}) } .gnu_extab ${RELOCATING-0} : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ .exception_ranges ${RELOCATING-0} : ONLY_IF_RO { *(.exception_ranges${RELOCATING+*}) } + ${TEXT_PLT+${PLT_NEXT_DATA+${PLT} ${OTHER_PLT_SECTIONS}}} - /* Various note sections. Placed here so that they are included in the - read-only segment, and so that they are not treated as orphan sections. */ + /* Various note sections. Placed here so that they are always included + in the read-only segment and not treated as orphan sections. The + current orphan handling algorithm does place note sections after R/O + data, but this is not guaranteed to always be the case. */ .note.build-id : { *(.note.build-id) } ${RELOCATING+${REGION}} .note.GNU-stack : { *(.note.GNU-stack) } ${RELOCATING+${REGION}} .note.gnu-property : { *(.note.gnu-property) } ${RELOCATING+${REGION}} @@ -685,23 +747,57 @@ cat <<EOF EOF } -emit_data() +align_data() { cat <<EOF + /* Start of the Read Write Data region. */ ${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}};}}} ${CREATE_SHLIB+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};} ${CREATE_PIE+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};} +EOF +} + +emit_init_fini_arrays() +{ +cat <<EOF +.preinit_array : + { + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__preinit_array_start"));} + KEEP (*(.preinit_array)) + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__preinit_array_end"));} + } + + .init_array : + { + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__init_array_start"));} + ${SORT_INIT_ARRAY} + KEEP (*(.init_array ${CTORS_IN_INIT_ARRAY})) + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__init_array_end"));} + } + + .fini_array : + { + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__fini_array_start"));} + ${SORT_FINI_ARRAY} + KEEP (*(.fini_array ${DTORS_IN_FINI_ARRAY})) + ${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__fini_array_end"));} + } +EOF +} - /* Exception handling */ +emit_data() +{ +cat <<EOF + /* Exception handling. */ .eh_frame ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame))${RELOCATING+ *(.eh_frame.*)} } .sframe ${RELOCATING-0} : ONLY_IF_RW { *(.sframe)${RELOCATING+ *(.sframe.*)} } .gnu_extab ${RELOCATING-0} : ONLY_IF_RW { *(.gnu_extab) } .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table${RELOCATING+ .gcc_except_table.*}) } .exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges${RELOCATING+*}) } - /* Thread Local Storage sections */ + /* Thread Local Storage sections. */ .tdata ${RELOCATING-0} : { ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__tdata_start"));}} @@ -709,11 +805,11 @@ cat <<EOF } .tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} } - ${RELOCATING+${PREINIT_ARRAY}} - ${RELOCATING+${INIT_ARRAY}} - ${RELOCATING+${FINI_ARRAY}} + ${RELOCATING+$(emit_init_fini_arrays)} + ${SMALL_DATA_CTOR-${RELOCATING+${CTOR}}} ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}} + .jcr ${RELOCATING-0} : { KEEP (*(.jcr)) } ${RELOCATING+${DATARELRO}} @@ -741,70 +837,165 @@ cat <<EOF *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*}) ${CONSTRUCTING+SORT(CONSTRUCTORS)} } + .data1 ${RELOCATING-0} : { *(.data1) } + ${WRITABLE_RODATA+${RODATA}} ${OTHER_READWRITE_SECTIONS} + ${SMALL_DATA_CTOR+${RELOCATING+${CTOR}}} ${SMALL_DATA_DTOR+${RELOCATING+${DTOR}}} ${SDATA_GOT+${DATA_PLT+${PLT_BEFORE_GOT+${PLT}}}} + ${SDATA_GOT+${RELOCATING+${OTHER_GOT_SYMBOLS+. = .; ${OTHER_GOT_SYMBOLS}}}} + ${SDATA_GOT+${GOT}} ${SDATA_GOT+${OTHER_GOT_SECTIONS}} + ${DATA_SDATA-${SDATA}} ${DATA_SDATA-${OTHER_SDATA_SECTIONS}} + ${RELOCATING+${SYMBOL_ABI_ALIGNMENT+. = ALIGN(${SYMBOL_ABI_ALIGNMENT});}} - ${RELOCATING+${DATA_END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}$(def_symbol "_edata")${CREATE_SHLIB+)}; PROVIDE ($(def_symbol "edata"));}} - ${PERSISTENT} + ${RELOCATING+${DATA_END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}$(def_symbol "_edata")${CREATE_SHLIB+)}; + PROVIDE ($(def_symbol "edata"));}} + + $(emit_persistent) + ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));} ${RELOCATING+${CREATE_SHLIB+PROVIDE (}$(def_symbol "__bss_start")${CREATE_SHLIB+)};} ${RELOCATING+${OTHER_BSS_SYMBOLS}} + ${DATA_SDATA-${SBSS}} ${BSS_PLT+${PLT}} .${BSS_NAME} ${RELOCATING-0} : { - ${RELOCATING+*(.dynbss)} - *(.${BSS_NAME}${RELOCATING+ .${BSS_NAME}.* .gnu.linkonce.b.*}) - ${RELOCATING+*(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we do not - pad the .data section. */ - . = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} + ${RELOCATING+*(.dynbss)} + *(.${BSS_NAME}${RELOCATING+ .${BSS_NAME}.* .gnu.linkonce.b.*}) + ${RELOCATING+*(COMMON)} + /* Align here to ensure that in the common case of there only being one + type of .bss section, the section occupies space up to _end. + Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + $(align_to_default_section_alignment) } + ${OTHER_BSS_SECTIONS} - ${LARGE_BSS_AFTER_BSS+${LARGE_BSS}} + + $(emit_large_bss 0) + ${RELOCATING+${OTHER_BSS_END_SYMBOLS}} - ${NOINIT} - ${RELOCATING+. = ALIGN(${ALIGNMENT});} + + $(emit_noinit) + + $(align_to_default_symbol_alignment) EOF } -emit_large_data() +align_large_data() { -LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${LARGE_DATA_ADDR-.});" -SHLIB_LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${SHLIB_LARGE_DATA_ADDR-.});" + LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${LARGE_DATA_ADDR-.});" + SHLIB_LARGE_DATA_ADDR=". = SEGMENT_START(\"ldata-segment\", ${SHLIB_LARGE_DATA_ADDR-.});" cat <<EOF + /* Start of the Large Data region. */ ${RELOCATING+${CREATE_SHLIB-${CREATE_PIE-${LARGE_DATA_ADDR}}}} ${CREATE_SHLIB+${SHLIB_LARGE_DATA_ADDR}} ${CREATE_PIE+${SHLIB_LARGE_DATA_ADDR}} - ${LARGE_SECTIONS} - ${LARGE_BSS_AFTER_BSS-${LARGE_BSS}} - ${RELOCATING+. = ALIGN(${ALIGNMENT});} +EOF +} + +emit_large_bss() +{ + if test "${LARGE_SECTIONS}" != "yes"; then + return + fi + + if test "$1" == "0"; then + if test -n "${LARGE_BSS_AFTER_BSS}"; then + return + fi + else + if test -z "${LARGE_BSS_AFTER_BSS}"; then + return + fi + fi + +cat <<EOF + .lbss ${RELOCATING-0} : + { + ${RELOCATING+*(.dynlbss)} + *(.lbss${RELOCATING+ .lbss.* .gnu.linkonce.lb.*}) + ${RELOCATING+*(LARGE_COMMON)} + } +EOF +} + +emit_large_data() +{ + if test "${LARGE_SECTIONS}" != "yes"; then + return + fi + +cat <<EOF + .lrodata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} : + { + *(.lrodata${RELOCATING+ .lrodata.* .gnu.linkonce.lr.*}) + } + + .ldata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} : + { + *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*}) + $(align_to_default_section_alignment) + } + + $(emit_large_bss 1) +EOF +} + +emit_end_symbols() +{ +cat <<EOF ${RELOCATING+${OTHER_END_SYMBOLS}} - ${RELOCATING+${END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}$(def_symbol "_end")${CREATE_SHLIB+)}; PROVIDE ($(def_symbol "end"));}} + + ${RELOCATING+${END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}$(def_symbol "_end")${CREATE_SHLIB+)}; + PROVIDE ($(def_symbol "end"));}} + ${RELOCATING+${DATA_SEGMENT_END}} +EOF +} + +emit_tiny_data() +{ +cat <<EOF + /* Start of the Tiny Data region. */ ${TINY_DATA_SECTION} ${TINY_BSS_SECTION} - ${STACK_ADDR+${STACK}} +EOF +} + +emit_stack() +{ + if test -z "${STACK_ADDR}"; then + return + fi + +cat <<EOF + /* Stack. */ + .stack ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} : + { + ${RELOCATING+$(def_symbol "_stack");} + *(.stack) + ${RELOCATING+${STACK_SENTINEL}} + } EOF } emit_misc() { -source_sh $srcdir/scripttempl/misc-sections.sc -source_sh $srcdir/scripttempl/DWARF.sc + source_sh $srcdir/scripttempl/misc-sections.sc + source_sh $srcdir/scripttempl/DWARF.sc cat <<EOF ${ATTRS_SECTIONS} @@ -826,8 +1017,17 @@ EOF emit_executable_start + #------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 @@ -840,32 +1040,62 @@ EOF fi fi - # We do not align the code segment here as doing so will increase the file size. - # Normally having the text segment at the start of the file will automatically - # mean that it is aligned(*), and if we have emitted any r/o sections due to the - # tests of SEPARATE_CODE above, then extra alignment will have already been - # generated. - # - # *: Including the ELF headers and .note.gnu.build-id section in the code segment - # is a very small theoretical risk. + #------Executable Code ---------------------------------------------------- + + # We do not invoke "align_text" here as doing so will increase the file + # size. Normally having the text segment at the start of the file will + # automatically mean that it is aligned and if we have emitted any R/O + # sections due to the code above, then extra alignment will have already + # been generated. emit_text + emit_text_end_symbols + + # FIXME: We emit the text segment alignment operations again here. + # (If they are defined). It is not clear why we do this. + + align_text + + #------Read Only Data ----------------------------------------------------- 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 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. + emit_rodata - + + #------Read Write Data ---------------------------------------------------- + + align_data emit_data + + align_large_data emit_large_data + align_to_default_symbol_alignment + emit_end_symbols + + # FIXME: Should the tiny data sections appear before the end symbols ? + + emit_tiny_data + + #------Miscellaneous ------------------------------------------------------ + + emit_stack + test -z "${NON_ALLOC_DYN}" || emit_dyn + emit_misc cat <<EOF |