* ldemul.c (ldemul_place_orphan): Add "constraint" param.

* ldemul.h (ldemul_place_orphan): Update prototype.
	(struct ld_emulation_xfer_struct <place_orphan>): Likewise add param.
	* ldlang.c (unique_section_p): Make static.
	(lang_output_section_statement_lookup): Optimise creation of SPECIAL
	sections.
	(lang_insert_orphan): Add "constraint" param.  Pass to
	lang_enter_output_section_statement.
	(init_os): Don't use an existing bfd section for SPECIAL sections.
	(lang_place_orphans): Don't rename unique output sections, instead
	mark their output section statements SPECIAL.
	* ldlang.h (lang_insert_orphan): Update prototype.
	(unique_section_p): Delete.
	* emultempl/beos.em (place_orphan): Add "constraint" param.
	* emultempl/elf32.em (place_orphan): Likewise.  Don't match existing
	output sections if set.
	* emultempl/pe.em (place_orphan): Likewise.
	* emultempl/pep.em (place_orphan): Likewise.
	* emultempl/mmo.em (mmo_place_orphan): Update.
	* emultempl/spuelf.em (spu_place_special_section): Update.
This commit is contained in:
Alan Modra 2008-10-04 06:08:59 +00:00
parent 2605c5df34
commit 8a99a385a7
11 changed files with 92 additions and 61 deletions

View File

@ -1,3 +1,27 @@
2008-10-04 Alan Modra <amodra@bigpond.net.au>
PR 6931
* ldemul.c (ldemul_place_orphan): Add "constraint" param.
* ldemul.h (ldemul_place_orphan): Update prototype.
(struct ld_emulation_xfer_struct <place_orphan>): Likewise add param.
* ldlang.c (unique_section_p): Make static.
(lang_output_section_statement_lookup): Optimise creation of SPECIAL
sections.
(lang_insert_orphan): Add "constraint" param. Pass to
lang_enter_output_section_statement.
(init_os): Don't use an existing bfd section for SPECIAL sections.
(lang_place_orphans): Don't rename unique output sections, instead
mark their output section statements SPECIAL.
* ldlang.h (lang_insert_orphan): Update prototype.
(unique_section_p): Delete.
* emultempl/beos.em (place_orphan): Add "constraint" param.
* emultempl/elf32.em (place_orphan): Likewise. Don't match existing
output sections if set.
* emultempl/pe.em (place_orphan): Likewise.
* emultempl/pep.em (place_orphan): Likewise.
* emultempl/mmo.em (mmo_place_orphan): Update.
* emultempl/spuelf.em (spu_place_special_section): Update.
2008-10-03 Alan Modra <amodra@bigpond.net.au> 2008-10-03 Alan Modra <amodra@bigpond.net.au>
PR 6931 PR 6931

View File

