aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2010-02-22 12:09:59 +0000
committerAlan Modra <amodra@gmail.com>2010-02-22 12:09:59 +0000
commitc380a809dea581f548281e813edfc5b6e5007708 (patch)
treeb83e6ed43b0f0a552da80868291b0279fc1463e9
parent8a59fff3dd9f8003c95d89ee2a71d632b130cf8b (diff)
downloadgdb-c380a809dea581f548281e813edfc5b6e5007708.zip
gdb-c380a809dea581f548281e813edfc5b6e5007708.tar.gz
gdb-c380a809dea581f548281e813edfc5b6e5007708.tar.bz2
PR ld/11304
* ldlang.c (exp_init_os): Delete forward declaration. (init_os): Don't check for bfd_section already created and don't init addr_tree and load_base expressions here. (map_input_to_output_sections): Only map input to output sections and set constraints here, and as an exception, create output sections which have their address set. Move all the other code to.. (create_other_output_sections): ..here. New function. Handle init of addr_tree and load_base here too. (lang_process): Call create_other_output_sections.
-rw-r--r--ld/ChangeLog13
-rw-r--r--ld/ldlang.c159
2 files changed, 121 insertions, 51 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 466e0a6..4b31b49 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,16 @@
+2010-02-22 Alan Modra <amodra@gmail.com>
+
+ PR ld/11304
+ * ldlang.c (exp_init_os): Delete forward declaration.
+ (init_os): Don't check for bfd_section already created and don't
+ init addr_tree and load_base expressions here.
+ (map_input_to_output_sections): Only map input to output sections
+ and set constraints here, and as an exception, create output
+ sections which have their address set. Move all the other code to..
+ (create_other_output_sections): ..here. New function. Handle init
+ of addr_tree and load_base here too.
+ (lang_process): Call create_other_output_sections.
+
2010-02-19 Alan Modra <amodra@gmail.com>
* Makefile.am (eelf32_i960.c): Depend on ELF_GEN_DEPS, not ELF_DEPS.
diff --git a/ld/ldlang.c b/ld/ldlang.c
index ce5a11c..18ec6a4 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -68,7 +68,6 @@ 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
@@ -2048,12 +2047,8 @@ 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);
@@ -2078,14 +2073,6 @@ init_os (lang_output_section_statement_type *s, asection *isec,
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;
@@ -3430,10 +3417,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:
@@ -3445,29 +3432,23 @@ map_input_to_output_sections
os);
break;
case lang_output_section_statement_enum:
- if (s->output_section_statement.constraint)
+ tos = &s->output_section_statement;
+ if (tos->constraint != 0)
{
- if (s->output_section_statement.constraint != ONLY_IF_RW
- && s->output_section_statement.constraint != ONLY_IF_RO)
+ if (tos->constraint != ONLY_IF_RW
+ && tos->constraint != ONLY_IF_RO)
break;
- 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->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.constraint = -1;
+ tos->constraint = -1;
break;
}
}
-
- map_input_to_output_sections (s->output_section_statement.children.head,
+ map_input_to_output_sections (tos->children.head,
target,
- &s->output_section_statement);
- break;
- case lang_output_statement_enum:
+ tos);
break;
case lang_target_statement_enum:
target = s->target_statement.target;
@@ -3477,19 +3458,102 @@ 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;
- if (os->bfd_section == NULL)
- init_os (os, NULL, flags);
- else
- os->bfd_section->flags |= flags;
+ os->bfd_section->flags |= flags;
break;
case lang_input_section_enum:
break;
@@ -3510,25 +3574,14 @@ map_input_to_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)
{
- lang_output_section_statement_type *aos
- = (lang_output_section_statement_lookup
- (s->address_statement.section_name, 0, TRUE));
+ const char *name = s->address_statement.section_name;
- if (aos->bfd_section == NULL)
- init_os (aos, NULL, 0);
- aos->addr_tree = s->address_statement.address;
+ tos = lang_output_section_find (name);
+ if (tos->bfd_section == NULL)
+ init_os (tos, NULL, 0);
}
break;
case lang_insert_statement_enum:
@@ -6347,6 +6400,10 @@ 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;