aboutsummaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-07-15 08:46:35 +0930
committerAlan Modra <amodra@gmail.com>2023-07-17 08:17:44 +0930
commit63e8fb86255ac97c31d368221be18850ad53039d (patch)
tree508341e8d8cdeab39688128e43308332161307f6 /ld/ldexp.c
parent5c77898d60cfea469a86fc6026f51b4a6d8e7444 (diff)
downloadgdb-63e8fb86255ac97c31d368221be18850ad53039d.zip
gdb-63e8fb86255ac97c31d368221be18850ad53039d.tar.gz
gdb-63e8fb86255ac97c31d368221be18850ad53039d.tar.bz2
Support NEXT_SECTION in ALIGNOF and SIZEOF
This patch is aimed at making __bss_start properly aligned with the first of any bss-style sections following. Most of the work here involves keeping track of the last output section seen when processing the linker script. You can almost align __bss_start properly by using ${RELOCATING+. = ALIGN(${DATA_SDATA-${NO_SMALL_DATA-ALIGNOF(.${SBSS_NAME}) != 0 ? ALIGNOF(.${SBSS_NAME}) : }}${BSS_PLT+ALIGNOF(.plt) != 0 ? ALIGNOF(.plt) : }ALIGNOF(.${BSS_NAME}));} and changing every place that defines NO_SMALL_DATA to use " ", but having two .plt sections (marked SPECIAL) on some backends foils that idea. The problem is that you only want to pick up the following .plt, not the one preceeding __bss_start in the data segment if the backend decides that is the proper .plt section. Perhaps that could be fixed too, but I decided instead to extend the linker script a little. THIS_SECTION and PREV_SECTION could easily be added too. * ld.texi (ALIGNOF, SIZEOF): Update and mention NEXT_SECTION. * ldexp.c (output_section_find): New function. (fold_name <ALIGNOF, SIZEOF>): Use output_section_find. (exp_fold_tree): Add os parameter. Adjust all calls. (exp_fold_tree_no_dot, exp_get_vma, exp_get_power): Likewise. * ldexp.h (struct ldexp_control): Add last_os. (exp_fold_tree, exp_fold_tree_no_dot): Update prototypes. (exp_get_vma, exp_get_power): Likewise. * ldlang.c: Pass last output section to expression folder calls throughout file. (open_input_bfds): Add os parameter to track last os seen. (lang_size_sections_1): Rename output_section_statement param to current_os. Track last os. (lang_do_assignments_1): Track last os. * scripttempl/arclinux.sc: Align to ALIGNOF NEXT_SECTION before defining __bss_start. * scripttempl/elf.sc: Likewise. * scripttempl/elf64bpf.sc: Likewise. * scripttempl/elf64hppa.sc: Likewise. * scripttempl/elf_chaos.sc: Likewise. * scripttempl/elfarc.sc: Likewise. * scripttempl/elfd10v.sc: Likewise. * scripttempl/elfxtensa.sc: Likewise. * scripttempl/epiphany_4x4.sc: Likewise. * scripttempl/iq2000.sc: Likewise. * scripttempl/mep.sc: Likewise. * scripttempl/nds32elf.sc: Likewise. * scripttempl/xstormy16.sc: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Update expected __bss_start. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 170e1ed..8b9d6dc 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -691,6 +691,24 @@ fold_trinary (etree_type *tree)
: tree->trinary.rhs);
}
+static lang_output_section_statement_type *
+output_section_find (const char *name)
+{
+ lang_output_section_statement_type *os = lang_output_section_find (name);
+
+ if (os == NULL && strcmp (name, "NEXT_SECTION") == 0)
+ {
+ os = expld.last_os;
+ if (os != NULL)
+ while ((os = os->next) != NULL)
+ if (os->constraint >= 0 && os->bfd_section != NULL)
+ break;
+ if (os == NULL)
+ os = abs_output_section;
+ }
+ return os;
+}
+
static void
fold_name (etree_type *tree)
{
@@ -850,7 +868,7 @@ fold_name (etree_type *tree)
{
lang_output_section_statement_type *os;
- os = lang_output_section_find (tree->name.name);
+ os = output_section_find (tree->name.name);
if (os == NULL)
{
if (expld.phase == lang_final_phase_enum)
@@ -1270,29 +1288,32 @@ exp_fold_tree_1 (etree_type *tree)
}
void
-exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
+exp_fold_tree (etree_type *tree, lang_output_section_statement_type *os,
+ asection *current_section, bfd_vma *dotp)
{
expld.rel_from_abs = false;
expld.dot = *dotp;
expld.dotp = dotp;
expld.section = current_section;
+ expld.last_os = os;
exp_fold_tree_1 (tree);
}
void
-exp_fold_tree_no_dot (etree_type *tree)
+exp_fold_tree_no_dot (etree_type *tree, lang_output_section_statement_type *os)
{
expld.rel_from_abs = false;
expld.dot = 0;
expld.dotp = NULL;
expld.section = bfd_abs_section_ptr;
+ expld.last_os = os;
exp_fold_tree_1 (tree);
}
static void
exp_value_fold (etree_type *tree)
{
- exp_fold_tree_no_dot (tree);
+ exp_fold_tree_no_dot (tree, NULL);
if (expld.result.valid_p)
{
tree->type.node_code = INT;
@@ -1547,11 +1568,12 @@ exp_print_tree (etree_type *tree)
}
bfd_vma
-exp_get_vma (etree_type *tree, bfd_vma def, char *name)
+exp_get_vma (etree_type *tree, lang_output_section_statement_type *os,
+ bfd_vma def, char *name)
{
if (tree != NULL)
{
- exp_fold_tree_no_dot (tree);
+ exp_fold_tree_no_dot (tree, os);
if (expld.result.valid_p)
return expld.result.value;
else if (name != NULL && expld.phase != lang_mark_phase_enum)
@@ -1567,9 +1589,10 @@ exp_get_vma (etree_type *tree, bfd_vma def, char *name)
NULL or cannot be resolved, return -1. */
int
-exp_get_power (etree_type *tree, char *name)
+exp_get_power (etree_type *tree, lang_output_section_statement_type *os,
+ char *name)
{
- bfd_vma x = exp_get_vma (tree, -1, name);
+ bfd_vma x = exp_get_vma (tree, os, -1, name);
bfd_vma p2;
int n;
@@ -1593,7 +1616,7 @@ exp_get_fill (etree_type *tree, fill_type *def, char *name)
if (tree == NULL)
return def;
- exp_fold_tree_no_dot (tree);
+ exp_fold_tree_no_dot (tree, NULL);
if (!expld.result.valid_p)
{
if (name != NULL && expld.phase != lang_mark_phase_enum)
@@ -1647,7 +1670,7 @@ exp_get_abs_int (etree_type *tree, int def, char *name)
{
if (tree != NULL)
{
- exp_fold_tree_no_dot (tree);
+ exp_fold_tree_no_dot (tree, NULL);
if (expld.result.valid_p)
{