aboutsummaryrefslogtreecommitdiff
path: root/ld/scripttempl/elf.sc
diff options
context:
space:
mode:
Diffstat (limited to 'ld/scripttempl/elf.sc')
-rw-r--r--ld/scripttempl/elf.sc118
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