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>
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,
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)

View File

@ -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