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.
This commit is contained in:
Alan Modra 2010-02-22 12:09:59 +00:00
parent 8a59fff3dd
commit c380a809de
2 changed files with 121 additions and 51 deletions

View File

@ -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.

View File

@ -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;