diff --git a/ld/ChangeLog b/ld/ChangeLog index 5b5b11d0a1..bc6aa01279 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2010-02-23 Alan Modra + + PR ld/11304 + * ldlang.c: Revert last patch. + 2010-02-23 Nick Clifton * po/bg.po: Updated Bulgarian translation. diff --git a/ld/ldlang.c b/ld/ldlang.c index 18ec6a4365..ce5a11c369 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -68,6 +68,7 @@ static struct unique_sections *unique_section_list; static bfd_boolean ldlang_sysrooted_script = FALSE; /* Forward declarations. */ +static void exp_init_os (etree_type *); static void init_map_userdata (bfd *, asection *, void *); static lang_input_statement_type *lookup_name (const char *); static struct bfd_hash_entry *lang_definedness_newfunc @@ -2047,8 +2048,12 @@ sort_def_symbol (struct bfd_link_hash_entry *hash_entry, /* Initialize an output section. */ static void -init_os (lang_output_section_statement_type *s, asection *isec, flagword flags) +init_os (lang_output_section_statement_type *s, asection *isec, + flagword flags) { + if (s->bfd_section != NULL) + return; + if (strcmp (s->name, DISCARD_SECTION_NAME) == 0) einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME); @@ -2073,6 +2078,14 @@ init_os (lang_output_section_statement_type *s, asection *isec, flagword flags) get_userdata (s->bfd_section) = new_userdata; } + /* If there is a base address, make sure that any sections it might + mention are initialized. */ + if (s->addr_tree != NULL) + exp_init_os (s->addr_tree); + + if (s->load_base != NULL) + exp_init_os (s->load_base); + /* If supplied an alignment, set it. */ if (s->section_alignment != -1) s->bfd_section->alignment_power = s->section_alignment; @@ -3417,10 +3430,10 @@ map_input_to_output_sections (lang_statement_union_type *s, const char *target, lang_output_section_statement_type *os) { + flagword flags; + for (; s != NULL; s = s->header.next) { - lang_output_section_statement_type *tos; - switch (s->header.type) { case lang_wild_statement_enum: @@ -3432,23 +3445,29 @@ map_input_to_output_sections os); break; case lang_output_section_statement_enum: - tos = &s->output_section_statement; - if (tos->constraint != 0) + if (s->output_section_statement.constraint) { - if (tos->constraint != ONLY_IF_RW - && tos->constraint != ONLY_IF_RO) + if (s->output_section_statement.constraint != ONLY_IF_RW + && s->output_section_statement.constraint != ONLY_IF_RO) break; - tos->all_input_readonly = TRUE; - check_input_sections (tos->children.head, tos); - if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO)) + s->output_section_statement.all_input_readonly = TRUE; + check_input_sections (s->output_section_statement.children.head, + &s->output_section_statement); + if ((s->output_section_statement.all_input_readonly + && s->output_section_statement.constraint == ONLY_IF_RW) + || (!s->output_section_statement.all_input_readonly + && s->output_section_statement.constraint == ONLY_IF_RO)) { - tos->constraint = -1; + s->output_section_statement.constraint = -1; break; } } - map_input_to_output_sections (tos->children.head, + + map_input_to_output_sections (s->output_section_statement.children.head, target, - tos); + &s->output_section_statement); + break; + case lang_output_statement_enum: break; case lang_target_statement_enum: target = s->target_statement.target; @@ -3458,102 +3477,19 @@ map_input_to_output_sections target, os); break; - case lang_address_statement_enum: - /* Mark the specified section with the supplied address. - If this section was actually a segment marker, then the - directive is ignored if the linker script explicitly - processed the segment marker. Originally, the linker - treated segment directives (like -Ttext on the - command-line) as section directives. We honor the - section directive semantics for backwards compatibilty; - linker scripts that do not specifically check for - SEGMENT_START automatically get the old semantics. */ - if (!s->address_statement.segment - || !s->address_statement.segment->used) - { - const char *name = s->address_statement.section_name; - - /* Create the output section statement here rather than - in create_other_output_sections so that orphans with - a set address will be placed after other script - sections. If we let the orphan placement code place - them in amongst other sections then the address will - affect following script sections, which is likely to - surprise naive users. */ - tos = lang_output_section_statement_lookup (name, 0, TRUE); - tos->addr_tree = s->address_statement.address; - } - break; - case lang_output_statement_enum: - case lang_data_statement_enum: - case lang_input_section_enum: - case lang_fill_statement_enum: - case lang_object_symbols_statement_enum: - case lang_reloc_statement_enum: - case lang_padding_statement_enum: - case lang_input_statement_enum: - case lang_assignment_statement_enum: - case lang_insert_statement_enum: - break; - } - } -} - -/* Create any other output sections, such as needed for data statements - or those referenced in expressions. */ - -static void -create_other_output_sections - (lang_statement_union_type *s, - lang_output_section_statement_type *os) -{ - lang_output_section_statement_type *tos; - flagword flags; - - for (; s != NULL; s = s->header.next) - { - switch (s->header.type) - { - case lang_wild_statement_enum: - break; - case lang_constructors_statement_enum: - create_other_output_sections (constructor_list.head, os); - break; - case lang_output_section_statement_enum: - tos = &s->output_section_statement; - if (tos->constraint != 0 - && tos->constraint != ONLY_IF_RW - && tos->constraint != ONLY_IF_RO) - break; - create_other_output_sections (tos->children.head, tos); - if (tos->bfd_section != NULL) - { - /* If there is a base address, make sure that any sections - it might mention are initialized. */ - if (tos->addr_tree != NULL) - exp_init_os (tos->addr_tree); - if (tos->load_base != NULL) - exp_init_os (tos->load_base); - } - break; - case lang_output_statement_enum: - case lang_target_statement_enum: - break; - case lang_group_statement_enum: - create_other_output_sections (s->group_statement.children.head, os); - break; case lang_data_statement_enum: /* Make sure that any sections mentioned in the expression are initialized. */ exp_init_os (s->data_statement.exp); - if (os->bfd_section == NULL) - init_os (os, NULL, 0); flags = SEC_HAS_CONTENTS; /* The output section gets contents, and then we inspect for any flags set in the input script which override any ALLOC. */ if (!(os->flags & SEC_NEVER_LOAD)) flags |= SEC_ALLOC | SEC_LOAD; - os->bfd_section->flags |= flags; + if (os->bfd_section == NULL) + init_os (os, NULL, flags); + else + os->bfd_section->flags |= flags; break; case lang_input_section_enum: break; @@ -3574,14 +3510,25 @@ create_other_output_sections exp_init_os (s->assignment_statement.exp); break; case lang_address_statement_enum: + /* Mark the specified section with the supplied address. + If this section was actually a segment marker, then the + directive is ignored if the linker script explicitly + processed the segment marker. Originally, the linker + treated segment directives (like -Ttext on the + command-line) as section directives. We honor the + section directive semantics for backwards compatibilty; + linker scripts that do not specifically check for + SEGMENT_START automatically get the old semantics. */ if (!s->address_statement.segment || !s->address_statement.segment->used) { - const char *name = s->address_statement.section_name; + lang_output_section_statement_type *aos + = (lang_output_section_statement_lookup + (s->address_statement.section_name, 0, TRUE)); - tos = lang_output_section_find (name); - if (tos->bfd_section == NULL) - init_os (tos, NULL, 0); + if (aos->bfd_section == NULL) + init_os (aos, NULL, 0); + aos->addr_tree = s->address_statement.address; } break; case lang_insert_statement_enum: @@ -6400,10 +6347,6 @@ lang_process (void) /* Find any sections not attached explicitly and handle them. */ lang_place_orphans (); - /* Create sections for data statements and those referenced in - expressions but otherwise empty. */ - create_other_output_sections (statement_list.head, NULL); - if (! link_info.relocatable) { asection *found;