From 8a99a385a72553a657a1238d310f94bafad182be Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 4 Oct 2008 06:08:59 +0000 Subject: [PATCH] * ldemul.c (ldemul_place_orphan): Add "constraint" param. * ldemul.h (ldemul_place_orphan): Update prototype. (struct ld_emulation_xfer_struct ): 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. --- ld/ChangeLog | 24 ++++++++++++++++ ld/emultempl/beos.em | 6 ++-- ld/emultempl/elf32.em | 14 ++++++---- ld/emultempl/mmo.em | 8 +++--- ld/emultempl/pe.em | 12 ++++---- ld/emultempl/pep.em | 12 ++++---- ld/emultempl/spuelf.em | 2 +- ld/ldemul.c | 4 +-- ld/ldemul.h | 4 +-- ld/ldlang.c | 63 +++++++++++++++++++++--------------------- ld/ldlang.h | 4 +-- 11 files changed, 92 insertions(+), 61 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index deeec540ba5..fc8345f84a8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,27 @@ +2008-10-04 Alan Modra + + PR 6931 + * ldemul.c (ldemul_place_orphan): Add "constraint" param. + * ldemul.h (ldemul_place_orphan): Update prototype. + (struct ld_emulation_xfer_struct ): 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 PR 6931 diff --git a/ld/emultempl/beos.em b/ld/emultempl/beos.em index 997f3a63cec..2777be86ac9 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 65ad4f13461..7eb4e28a467 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -62,7 +62,8 @@ fragment <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 8b02fd64228..4ff9846ed12 100644 --- a/ld/emultempl/mmo.em +++ b/ld/emultempl/mmo.em @@ -47,7 +47,9 @@ fragment <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 89c521d9e9e..b01425704f1 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 4afac022b6d..386c98f99aa 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 bc2f6b548fc..fe248af6a46 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 68e1de26210..567e8ac2cd4 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 6c95a9d9a16..65612583a78 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 44fb136d84b..29084490e7b 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 8b652a8d785..fd0465ea1ab 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 -- 2.30.2