@ -665,7 +665,9 @@ gld_${EMULATION_NAME}_before_allocation (void)
which are not mentioned in the linker script. */ which are not mentioned in the linker script. */
static bfd_boolean static bfd_boolean
gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname) gld${EMULATION_NAME}_place_orphan (asection *s,
const char *secname,
int constraint)
{ {
char *output_secname, *ps; char *output_secname, *ps;
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
@ -694,7 +696,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
output_secname = xstrdup (secname); output_secname = xstrdup (secname);
ps = strchr (output_secname + 1, '\$'); ps = strchr (output_secname + 1, '\$');
*ps = 0; *ps = 0;
os = lang_output_section_statement_lookup (output_secname, 0, TRUE); os = lang_output_section_statement_lookup (output_secname, constraint, TRUE);
/* Find the '\$' wild statement for this section. We currently require the /* Find the '\$' wild statement for this section. We currently require the
linker script to explicitly mention "*(.foo\$)". linker script to explicitly mention "*(.foo\$)".

View File

@ -62,7 +62,8 @@ fragment <<EOF
static void gld${EMULATION_NAME}_before_parse (void); static void gld${EMULATION_NAME}_before_parse (void);
static void gld${EMULATION_NAME}_after_open (void); static void gld${EMULATION_NAME}_after_open (void);
static void gld${EMULATION_NAME}_before_allocation (void); static void gld${EMULATION_NAME}_before_allocation (void);
static bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *, const char *); static bfd_boolean gld${EMULATION_NAME}_place_orphan
(asection *, const char *, int);
static void gld${EMULATION_NAME}_finish (void); static void gld${EMULATION_NAME}_finish (void);
EOF EOF
@ -1635,7 +1636,9 @@ output_rel_find (asection *sec, int isdyn)
sections in the right segment. */ sections in the right segment. */
static bfd_boolean static bfd_boolean
gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname) gld${EMULATION_NAME}_place_orphan (asection *s,
const char *secname,
int constraint)
{ {
static struct orphan_save hold[] = static struct orphan_save hold[] =
{ {
@ -1705,9 +1708,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
} }
/* Look through the script to see where to place this section. */ /* Look through the script to see where to place this section. */
os = lang_output_section_find (secname); if (constraint == 0
&& (os = lang_output_section_find (secname)) != NULL
if (os != NULL
&& os->bfd_section != NULL && os->bfd_section != NULL
&& (os->bfd_section->flags == 0 && (os->bfd_section->flags == 0
|| (_bfd_elf_match_sections_by_type (link_info.output_bfd, || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
@ -1796,7 +1798,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
after = &lang_output_section_statement.head->output_section_statement; after = &lang_output_section_statement.head->output_section_statement;
} }
lang_insert_orphan (s, secname, after, place, NULL, NULL); lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
return TRUE; return TRUE;
} }

View File

@ -47,7 +47,9 @@ fragment <<EOF
from elf32.em. */ from elf32.em. */
static bfd_boolean static bfd_boolean
mmo_place_orphan (asection *s) mmo_place_orphan (asection *s,
const char *secname,
int constraint ATTRIBUTE_UNUSED)
{ {
static struct orphan_save hold_text = static struct orphan_save hold_text =
{ {
@ -56,7 +58,6 @@ mmo_place_orphan (asection *s)
0, 0, 0, 0 0, 0, 0, 0
}; };
struct orphan_save *place; struct orphan_save *place;
const char *secname;
lang_output_section_statement_type *after; lang_output_section_statement_type *after;
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
@ -66,7 +67,6 @@ mmo_place_orphan (asection *s)
return FALSE; return FALSE;
/* Only care for sections we're going to load. */ /* Only care for sections we're going to load. */
secname = s->name;
os = lang_output_section_find (secname); os = lang_output_section_find (secname);
/* We have an output section by this name. Place the section inside it /* We have an output section by this name. Place the section inside it
@ -93,7 +93,7 @@ mmo_place_orphan (asection *s)
/* If there's an output section by this name, we'll use it, regardless /* If there's an output section by this name, we'll use it, regardless
of section flags, in contrast to what's done in elf32.em. */ of section flags, in contrast to what's done in elf32.em. */
os = lang_insert_orphan (s, secname, after, place, NULL, NULL); os = lang_insert_orphan (s, secname, 0, after, place, NULL, NULL);
/* We need an output section for .text as a root, so if there was none /* We need an output section for .text as a root, so if there was none
(might happen with a peculiar linker script such as in "map (might happen with a peculiar linker script such as in "map

View File

@ -1613,7 +1613,9 @@ gld_${EMULATION_NAME}_finish (void)
sort_sections. */ sort_sections. */
static bfd_boolean static bfd_boolean
gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname) gld_${EMULATION_NAME}_place_orphan (asection *s,
const char *secname,
int constraint)
{ {
const char *orig_secname = secname; const char *orig_secname = secname;
char *dollar = NULL; char *dollar = NULL;
@ -1631,11 +1633,10 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
secname = newname; secname = newname;
} }
os = lang_output_section_find (secname);
lang_list_init (&add_child); lang_list_init (&add_child);
if (os != NULL if (constraint == 0
&& (os = lang_output_section_find (secname)) != NULL
&& os->bfd_section != NULL && os->bfd_section != NULL
&& (os->bfd_section->flags == 0 && (os->bfd_section->flags == 0
|| ((s->flags ^ os->bfd_section->flags) || ((s->flags ^ os->bfd_section->flags)
@ -1721,7 +1722,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
/* All sections in an executable must be aligned to a page boundary. */ /* All sections in an executable must be aligned to a page boundary. */
address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__")); address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
os = lang_insert_orphan (s, secname, after, place, address, &add_child); os = lang_insert_orphan (s, secname, constraint, after, place, address,
&add_child);
} }
{ {

View File

@ -1372,7 +1372,9 @@ gld_${EMULATION_NAME}_finish (void)
sort_sections. */ sort_sections. */
static bfd_boolean static bfd_boolean
gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname) gld_${EMULATION_NAME}_place_orphan (asection *s,
const char *secname,
int constraint)
{ {
const char *orig_secname = secname; const char *orig_secname = secname;
char *dollar = NULL; char *dollar = NULL;
@ -1390,11 +1392,10 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
secname = newname; secname = newname;
} }
os = lang_output_section_find (secname);
lang_list_init (&add_child); lang_list_init (&add_child);
if (os != NULL if (constraint == 0
&& (os = lang_output_section_find (secname)) != NULL
&& os->bfd_section != NULL && os->bfd_section != NULL
&& (os->bfd_section->flags == 0 && (os->bfd_section->flags == 0
|| ((s->flags ^ os->bfd_section->flags) || ((s->flags ^ os->bfd_section->flags)
@ -1480,7 +1481,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
/* All sections in an executable must be aligned to a page boundary. */ /* All sections in an executable must be aligned to a page boundary. */
address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__")); address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
os = lang_insert_orphan (s, secname, after, place, address, &add_child); os = lang_insert_orphan (s, secname, constraint, after, place, address,
&add_child);
} }
{ {

View File

@ -114,7 +114,7 @@ spu_place_special_section (asection *s, asection *o, const char *output_name)
os = lang_output_section_find (o != NULL ? o->name : output_name); os = lang_output_section_find (o != NULL ? o->name : output_name);
if (os == NULL) if (os == NULL)
gld${EMULATION_NAME}_place_orphan (s, output_name); gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
else if (o != NULL && os->children.head != NULL) else if (o != NULL && os->children.head != NULL)
{ {
lang_statement_list_type add; lang_statement_list_type add;

View File

@ -120,10 +120,10 @@ ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
} }
bfd_boolean bfd_boolean
ldemul_place_orphan (asection *s, const char *name) ldemul_place_orphan (asection *s, const char *name, int constraint)
{ {
if (ld_emulation->place_orphan) if (ld_emulation->place_orphan)
return (*ld_emulation->place_orphan) (s, name); return (*ld_emulation->place_orphan) (s, name, constraint);
return FALSE; return FALSE;
} }

View File

@ -59,7 +59,7 @@ extern void ldemul_set_symbols
extern void ldemul_create_output_section_statements extern void ldemul_create_output_section_statements
(void); (void);
extern bfd_boolean ldemul_place_orphan extern bfd_boolean ldemul_place_orphan
(asection *, const char *); (asection *, const char *, int);
extern bfd_boolean ldemul_parse_args extern bfd_boolean ldemul_parse_args
(int, char **); (int, char **);
extern void ldemul_add_options extern void ldemul_add_options
@ -152,7 +152,7 @@ typedef struct ld_emulation_xfer_struct {
the default action should be taken. This field may be NULL, in the default action should be taken. This field may be NULL, in
which case the default action will always be taken. */ which case the default action will always be taken. */
bfd_boolean (*place_orphan) bfd_boolean (*place_orphan)
(asection *, const char *); (asection *, const char *, int);
/* Run after assigning parsing with the args, but before /* Run after assigning parsing with the args, but before
reading the script. Used to initialize symbols used in the script. */ reading the script. Used to initialize symbols used in the script. */

View File

@ -193,7 +193,7 @@ input_statement_is_archive_path (const char *file_spec, char *sep,
return match; return match;
} }
bfd_boolean static bfd_boolean
unique_section_p (const asection *sec) unique_section_p (const asection *sec)
{ {
struct unique_sections *unam; struct unique_sections *unam;
@ -1278,19 +1278,25 @@ lang_output_section_statement_lookup (const char *const name,
struct out_section_hash_entry *last_ent; struct out_section_hash_entry *last_ent;
unsigned long hash = entry->root.hash; unsigned long hash = entry->root.hash;
do if (create && constraint == SPECIAL)
{ /* Not traversing to the end reverses the order of the second
if (entry->s.output_section_statement.constraint >= 0 and subsequent SPECIAL sections in the hash table chain,
&& (constraint == 0 but that shouldn't matter. */
|| (constraint == entry->s.output_section_statement.constraint last_ent = entry;
&& constraint != SPECIAL))) else
return &entry->s.output_section_statement; do
last_ent = entry; {
entry = (struct out_section_hash_entry *) entry->root.next; if (entry->s.output_section_statement.constraint >= 0
} && (constraint == 0
while (entry != NULL || (constraint
&& entry->root.hash == hash == entry->s.output_section_statement.constraint)))
&& strcmp (name, entry->s.output_section_statement.name) == 0); return &entry->s.output_section_statement;
last_ent = entry;
entry = (struct out_section_hash_entry *) entry->root.next;
}
while (entry != NULL
&& entry->root.hash == hash
&& strcmp (name, entry->s.output_section_statement.name) == 0);
if (!create) if (!create)
return NULL; return NULL;
@ -1556,6 +1562,7 @@ insert_os_after (lang_output_section_statement_type *after)
lang_output_section_statement_type * lang_output_section_statement_type *
lang_insert_orphan (asection *s, lang_insert_orphan (asection *s,
const char *secname, const char *secname,
int constraint,
lang_output_section_statement_type *after, lang_output_section_statement_type *after,
struct orphan_save *place, struct orphan_save *place,
etree_type *address, etree_type *address,
@ -1611,7 +1618,7 @@ lang_insert_orphan (asection *s,
os_tail = ((lang_output_section_statement_type **) os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail); lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL, os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
NULL, 0); NULL, constraint);
if (add_child == NULL) if (add_child == NULL)
add_child = &os->children; add_child = &os->children;
@ -1914,10 +1921,11 @@ init_os (lang_output_section_statement_type *s, asection *isec,
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0) if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME); einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name); if (s->constraint != SPECIAL)
s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
if (s->bfd_section == NULL) if (s->bfd_section == NULL)
s->bfd_section = bfd_make_section_with_flags (link_info.output_bfd, s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
s->name, flags); s->name, flags);
if (s->bfd_section == NULL) if (s->bfd_section == NULL)
{ {
einfo (_("%P%F: output format %s cannot represent section called %s\n"), einfo (_("%P%F: output format %s cannot represent section called %s\n"),
@ -5655,23 +5663,16 @@ lang_place_orphans (void)
else else
{ {
const char *name = s->name; const char *name = s->name;
int constraint = 0;
if ((config.unique_orphan_sections if (config.unique_orphan_sections || unique_section_p (s))
|| unique_section_p (s)) constraint = SPECIAL;
&& bfd_get_section_by_name (link_info.output_bfd,
name) != NULL)
{
static int count = 1;
name = bfd_get_unique_section_name (link_info.output_bfd,
name, &count);
if (name == NULL)
einfo ("%F%P: place_orphan failed: %E\n");
}
if (!ldemul_place_orphan (s, name)) if (!ldemul_place_orphan (s, name, constraint))
{ {
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (name, 0, os = lang_output_section_statement_lookup (name,
constraint,
TRUE); TRUE);
lang_add_section (&os->children, s, os); lang_add_section (&os->children, s, os);
} }

View File

@ -536,7 +536,7 @@ extern lang_output_section_statement_type *lang_output_section_find_by_flags
(const asection *, lang_output_section_statement_type **, (const asection *, lang_output_section_statement_type **,
lang_match_sec_type_func); lang_match_sec_type_func);
extern lang_output_section_statement_type *lang_insert_orphan extern lang_output_section_statement_type *lang_insert_orphan
(asection *, const char *, lang_output_section_statement_type *, (asection *, const char *, int, lang_output_section_statement_type *,
struct orphan_save *, etree_type *, lang_statement_list_type *); struct orphan_save *, etree_type *, lang_statement_list_type *);
extern lang_input_statement_type *lang_add_input_file extern lang_input_statement_type *lang_add_input_file
(const char *, lang_input_file_enum_type, const char *); (const char *, lang_input_file_enum_type, const char *);
@ -604,8 +604,6 @@ extern void lang_register_vers_node
extern void lang_append_dynamic_list (struct bfd_elf_version_expr *); extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
extern void lang_append_dynamic_list_cpp_typeinfo (void); extern void lang_append_dynamic_list_cpp_typeinfo (void);
extern void lang_append_dynamic_list_cpp_new (void); extern void lang_append_dynamic_list_cpp_new (void);
bfd_boolean unique_section_p
(const asection *);
extern void lang_add_unique extern void lang_add_unique
(const char *); (const char *);
extern const char *lang_get_output_target extern const char *lang_get_output_target