aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog21
-rw-r--r--ld/ldgram.y7
-rw-r--r--ld/ldlang.c125
-rw-r--r--ld/ldlang.h12
4 files changed, 87 insertions, 78 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b9b806a..93ebd70 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,24 @@
+2002-05-07 Richard Sandiford <rsandifo@redhat.com>
+
+ * ldlang.h (lang_output_section_statement_type): Add update_dot_tree.
+ (lang_enter_overlay): Remove the last two parameters.
+ (lang_leave_overlay): Take them here instead.
+ * ldgram.y (memspec_at_opt): Set $$ to null if no region is given.
+ (section): Pass LMA and crossref flag to lang_leave_overlay rather
+ than lang_enter_overlay.
+ * ldlang.c (lang_memory_region_lookup): Return null for null names.
+ (lang_output_section_statement_lookup): Initialize update_dot_tree.
+ (lang_size_sections_1): Evaluate it.
+ (lang_leave_output_section_statement): Rework LMA lookup.
+ (overlay_lma, overlay_nocrossrefs): Remove.
+ (lang_enter_overlay): Remove LMA and corssref arguments.
+ (lang_enter_overlay_section): Don't set the LMA here.
+ (lang_leave_overlay): Take LMA and crossref arguments. Move the '.'
+ assignment to the last section's update_dot_tree. Unconditionally
+ use the load and run-time regions specified in the OVERLAY statement.
+ Likewise the first section's LMA. Only set the other sections' LMAs
+ when no load region is given.
+
2002-05-06 Nick Clifton <nickc@redhat.com>
* po/sv.po: New translation.
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 71da62c..3de9326 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -820,7 +820,7 @@ exp :
memspec_at_opt:
AT '>' NAME { $$ = $3; }
- | { $$ = "*default*"; }
+ | { $$ = 0; }
;
opt_at:
@@ -851,7 +851,7 @@ section: NAME { ldlex_expression(); }
{ ldlex_popstate (); ldlex_script (); }
'{'
{
- lang_enter_overlay ($3, $5, (int) $4);
+ lang_enter_overlay ($3);
}
overlay_section
'}'
@@ -859,7 +859,8 @@ section: NAME { ldlex_expression(); }
memspec_opt memspec_at_opt phdr_opt fill_opt
{
ldlex_popstate ();
- lang_leave_overlay ($15, $12, $14, $13);
+ lang_leave_overlay ($5, (int) $4,
+ $15, $12, $14, $13);
}
opt_comma
| /* The GROUP case is just enough to support the gcc
diff --git a/ld/ldlang.c b/ld/ldlang.c
index f8c9c44..054ffc0 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -617,6 +617,10 @@ lang_memory_region_lookup (name)
{
lang_memory_region_type *p;
+ /* NAME is NULL for LMA memspecs if no region was specified. */
+ if (name == NULL)
+ return NULL;
+
for (p = lang_memory_region_list;
p != (lang_memory_region_type *) NULL;
p = p->next)
@@ -738,6 +742,7 @@ lang_output_section_statement_lookup (name)
lookup->subsection_alignment = -1;
lookup->section_alignment = -1;
lookup->load_base = (union etree_union *) NULL;
+ lookup->update_dot_tree = NULL;
lookup->phdrs = NULL;
lang_statement_append (&lang_output_section_statement,
@@ -3009,9 +3014,14 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
else
os->bfd_section->_raw_size =
(after - os->bfd_section->vma) * opb;
+
dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
os->processed = true;
+ if (os->update_dot_tree != 0)
+ exp_fold_tree (os->update_dot_tree, abs_output_section,
+ lang_allocating_phase_enum, dot, &dot);
+
/* Update dot in the region ?
We only do this if the section is going to be allocated,
since unallocated sections do not contribute to the region's
@@ -4514,14 +4524,13 @@ lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
{
current_section->fill = fill;
current_section->region = lang_memory_region_lookup (memspec);
- if (strcmp (lma_memspec, "*default*") != 0)
- {
- current_section->lma_region = lang_memory_region_lookup (lma_memspec);
- /* If no runtime region has been given, but the load region has
- been, use the load region. */
- if (strcmp (memspec, "*default*") == 0)
- current_section->region = lang_memory_region_lookup (lma_memspec);
- }
+ current_section->lma_region = lang_memory_region_lookup (lma_memspec);
+
+ /* If no runtime region has been given, but the load region has
+ been, use the load region. */
+ if (current_section->lma_region != 0 && strcmp (memspec, "*default*") == 0)
+ current_section->region = current_section->lma_region;
+
current_section->phdrs = phdrs;
stat_ptr = &statement_list;
}
@@ -4803,12 +4812,6 @@ lang_add_nocrossref (l)
/* The overlay virtual address. */
static etree_type *overlay_vma;
-/* The overlay load address. */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay. */
-static int overlay_nocrossrefs;
-
/* An expression for the maximum section size seen so far. */
static etree_type *overlay_max;
@@ -4824,24 +4827,18 @@ static struct overlay_list *overlay_list;
/* Start handling an overlay. */
void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
etree_type *vma_expr;
- etree_type *lma_expr;
- int nocrossrefs;
{
/* The grammar should prevent nested overlays from occurring. */
- ASSERT (overlay_vma == NULL
- && overlay_lma == NULL
- && overlay_list == NULL
- && overlay_max == NULL);
+ ASSERT (overlay_vma == NULL && overlay_max == NULL);
overlay_vma = vma_expr;
- overlay_lma = lma_expr;
- overlay_nocrossrefs = nocrossrefs;
}
/* Start a section in an overlay. We handle this by calling
- lang_enter_output_section_statement with the correct VMA and LMA. */
+ lang_enter_output_section_statement with the correct VMA.
+ lang_leave_overlay sets up the LMA and memory regions. */
void
lang_enter_overlay_section (name)
@@ -4851,16 +4848,13 @@ lang_enter_overlay_section (name)
etree_type *size;
lang_enter_output_section_statement (name, overlay_vma, normal_section,
- 0, 0, 0, overlay_lma);
+ 0, 0, 0, 0);
- /* If this is the first section, then base the VMA and LMA of future
+ /* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is
used in the addresses. */
if (overlay_list == NULL)
- {
- overlay_vma = exp_nameop (ADDR, name);
- overlay_lma = exp_nameop (LOADADDR, name);
- }
+ overlay_vma = exp_nameop (ADDR, name);
/* Remember the section. */
n = (struct overlay_list *) xmalloc (sizeof *n);
@@ -4870,9 +4864,6 @@ lang_enter_overlay_section (name)
size = exp_nameop (SIZEOF, name);
- /* Adjust the LMA for the next section. */
- overlay_lma = exp_binop ('+', overlay_lma, size);
-
/* Arrange to work out the maximum section end address. */
if (overlay_max == NULL)
overlay_max = size;
@@ -4895,8 +4886,10 @@ lang_leave_overlay_section (fill, phdrs)
name = current_section->name;
- lang_leave_output_section_statement (fill, "*default*",
- phdrs, "*default*");
+ /* For now, assume that "*default*" is the run-time memory region and
+ that no load-time region has been specified. It doesn't really
+ matter what we say here, since lang_leave_overlay will override it. */
+ lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
/* Define the magic symbols. */
@@ -4926,32 +4919,30 @@ lang_leave_overlay_section (fill, phdrs)
looks through all the sections in the overlay and sets them. */
void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+ etree_type *lma_expr;
+ int nocrossrefs;
fill_type *fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{
lang_memory_region_type *region;
- lang_memory_region_type *default_region;
lang_memory_region_type *lma_region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
- default_region = lang_memory_region_lookup ("*default*");
-
- if (memspec == NULL)
- region = NULL;
- else
- region = lang_memory_region_lookup (memspec);
-
- if (lma_memspec == NULL)
- lma_region = NULL;
- else
- lma_region = lang_memory_region_lookup (lma_memspec);
+ region = lang_memory_region_lookup (memspec);
+ lma_region = lang_memory_region_lookup (lma_memspec);
nocrossref = NULL;
+ /* After setting the size of the last section, set '.' to end of the
+ overlay region. */
+ if (overlay_list != NULL)
+ overlay_list->os->update_dot_tree
+ = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
l = overlay_list;
while (l != NULL)
{
@@ -4960,28 +4951,24 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
l->os->fill = fill;
- /* Assign a region to the sections, if one has been specified.
- Override the assignment of the default section, but not
- other sections. */
- if (region != NULL &&
- (l->os->region == NULL ||
- l->os->region == default_region))
- l->os->region = region;
-
- /* We only set lma_region for the first overlay section, as
- subsequent overlay sections will have load_base set relative
- to the first section. Also, don't set lma_region if
- load_base is specified. FIXME: There should really be a test
- that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
- rather than letting LDADDR simply override LMA_REGION. */
- if (lma_region != NULL && l->os->lma_region == NULL
- && l->next == NULL && l->os->load_base == NULL)
- l->os->lma_region = lma_region;
+ l->os->region = region;
+ l->os->lma_region = lma_region;
+
+ /* The first section has the load address specified in the
+ OVERLAY statement. The rest are worked out from that.
+ The base address is not needed (and should be null) if
+ an LMA region was specified. */
+ if (l->next == 0)
+ l->os->load_base = lma_expr;
+ else if (lma_region == 0)
+ l->os->load_base = exp_binop ('+',
+ exp_nameop (LOADADDR, l->next->os->name),
+ exp_nameop (SIZEOF, l->next->os->name));
if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs;
- if (overlay_nocrossrefs)
+ if (nocrossrefs)
{
struct lang_nocrossref *nc;
@@ -4999,13 +4986,7 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
if (nocrossref != NULL)
lang_add_nocrossref (nocrossref);
- /* Update . for the end of the overlay. */
- lang_add_assignment (exp_assop ('=', ".",
- exp_binop ('+', overlay_vma, overlay_max)));
-
overlay_vma = NULL;
- overlay_lma = NULL;
- overlay_nocrossrefs = 0;
overlay_list = NULL;
overlay_max = NULL;
}
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 4e3353a..26c4121 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -135,6 +135,12 @@ typedef struct lang_output_section_statement_struct {
union etree_union *load_base;
+ /* If non-null, an expression to evaluate after setting the section's
+ size. The expression is evaluated inside REGION (above) with '.'
+ set to the end of the section. Used in the last overlay section
+ to move '.' past all the overlaid sections. */
+ union etree_union *update_dot_tree;
+
struct lang_output_section_phdr_list *phdrs;
} lang_output_section_statement_type;
@@ -456,13 +462,13 @@ extern void lang_new_phdr
PARAMS ((const char *, etree_type *, boolean, boolean, etree_type *,
etree_type *));
extern void lang_add_nocrossref PARAMS ((struct lang_nocrossref *));
-extern void lang_enter_overlay PARAMS ((etree_type *, etree_type *, int));
+extern void lang_enter_overlay PARAMS ((etree_type *));
extern void lang_enter_overlay_section PARAMS ((const char *));
extern void lang_leave_overlay_section
PARAMS ((fill_type *, struct lang_output_section_phdr_list *));
extern void lang_leave_overlay
- PARAMS ((fill_type *, const char *, struct lang_output_section_phdr_list *,
- const char *));
+ PARAMS ((etree_type *, int, fill_type *, const char *,
+ struct lang_output_section_phdr_list *, const char *));
extern struct bfd_elf_version_tree *lang_elf_version_info;