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.
This commit is contained in:
Alan Modra 2020-11-24 23:41:31 +10:30
parent 6595cf3ce8
commit 21401fc7bf
3 changed files with 45 additions and 42 deletions

View File

@ -1,3 +1,14 @@
2020-11-25 Alan Modra <amodra@gmail.com>
* 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 <hongjiu.lu@intel.com> 2020-11-24 H.J. Lu <hongjiu.lu@intel.com>
PR gold/26939 PR gold/26939

View File

@ -1305,7 +1305,7 @@ lang_init (void)
first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum, first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
NULL); NULL);
abs_output_section = 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; 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. /* Find or create an output_section_statement with the given NAME.
If CONSTRAINT is non-zero match one with that constraint, otherwise If CONSTRAINT is non-zero match one with that constraint, otherwise
match any non-negative constraint. If CREATE, always make a match any non-negative constraint. If CREATE is 0 return NULL when
new output_section_statement for SPECIAL CONSTRAINT. */ 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_type *
lang_output_section_statement_lookup (const char *name, lang_output_section_statement_lookup (const char *name,
int constraint, int constraint,
bfd_boolean create) int create)
{ {
struct out_section_hash_entry *entry; struct out_section_hash_entry *entry;
entry = ((struct out_section_hash_entry *) entry = ((struct out_section_hash_entry *)
bfd_hash_lookup (&output_section_statement_table, name, bfd_hash_lookup (&output_section_statement_table, name,
create, FALSE)); create != 0, FALSE));
if (entry == NULL) if (entry == NULL)
{ {
if (create) if (create)
@ -1491,23 +1493,19 @@ lang_output_section_statement_lookup (const char *name,
struct out_section_hash_entry *last_ent; struct out_section_hash_entry *last_ent;
name = entry->s.output_section_statement.name; name = entry->s.output_section_statement.name;
if (create && constraint == SPECIAL) do
/* Not traversing to the end reverses the order of the second {
and subsequent SPECIAL sections in the hash table chain, if (create != 2
but that shouldn't matter. */ && !(create && constraint == SPECIAL)
last_ent = entry; && (constraint == entry->s.output_section_statement.constraint
else || (constraint == 0
do && entry->s.output_section_statement.constraint >= 0)))
{ return &entry->s.output_section_statement;
if (constraint == entry->s.output_section_statement.constraint last_ent = entry;
|| (constraint == 0 entry = (struct out_section_hash_entry *) entry->root.next;
&& entry->s.output_section_statement.constraint >= 0)) }
return &entry->s.output_section_statement; while (entry != NULL
last_ent = entry; && name == entry->s.output_section_statement.name);
entry = (struct out_section_hash_entry *) entry->root.next;
}
while (entry != NULL
&& name == entry->s.output_section_statement.name);
if (!create) if (!create)
return NULL; return NULL;
@ -4175,22 +4173,18 @@ map_input_to_output_sections
break; break;
case lang_output_section_statement_enum: case lang_output_section_statement_enum:
tos = &s->output_section_statement; 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; tos->all_input_readonly = TRUE;
check_input_sections (tos->children.head, tos); check_input_sections (tos->children.head, tos);
if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO)) if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO))
{ tos->constraint = -1;
tos->constraint = -1;
break;
}
} }
map_input_to_output_sections (tos->children.head, if (tos->constraint >= 0)
target, map_input_to_output_sections (tos->children.head,
tos); target,
tos);
break; break;
case lang_output_statement_enum: case lang_output_statement_enum:
break; break;
@ -4270,7 +4264,7 @@ map_input_to_output_sections
place them in amongst other sections then the address place them in amongst other sections then the address
will affect following script sections, which is will affect following script sections, which is
likely to surprise naive users. */ 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; tos->addr_tree = s->address_statement.address;
if (tos->bfd_section == NULL) if (tos->bfd_section == NULL)
init_os (tos, 0); init_os (tos, 0);
@ -7206,8 +7200,7 @@ ldlang_place_orphan (asection *s)
if (config.orphan_handling == orphan_handling_discard) if (config.orphan_handling == orphan_handling_discard)
{ {
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, 1);
TRUE);
if (os->addr_tree == NULL if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info) && (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
@ -7230,7 +7223,7 @@ ldlang_place_orphan (asection *s)
os = ldemul_place_orphan (s, name, constraint); os = ldemul_place_orphan (s, name, constraint);
if (os == NULL) 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 if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info) && (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)) || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
@ -7277,8 +7270,7 @@ lang_place_orphans (void)
{ {
if (default_common_section == NULL) if (default_common_section == NULL)
default_common_section default_common_section
= lang_output_section_statement_lookup (".bss", 0, = lang_output_section_statement_lookup (".bss", 0, 1);
TRUE);
lang_add_section (&default_common_section->children, s, lang_add_section (&default_common_section->children, s,
NULL, default_common_section); 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; lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (output_section_statement_name, os = lang_output_section_statement_lookup (output_section_statement_name,
constraint, TRUE); constraint, 2);
current_section = os; current_section = os;
if (os->addr_tree == NULL) if (os->addr_tree == NULL)

View File

@ -586,7 +586,7 @@ extern asection *section_for_dot
statement = statement->next) statement = statement->next)
#define lang_output_section_find(NAME) \ #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 extern void lang_process
(void); (void);
@ -605,7 +605,7 @@ extern void lang_add_keepsyms_file
extern lang_output_section_statement_type *lang_output_section_get extern lang_output_section_statement_type *lang_output_section_get
(const asection *); (const asection *);
extern lang_output_section_statement_type *lang_output_section_statement_lookup 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 extern lang_output_section_statement_type *next_matching_output_section_statement
(lang_output_section_statement_type *, int); (lang_output_section_statement_type *, int);
extern void ldlang_add_undef extern void ldlang_add_undef