diff options
-rw-r--r-- | ld/ChangeLog | 21 | ||||
-rw-r--r-- | ld/ldgram.y | 7 | ||||
-rw-r--r-- | ld/ldlang.c | 125 | ||||
-rw-r--r-- | ld/ldlang.h | 12 |
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; |