diff options
Diffstat (limited to 'binutils-2.25/ld/ldlang.c')
-rw-r--r-- | binutils-2.25/ld/ldlang.c | 187 |
1 files changed, 75 insertions, 112 deletions
diff --git a/binutils-2.25/ld/ldlang.c b/binutils-2.25/ld/ldlang.c index c4da07f5..8982aa22 100644 --- a/binutils-2.25/ld/ldlang.c +++ b/binutils-2.25/ld/ldlang.c @@ -5295,7 +5295,7 @@ lang_size_sections_1 } expld.dataseg.relro = exp_dataseg_relro_none; - /* This symbol may be relative to this section. */ + /* This symbol is relative to this section. */ if ((tree->type.node_class == etree_provided || tree->type.node_class == etree_assign) && (tree->assign.dst [0] != '.' @@ -5518,18 +5518,13 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) expld.dataseg.phase = exp_dataseg_done; } -static lang_output_section_statement_type *current_section; -static lang_assignment_statement_type *current_assign; -static bfd_boolean prefer_next_section; - /* 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 *current_os, fill_type *fill, - bfd_vma dot, - bfd_boolean *found_end) + bfd_vma dot) { for (; s != NULL; s = s->header.next) { @@ -5537,7 +5532,7 @@ lang_do_assignments_1 (lang_statement_union_type *s, { case lang_constructors_statement_enum: dot = lang_do_assignments_1 (constructor_list.head, - current_os, fill, dot, found_end); + current_os, fill, dot); break; case lang_output_section_statement_enum: @@ -5545,18 +5540,12 @@ lang_do_assignments_1 (lang_statement_union_type *s, lang_output_section_statement_type *os; os = &(s->output_section_statement); - os->after_end = *found_end; if (os->bfd_section != NULL && !os->ignored) { - if ((os->bfd_section->flags & SEC_ALLOC) != 0) - { - current_section = os; - prefer_next_section = FALSE; - } dot = os->bfd_section->vma; lang_do_assignments_1 (os->children.head, - os, os->fill, dot, found_end); + os, os->fill, dot); /* .tbss sections effectively have zero size. */ if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0 @@ -5573,7 +5562,7 @@ lang_do_assignments_1 (lang_statement_union_type *s, case lang_wild_statement_enum: dot = lang_do_assignments_1 (s->wild_statement.children.head, - current_os, fill, dot, found_end); + current_os, fill, dot); break; case lang_object_symbols_statement_enum: @@ -5644,19 +5633,6 @@ lang_do_assignments_1 (lang_statement_union_type *s, break; case lang_assignment_statement_enum: - current_assign = &s->assignment_statement; - if (current_assign->exp->type.node_class != etree_assert) - { - const char *p = current_assign->exp->assign.dst; - - if (current_os == abs_output_section && p[0] == '.' && p[1] == 0) - prefer_next_section = TRUE; - - while (*p == '_') - ++p; - if (strcmp (p, "end") == 0) - *found_end = TRUE; - } exp_fold_tree (s->assignment_statement.exp, current_os->bfd_section, &dot); @@ -5668,7 +5644,7 @@ lang_do_assignments_1 (lang_statement_union_type *s, case lang_group_statement_enum: dot = lang_do_assignments_1 (s->group_statement.children.head, - current_os, fill, dot, found_end); + current_os, fill, dot); break; case lang_insert_statement_enum: @@ -5688,89 +5664,10 @@ lang_do_assignments_1 (lang_statement_union_type *s, void lang_do_assignments (lang_phase_type phase) { - bfd_boolean found_end = FALSE; - - current_section = NULL; - prefer_next_section = FALSE; expld.phase = phase; lang_statement_iteration++; lang_do_assignments_1 (statement_list.head, - abs_output_section, NULL, 0, &found_end); -} - -/* For an assignment statement outside of an output section statement, - choose the best of neighbouring output sections to use for values - of "dot". */ - -asection * -section_for_dot (void) -{ - asection *s; - - /* Assignments belong to the previous output section, unless there - has been an assignment to "dot", in which case following - assignments belong to the next output section. (The assumption - is that an assignment to "dot" is setting up the address for the - next output section.) Except that past the assignment to "_end" - we always associate with the previous section. This exception is - for targets like SH that define an alloc .stack or other - weirdness after non-alloc sections. */ - if (current_section == NULL || prefer_next_section) - { - lang_statement_union_type *stmt; - lang_output_section_statement_type *os; - - for (stmt = (lang_statement_union_type *) current_assign; - stmt != NULL; - stmt = stmt->header.next) - if (stmt->header.type == lang_output_section_statement_enum) - break; - - os = &stmt->output_section_statement; - while (os != NULL - && !os->after_end - && (os->bfd_section == NULL - || (os->bfd_section->flags & SEC_EXCLUDE) != 0 - || bfd_section_removed_from_list (link_info.output_bfd, - os->bfd_section))) - os = os->next; - - if (current_section == NULL || os == NULL || !os->after_end) - { - if (os != NULL) - s = os->bfd_section; - else - s = link_info.output_bfd->section_last; - while (s != NULL - && ((s->flags & SEC_ALLOC) == 0 - || (s->flags & SEC_THREAD_LOCAL) != 0)) - s = s->prev; - if (s != NULL) - return s; - - return bfd_abs_section_ptr; - } - } - - s = current_section->bfd_section; - - /* The section may have been stripped. */ - while (s != NULL - && ((s->flags & SEC_EXCLUDE) != 0 - || (s->flags & SEC_ALLOC) == 0 - || (s->flags & SEC_THREAD_LOCAL) != 0 - || bfd_section_removed_from_list (link_info.output_bfd, s))) - s = s->prev; - if (s == NULL) - s = link_info.output_bfd->sections; - while (s != NULL - && ((s->flags & SEC_ALLOC) == 0 - || (s->flags & SEC_THREAD_LOCAL) != 0)) - s = s->next; - if (s != NULL) - return s; - - return bfd_abs_section_ptr; + abs_output_section, NULL, 0); } /* Fix any .startof. or .sizeof. symbols. When the assemblers see the @@ -5802,8 +5699,8 @@ lang_set_startof (void) if (h != NULL && h->type == bfd_link_hash_undefined) { h->type = bfd_link_hash_defined; - h->u.def.value = 0; - h->u.def.section = s; + h->u.def.value = bfd_get_section_vma (link_info.output_bfd, s); + h->u.def.section = bfd_abs_section_ptr; } sprintf (buf, ".sizeof.%s", secname); @@ -6286,6 +6183,8 @@ lang_add_output (const char *name, int from_script) } } +static lang_output_section_statement_type *current_section; + static int topower (int x) { @@ -7100,6 +6999,70 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec, pop_stat_ptr (); } +/* Create an absolute symbol with the given name with the value of the + address of first byte of the section named. + + If the symbol already exists, then do nothing. */ + +void +lang_abs_symbol_at_beginning_of (const char *secname, const char *name) +{ + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE); + if (h == NULL) + einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + + if (h->type == bfd_link_hash_new + || h->type == bfd_link_hash_undefined) + { + asection *sec; + + h->type = bfd_link_hash_defined; + + sec = bfd_get_section_by_name (link_info.output_bfd, secname); + if (sec == NULL) + h->u.def.value = 0; + else + h->u.def.value = bfd_get_section_vma (link_info.output_bfd, sec); + + h->u.def.section = bfd_abs_section_ptr; + } +} + +/* Create an absolute symbol with the given name with the value of the + address of the first byte after the end of the section named. + + If the symbol already exists, then do nothing. */ + +void +lang_abs_symbol_at_end_of (const char *secname, const char *name) +{ + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE); + if (h == NULL) + einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + + if (h->type == bfd_link_hash_new + || h->type == bfd_link_hash_undefined) + { + asection *sec; + + h->type = bfd_link_hash_defined; + + sec = bfd_get_section_by_name (link_info.output_bfd, secname); + if (sec == NULL) + h->u.def.value = 0; + else + h->u.def.value = (bfd_get_section_vma (link_info.output_bfd, sec) + + TO_ADDR (sec->size)); + + h->u.def.section = bfd_abs_section_ptr; + } +} + + void lang_statement_append (lang_statement_list_type *list, lang_statement_union_type *element, |