diff options
-rw-r--r-- | ld/ChangeLog | 24 | ||||
-rw-r--r-- | ld/emultempl/beos.em | 6 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 14 | ||||
-rw-r--r-- | ld/emultempl/mmo.em | 8 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 12 | ||||
-rw-r--r-- | ld/emultempl/pep.em | 12 | ||||
-rw-r--r-- | ld/emultempl/spuelf.em | 2 | ||||
-rw-r--r-- | ld/ldemul.c | 4 | ||||
-rw-r--r-- | ld/ldemul.h | 4 | ||||
-rw-r--r-- | ld/ldlang.c | 63 | ||||
-rw-r--r-- | ld/ldlang.h | 4 |
11 files changed, 92 insertions, 61 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index deeec54..fc8345f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -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> PR 6931 diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em index 997f3a6..2777be8 100644 --- a/ld/emultempl/beos.em +++ b/ld/emultempl/beos.em @@ -665,7 +665,9 @@ gld_${EMULATION_NAME}_before_allocation (void) which are not mentioned in the linker script. */ 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; lang_output_section_statement_type *os; @@ -694,7 +696,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname) output_secname = xstrdup (secname); ps = strchr (output_secname + 1, '\$'); *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 linker script to explicitly mention "*(.foo\$)". diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 65ad4f1..7eb4e28 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -62,7 +62,8 @@ fragment <<EOF static void gld${EMULATION_NAME}_before_parse (void); static void gld${EMULATION_NAME}_after_open (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); EOF @@ -1635,7 +1636,9 @@ output_rel_find (asection *sec, int isdyn) sections in the right segment. */ 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[] = { @@ -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. */ - os = lang_output_section_find (secname); - - if (os != NULL + if (constraint == 0 + && (os = lang_output_section_find (secname)) != NULL && os->bfd_section != NULL && (os->bfd_section->flags == 0 || (_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; } - lang_insert_orphan (s, secname, after, place, NULL, NULL); + lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL); return TRUE; } diff --git a/ld/emultempl/mmo.em b/ld/emultempl/mmo.em index 8b02fd6..4ff9846 100644 --- a/ld/emultempl/mmo.em +++ b/ld/emultempl/mmo.em @@ -47,7 +47,9 @@ fragment <<EOF from elf32.em. */ 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 = { @@ -56,7 +58,6 @@ mmo_place_orphan (asection *s) 0, 0, 0, 0 }; struct orphan_save *place; - const char *secname; lang_output_section_statement_type *after; lang_output_section_statement_type *os; @@ -66,7 +67,6 @@ mmo_place_orphan (asection *s) return FALSE; /* Only care for sections we're going to load. */ - secname = s->name; os = lang_output_section_find (secname); /* 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 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 (might happen with a peculiar linker script such as in "map diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 89c521d..b014257 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1613,7 +1613,9 @@ gld_${EMULATION_NAME}_finish (void) sort_sections. */ 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; char *dollar = NULL; @@ -1631,11 +1633,10 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname) secname = newname; } - os = lang_output_section_find (secname); - 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->flags == 0 || ((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. */ 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); } { diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 4afac02..386c98f 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1372,7 +1372,9 @@ gld_${EMULATION_NAME}_finish (void) sort_sections. */ 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; char *dollar = NULL; @@ -1390,11 +1392,10 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname) secname = newname; } - os = lang_output_section_find (secname); - 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->flags == 0 || ((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. */ 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); } { diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em index bc2f6b5..fe248af 100644 --- a/ld/emultempl/spuelf.em +++ b/ld/emultempl/spuelf.em @@ -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); 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) { lang_statement_list_type add; diff --git a/ld/ldemul.c b/ld/ldemul.c index 68e1de2..567e8ac 100644 --- a/ld/ldemul.c +++ b/ld/ldemul.c @@ -120,10 +120,10 @@ ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search, } 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) - return (*ld_emulation->place_orphan) (s, name); + return (*ld_emulation->place_orphan) (s, name, constraint); return FALSE; } diff --git a/ld/ldemul.h b/ld/ldemul.h index 6c95a9d..6561258 100644 --- a/ld/ldemul.h +++ b/ld/ldemul.h @@ -59,7 +59,7 @@ extern void ldemul_set_symbols extern void ldemul_create_output_section_statements (void); extern bfd_boolean ldemul_place_orphan - (asection *, const char *); + (asection *, const char *, int); extern bfd_boolean ldemul_parse_args (int, char **); 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 which case the default action will always be taken. */ bfd_boolean (*place_orphan) - (asection *, const char *); + (asection *, const char *, int); /* Run after assigning parsing with the args, but before reading the script. Used to initialize symbols used in the script. */ diff --git a/ld/ldlang.c b/ld/ldlang.c index 44fb136..2908449 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -193,7 +193,7 @@ input_statement_is_archive_path (const char *file_spec, char *sep, return match; } -bfd_boolean +static bfd_boolean unique_section_p (const asection *sec) { struct unique_sections *unam; @@ -1278,19 +1278,25 @@ lang_output_section_statement_lookup (const char *const name, struct out_section_hash_entry *last_ent; unsigned long hash = entry->root.hash; - do - { - if (entry->s.output_section_statement.constraint >= 0 - && (constraint == 0 - || (constraint == entry->s.output_section_statement.constraint - && constraint != SPECIAL))) - 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 && constraint == SPECIAL) + /* Not traversing to the end reverses the order of the second + and subsequent SPECIAL sections in the hash table chain, + but that shouldn't matter. */ + last_ent = entry; + else + do + { + if (entry->s.output_section_statement.constraint >= 0 + && (constraint == 0 + || (constraint + == entry->s.output_section_statement.constraint))) + 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) return NULL; @@ -1556,6 +1562,7 @@ insert_os_after (lang_output_section_statement_type *after) lang_output_section_statement_type * lang_insert_orphan (asection *s, const char *secname, + int constraint, lang_output_section_statement_type *after, struct orphan_save *place, etree_type *address, @@ -1611,7 +1618,7 @@ lang_insert_orphan (asection *s, os_tail = ((lang_output_section_statement_type **) lang_output_section_statement.tail); os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL, - NULL, 0); + NULL, constraint); if (add_child == NULL) 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) 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) - s->bfd_section = bfd_make_section_with_flags (link_info.output_bfd, - s->name, flags); + s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd, + s->name, flags); if (s->bfd_section == NULL) { einfo (_("%P%F: output format %s cannot represent section called %s\n"), @@ -5655,23 +5663,16 @@ lang_place_orphans (void) else { const char *name = s->name; + int constraint = 0; - if ((config.unique_orphan_sections - || unique_section_p (s)) - && 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 (config.unique_orphan_sections || unique_section_p (s)) + constraint = SPECIAL; - if (!ldemul_place_orphan (s, name)) + if (!ldemul_place_orphan (s, name, constraint)) { lang_output_section_statement_type *os; - os = lang_output_section_statement_lookup (name, 0, + os = lang_output_section_statement_lookup (name, + constraint, TRUE); lang_add_section (&os->children, s, os); } diff --git a/ld/ldlang.h b/ld/ldlang.h index 8b652a8..fd0465e 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -536,7 +536,7 @@ extern lang_output_section_statement_type *lang_output_section_find_by_flags (const asection *, lang_output_section_statement_type **, lang_match_sec_type_func); 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 *); extern lang_input_statement_type *lang_add_input_file (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_cpp_typeinfo (void); extern void lang_append_dynamic_list_cpp_new (void); -bfd_boolean unique_section_p - (const asection *); extern void lang_add_unique (const char *); extern const char *lang_get_output_target |