aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c118
1 files changed, 67 insertions, 51 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b1c5a8b..7938eb6 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1164,16 +1164,17 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
new->name = xstrdup (name);
new->next = NULL;
-
- *lang_memory_region_list_tail = new;
- lang_memory_region_list_tail = &new->next;
new->origin = 0;
- new->flags = 0;
- new->not_flags = 0;
new->length = ~(bfd_size_type) 0;
new->current = 0;
+ new->last_os = NULL;
+ new->flags = 0;
+ new->not_flags = 0;
new->had_full_message = FALSE;
+ *lang_memory_region_list_tail = new;
+ lang_memory_region_list_tail = &new->next;
+
return new;
}
@@ -1462,7 +1463,6 @@ lang_insert_orphan (asection *s,
lang_statement_list_type *old;
lang_statement_list_type add;
const char *ps;
- etree_type *load_base;
lang_output_section_statement_type *os;
lang_output_section_statement_type **os_tail;
@@ -1506,20 +1506,10 @@ lang_insert_orphan (asection *s,
if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
address = exp_intop (0);
- load_base = NULL;
- if (after != NULL && after->load_base != NULL)
- {
- etree_type *lma_from_vma;
- lma_from_vma = exp_binop ('-', after->load_base,
- exp_nameop (ADDR, after->name));
- load_base = exp_binop ('+', lma_from_vma,
- exp_nameop (ADDR, secname));
- }
-
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
- load_base, 0);
+ NULL, 0);
if (add_child == NULL)
add_child = &os->children;
@@ -4417,20 +4407,16 @@ lang_size_sections_1
os_region_check (os, os->region, os->addr_tree,
os->bfd_section->vma);
- /* If there's no load address specified, use the run
- region as the load region. */
- if (os->lma_region == NULL && os->load_base == NULL)
- os->lma_region = os->region;
-
if (os->lma_region != NULL && os->lma_region != os->region)
{
/* Set load_base, which will be handled later. */
os->load_base = exp_intop (os->lma_region->current);
os->lma_region->current +=
TO_ADDR (os->bfd_section->size);
+
if (check_regions)
os_region_check (os, os->lma_region, NULL,
- os->bfd_section->lma);
+ os->lma_region->current);
}
}
}
@@ -4709,11 +4695,10 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
/* Worker function for lang_do_assignments. Recursiveness goes here. */
static bfd_vma
-lang_do_assignments_1
- (lang_statement_union_type *s,
- lang_output_section_statement_type *output_section_statement,
- fill_type *fill,
- bfd_vma dot)
+lang_do_assignments_1 (lang_statement_union_type *s,
+ lang_output_section_statement_type *current_os,
+ fill_type *fill,
+ bfd_vma dot)
{
for (; s != NULL; s = s->header.next)
{
@@ -4721,9 +4706,7 @@ lang_do_assignments_1
{
case lang_constructors_statement_enum:
dot = lang_do_assignments_1 (constructor_list.head,
- output_section_statement,
- fill,
- dot);
+ current_os, fill, dot);
break;
case lang_output_section_statement_enum:
@@ -4733,22 +4716,61 @@ lang_do_assignments_1
os = &(s->output_section_statement);
if (os->bfd_section != NULL && !os->ignored)
{
+ lang_memory_region_type *r;
+
dot = os->bfd_section->vma;
- lang_do_assignments_1 (os->children.head, os, os->fill, dot);
+ r = os->region;
+ if (r == NULL)
+ r = lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
+
+ if (os->load_base)
+ os->bfd_section->lma
+ = exp_get_abs_int (os->load_base, 0, "load base");
+ else if (r->last_os != NULL)
+ {
+ asection *last;
+ bfd_vma lma;
+
+ last = r->last_os->output_section_statement.bfd_section;
+
+ /* If the current vma overlaps the previous section,
+ then set the current lma to that at the end of
+ the previous section. The previous section was
+ probably an overlay. */
+ if ((dot >= last->vma
+ && dot < last->vma + last->size)
+ || (last->vma >= dot
+ && last->vma < dot + os->bfd_section->size))
+ lma = last->lma + last->size;
+
+ /* Otherwise, keep the same lma to vma relationship
+ as the previous section. */
+ else
+ lma = dot + last->lma - last->vma;
+
+ if (os->section_alignment != -1)
+ lma = align_power (lma, os->section_alignment);
+ os->bfd_section->lma = lma;
+ }
+
+ lang_do_assignments_1 (os->children.head,
+ os, os->fill, dot);
+
/* .tbss sections effectively have zero size. */
if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
|| link_info.relocatable)
- dot += TO_ADDR (os->bfd_section->size);
- }
- if (os->load_base)
- {
- /* If nothing has been placed into the output section then
- it won't have a bfd_section. */
- if (os->bfd_section && !os->ignored)
{
- os->bfd_section->lma
- = exp_get_abs_int (os->load_base, 0, "load base");
+ dot += TO_ADDR (os->bfd_section->size);
+
+ /* Keep track of normal sections using the default
+ lma region. We use this to set the lma for
+ following sections. Overlays or other linker
+ script assignment to lma might mean that the
+ default lma == vma is incorrect. */
+ if (!link_info.relocatable
+ && os->lma_region == NULL)
+ r->last_os = s;
}
}
}
@@ -4757,8 +4779,7 @@ lang_do_assignments_1
case lang_wild_statement_enum:
dot = lang_do_assignments_1 (s->wild_statement.children.head,
- output_section_statement,
- fill, dot);
+ current_os, fill, dot);
break;
case lang_object_symbols_statement_enum:
@@ -4827,7 +4848,7 @@ lang_do_assignments_1
case lang_assignment_statement_enum:
exp_fold_tree (s->assignment_statement.exp,
- output_section_statement->bfd_section,
+ current_os->bfd_section,
&dot);
break;
@@ -4837,8 +4858,7 @@ lang_do_assignments_1
case lang_group_statement_enum:
dot = lang_do_assignments_1 (s->group_statement.children.head,
- output_section_statement,
- fill, dot);
+ current_os, fill, dot);
break;
default:
@@ -5423,8 +5443,8 @@ lang_reset_memory_regions (void)
for (p = lang_memory_region_list; p != NULL; p = p->next)
{
- p->old_length = (bfd_size_type) (p->current - p->origin);
p->current = p->origin;
+ p->last_os = NULL;
}
for (os = &lang_output_section_statement.head->output_section_statement;
@@ -6350,10 +6370,6 @@ lang_leave_overlay (etree_type *lma_expr,
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;