From 21401fc7bf67dbf73f4a3eda4bcfc58fa4211584 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 24 Nov 2020 23:41:31 +1030 Subject: Duplicate output sections in scripts Previously, ld merged duplicate output sections if such existed in scripts, except for those with a constraint of SPECIAL. This makes scripts with duplicate output section statements create duplicate output sections in the linker output file. * ldlang.c (lang_output_section_statement_lookup): Change "create" parameter to a tristate, if 2 then always create a new output section statement. Update all callers, with lang_enter_output_section_statement using "2". (map_input_to_output_sections): Don't ignore SPECIAL constraint here. * ldlang.h (lang_output_section_statement_type): Update prototype. (lang_output_section_find): Update. --- ld/ChangeLog | 11 ++++++++++ ld/ldlang.c | 72 +++++++++++++++++++++++++++--------------------------------- ld/ldlang.h | 4 ++-- 3 files changed, 45 insertions(+), 42 deletions(-) (limited to 'ld') diff --git a/ld/ChangeLog b/ld/ChangeLog index 0faa03a..d7280ef 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +2020-11-25 Alan Modra + + * ldlang.c (lang_output_section_statement_lookup): Change "create" + parameter to a tristate, if 2 then always create a new output + section statement. Update all callers, with + lang_enter_output_section_statement using "2". + (map_input_to_output_sections): Don't ignore SPECIAL constraint + here. + * ldlang.h (lang_output_section_statement_type): Update prototype. + (lang_output_section_find): Update. + 2020-11-24 H.J. Lu PR gold/26939 diff --git a/ld/ldlang.c b/ld/ldlang.c index b70937a..41000da 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1305,7 +1305,7 @@ lang_init (void) first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum, NULL); abs_output_section = - lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE); + lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, 1); abs_output_section->bfd_section = bfd_abs_section_ptr; @@ -1464,19 +1464,21 @@ lang_output_section_get (const asection *output_section) /* Find or create an output_section_statement with the given NAME. If CONSTRAINT is non-zero match one with that constraint, otherwise - match any non-negative constraint. If CREATE, always make a - new output_section_statement for SPECIAL CONSTRAINT. */ + match any non-negative constraint. If CREATE is 0 return NULL when + no match exists. If CREATE is 1, create an output_section_statement + when no match exists or if CONSTRAINT is SPECIAL. If CREATE is 2, + always make a new output_section_statement. */ lang_output_section_statement_type * lang_output_section_statement_lookup (const char *name, int constraint, - bfd_boolean create) + int create) { struct out_section_hash_entry *entry; entry = ((struct out_section_hash_entry *) bfd_hash_lookup (&output_section_statement_table, name, - create, FALSE)); + create != 0, FALSE)); if (entry == NULL) { if (create) @@ -1491,23 +1493,19 @@ lang_output_section_statement_lookup (const char *name, struct out_section_hash_entry *last_ent; name = entry->s.output_section_statement.name; - 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 (constraint == entry->s.output_section_statement.constraint - || (constraint == 0 - && entry->s.output_section_statement.constraint >= 0)) - return &entry->s.output_section_statement; - last_ent = entry; - entry = (struct out_section_hash_entry *) entry->root.next; - } - while (entry != NULL - && name == entry->s.output_section_statement.name); + do + { + if (create != 2 + && !(create && constraint == SPECIAL) + && (constraint == entry->s.output_section_statement.constraint + || (constraint == 0 + && entry->s.output_section_statement.constraint >= 0))) + return &entry->s.output_section_statement; + last_ent = entry; + entry = (struct out_section_hash_entry *) entry->root.next; + } + while (entry != NULL + && name == entry->s.output_section_statement.name); if (!create) return NULL; @@ -4175,22 +4173,18 @@ map_input_to_output_sections break; case lang_output_section_statement_enum: tos = &s->output_section_statement; - if (tos->constraint != 0) + if (tos->constraint == ONLY_IF_RW + || tos->constraint == ONLY_IF_RO) { - if (tos->constraint != ONLY_IF_RW - && tos->constraint != ONLY_IF_RO) - break; tos->all_input_readonly = TRUE; check_input_sections (tos->children.head, tos); if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO)) - { - tos->constraint = -1; - break; - } + tos->constraint = -1; } - map_input_to_output_sections (tos->children.head, - target, - tos); + if (tos->constraint >= 0) + map_input_to_output_sections (tos->children.head, + target, + tos); break; case lang_output_statement_enum: break; @@ -4270,7 +4264,7 @@ map_input_to_output_sections 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 = lang_output_section_statement_lookup (name, 0, 1); tos->addr_tree = s->address_statement.address; if (tos->bfd_section == NULL) init_os (tos, 0); @@ -7206,8 +7200,7 @@ ldlang_place_orphan (asection *s) if (config.orphan_handling == orphan_handling_discard) { lang_output_section_statement_type *os; - os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, - TRUE); + os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, 1); if (os->addr_tree == NULL && (bfd_link_relocatable (&link_info) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) @@ -7230,7 +7223,7 @@ ldlang_place_orphan (asection *s) os = ldemul_place_orphan (s, name, constraint); if (os == NULL) { - os = lang_output_section_statement_lookup (name, constraint, TRUE); + os = lang_output_section_statement_lookup (name, constraint, 1); if (os->addr_tree == NULL && (bfd_link_relocatable (&link_info) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) @@ -7277,8 +7270,7 @@ lang_place_orphans (void) { if (default_common_section == NULL) default_common_section - = lang_output_section_statement_lookup (".bss", 0, - TRUE); + = lang_output_section_statement_lookup (".bss", 0, 1); lang_add_section (&default_common_section->children, s, NULL, default_common_section); } @@ -7420,7 +7412,7 @@ lang_enter_output_section_statement (const char *output_section_statement_name, lang_output_section_statement_type *os; os = lang_output_section_statement_lookup (output_section_statement_name, - constraint, TRUE); + constraint, 2); current_section = os; if (os->addr_tree == NULL) diff --git a/ld/ldlang.h b/ld/ldlang.h index 6675c57..0f1b607 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -586,7 +586,7 @@ extern asection *section_for_dot statement = statement->next) #define lang_output_section_find(NAME) \ - lang_output_section_statement_lookup (NAME, 0, FALSE) + lang_output_section_statement_lookup (NAME, 0, 0) extern void lang_process (void); @@ -605,7 +605,7 @@ extern void lang_add_keepsyms_file extern lang_output_section_statement_type *lang_output_section_get (const asection *); extern lang_output_section_statement_type *lang_output_section_statement_lookup - (const char *, int, bfd_boolean); + (const char *, int, int); extern lang_output_section_statement_type *next_matching_output_section_statement (lang_output_section_statement_type *, int); extern void ldlang_add_undef -- cgit v1.1