elf: Allow mixed ordered/unordered inputs for non-relocatable link

For non-relocatable link with SHF_LINK_ORDER inputs, allow mixed indirect
and data inputs with ordered and unordered inputs:

1. Add pattern to bfd_section for the matching section name pattern in
linker script and update BFD_FAKE_SECTION.
2. Sort the consecutive bfd_indirect_link_order sections with the same
pattern to allow linker script to overdide input section order.
3. Place unordered sections before ordered sections.
4. Change the offsets of the indirect input sections only.

bfd/

	PR ld/26256
	* elflink.c (compare_link_order): Place unordered sections before
	ordered sections.
	(elf_fixup_link_order): Add a link info argument.  Allow mixed
	ordered and unordered input sections for non-relocatable link.
	Sort the consecutive bfd_indirect_link_order sections with the
	same pattern.  Change the offsets of the bfd_indirect_link_order
	sections only.
	(bfd_elf_final_link): Pass info to elf_fixup_link_order.
	* section.c (bfd_section): Add pattern.
	(BFD_FAKE_SECTION): Initialize pattern to NULL.
	* bfd-in2.h: Regenerated.

gas/

	PR ld/26256
	* config/obj-elf.c (obj_elf_change_section): Also filter out
	SHF_LINK_ORDER.

ld/

	PR ld/26256
	* ldlang.c (gc_section_callback): Set pattern.
	* testsuite/ld-elf/pr26256-1.s: New file.
	* testsuite/ld-elf/pr26256-1.t: Likewise.
	* testsuite/ld-elf/pr26256-1a.d: Likewise.
	* testsuite/ld-elf/pr26256-1b.d: Likewise.
	* testsuite/ld-elf/pr26256-2.s: Likewise.
	* testsuite/ld-elf/pr26256-2.t: Likewise.
	* testsuite/ld-elf/pr26256-2a.d: Likewise.
	* testsuite/ld-elf/pr26256-2b-alt.d: Likewise.
	* testsuite/ld-elf/pr26256-2b.d: Likewise.
	* testsuite/ld-elf/pr26256-3.s: Likewise.
	* testsuite/ld-elf/pr26256-3a.d: Likewise.
	* testsuite/ld-elf/pr26256-3a.t: Likewise.
	* testsuite/ld-elf/pr26256-3b.d: Likewise.
	* testsuite/ld-elf/pr26256-3b.t: Likewise.
This commit is contained in:
H.J. Lu 2021-01-04 12:37:49 -08:00
parent e4ad960a57
commit cd6d537c48
22 changed files with 353 additions and 24 deletions

View file

@ -1,3 +1,18 @@
2021-01-04 H.J. Lu <hongjiu.lu@intel.com>
PR ld/26256
* elflink.c (compare_link_order): Place unordered sections before
ordered sections.
(elf_fixup_link_order): Add a link info argument. Allow mixed
ordered and unordered input sections for non-relocatable link.
Sort the consecutive bfd_indirect_link_order sections with the
same pattern. Change the offsets of the bfd_indirect_link_order
sections only.
(bfd_elf_final_link): Pass info to elf_fixup_link_order.
* section.c (bfd_section): Add pattern.
(BFD_FAKE_SECTION): Initialize pattern to NULL.
* bfd-in2.h: Regenerated.
2021-01-04 Alexander Fedotov <alfedotov@gmail.com>
* elf32-arm.c (elf32_arm_print_private_bfd_data): Prefix hex value

View file

@ -1184,6 +1184,9 @@ typedef struct bfd_section
struct bfd_symbol *symbol;
struct bfd_symbol **symbol_ptr_ptr;
/* The matching section name pattern in linker script. */
const char *pattern;
/* Early in the link process, map_head and map_tail are used to build
a list of input sections attached to an output section. Later,
output sections use these fields for a list of bfd_link_order
@ -1377,8 +1380,8 @@ discarded_section (const asection *sec)
/* target_index, used_by_bfd, constructor_chain, owner, */ \
0, NULL, NULL, NULL, \
\
/* symbol, symbol_ptr_ptr, */ \
(struct bfd_symbol *) SYM, &SEC.symbol, \
/* symbol, symbol_ptr_ptr, pattern, */ \
(struct bfd_symbol *) SYM, &SEC.symbol, NULL, \
\
/* map_head, map_tail, already_assigned */ \
{ NULL }, { NULL }, NULL \

View file

@ -11869,8 +11869,21 @@ compare_link_order (const void *a, const void *b)
const struct bfd_link_order *blo = *(const struct bfd_link_order **) b;
asection *asec = elf_linked_to_section (alo->u.indirect.section);
asection *bsec = elf_linked_to_section (blo->u.indirect.section);
bfd_vma apos = asec->output_section->lma + asec->output_offset;
bfd_vma bpos = bsec->output_section->lma + bsec->output_offset;
bfd_vma apos, bpos;
/* Check if any sections are unordered. */
if (asec == NULL || bsec == NULL)
{
/* Place unordered sections before ordered sections. */
if (bsec != NULL)
return -1;
else if (asec != NULL)
return 1;
return 0;
}
apos = asec->output_section->lma + asec->output_offset;
bpos = bsec->output_section->lma + bsec->output_offset;
if (apos < bpos)
return -1;
@ -11905,14 +11918,14 @@ compare_link_order (const void *a, const void *b)
sections. Ideally we'd do this in the linker proper. */
static bfd_boolean
elf_fixup_link_order (bfd *abfd, asection *o)
elf_fixup_link_order (struct bfd_link_info *info, bfd *abfd, asection *o)
{
size_t seen_linkorder;
size_t seen_other;
size_t n;
struct bfd_link_order *p;
bfd *sub;
struct bfd_link_order **sections;
struct bfd_link_order **sections, **indirect_sections;
asection *other_sec, *linkorder_sec;
bfd_vma offset; /* Octets. */
@ -11943,7 +11956,9 @@ elf_fixup_link_order (bfd *abfd, asection *o)
else
seen_other++;
if (seen_other && seen_linkorder)
/* Allow mixed ordered and unordered input sections for
non-relocatable link. */
if (bfd_link_relocatable (info) && seen_other && seen_linkorder)
{
if (other_sec && linkorder_sec)
_bfd_error_handler
@ -11963,6 +11978,10 @@ elf_fixup_link_order (bfd *abfd, asection *o)
if (!seen_linkorder)
return TRUE;
/* Non-relocatable output can have both ordered and unordered input
sections. */
seen_linkorder += seen_other;
sections = bfd_malloc (seen_linkorder * sizeof (*sections));
if (sections == NULL)
return FALSE;
@ -11971,22 +11990,48 @@ elf_fixup_link_order (bfd *abfd, asection *o)
for (p = o->map_head.link_order; p != NULL; p = p->next)
sections[seen_linkorder++] = p;
/* Sort the input sections in the order of their linked section. */
qsort (sections, seen_linkorder, sizeof (*sections), compare_link_order);
for (indirect_sections = sections, n = 0;
n < seen_linkorder;
indirect_sections++, n++)
{
/* Find the first bfd_indirect_link_order section. */
if (indirect_sections[0]->type == bfd_indirect_link_order)
{
/* Count the consecutive bfd_indirect_link_order sections
with the same pattern. */
size_t i, n_indirect;
const char *pattern
= indirect_sections[0]->u.indirect.section->pattern;
for (i = n + 1; i < seen_linkorder; i++)
if (sections[i]->type != bfd_indirect_link_order
|| sections[i]->u.indirect.section->pattern != pattern)
break;
n_indirect = i - n;
/* Sort the bfd_indirect_link_order sections in the order of
their linked section. */
qsort (indirect_sections, n_indirect, sizeof (*sections),
compare_link_order);
indirect_sections += n_indirect;
n += n_indirect;
}
}
/* Change the offsets of the sections. */
/* Change the offsets of the bfd_indirect_link_order sections. */
offset = 0;
for (n = 0; n < seen_linkorder; n++)
{
bfd_vma mask;
asection *s = sections[n]->u.indirect.section;
unsigned int opb = bfd_octets_per_byte (abfd, s);
if (sections[n]->type == bfd_indirect_link_order)
{
bfd_vma mask;
asection *s = sections[n]->u.indirect.section;
unsigned int opb = bfd_octets_per_byte (abfd, s);
mask = ~(bfd_vma) 0 << s->alignment_power * opb;
offset = (offset + ~mask) & mask;
sections[n]->offset = s->output_offset = offset / opb;
offset += sections[n]->size;
}
mask = ~(bfd_vma) 0 << s->alignment_power * opb;
offset = (offset + ~mask) & mask;
sections[n]->offset = s->output_offset = offset / opb;
offset += sections[n]->size;
}
else
offset = sections[n]->offset + sections[n]->size;
free (sections);
return TRUE;
@ -12629,7 +12674,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
/* Reorder SHF_LINK_ORDER sections. */
for (o = abfd->sections; o != NULL; o = o->next)
{
if (!elf_fixup_link_order (abfd, o))
if (!elf_fixup_link_order (info, abfd, o))
return FALSE;
}

View file

@ -541,6 +541,9 @@ CODE_FRAGMENT
. struct bfd_symbol *symbol;
. struct bfd_symbol **symbol_ptr_ptr;
.
. {* The matching section name pattern in linker script. *}
. const char *pattern;
.
. {* Early in the link process, map_head and map_tail are used to build
. a list of input sections attached to an output section. Later,
. output sections use these fields for a list of bfd_link_order
@ -734,8 +737,8 @@ CODE_FRAGMENT
. {* target_index, used_by_bfd, constructor_chain, owner, *} \
. 0, NULL, NULL, NULL, \
. \
. {* symbol, symbol_ptr_ptr, *} \
. (struct bfd_symbol *) SYM, &SEC.symbol, \
. {* symbol, symbol_ptr_ptr, pattern, *} \
. (struct bfd_symbol *) SYM, &SEC.symbol, NULL, \
. \
. {* map_head, map_tail, already_assigned *} \
. { NULL }, { NULL }, NULL \

View file

@ -1,3 +1,9 @@
2021-01-04 H.J. Lu <hongjiu.lu@intel.com>
PR ld/26256
* config/obj-elf.c (obj_elf_change_section): Also filter out
SHF_LINK_ORDER.
2021-01-04 Alan Modra <amodra@gmail.com>
PR 27102

View file

@ -666,7 +666,9 @@ obj_elf_change_section (const char *name,
}
}
if (old_sec == NULL && ((attr & ~(SHF_MASKOS | SHF_MASKPROC))
if (old_sec == NULL && ((attr & ~(SHF_LINK_ORDER
| SHF_MASKOS
| SHF_MASKPROC))
& ~ssect->attr) != 0)
{
/* As a GNU extension, we permit a .note section to be

View file

@ -1,3 +1,22 @@
2021-01-04 H.J. Lu <hongjiu.lu@intel.com>
PR ld/26256
* ldlang.c (gc_section_callback): Set pattern.
* testsuite/ld-elf/pr26256-1.s: New file.
* testsuite/ld-elf/pr26256-1.t: Likewise.
* testsuite/ld-elf/pr26256-1a.d: Likewise.
* testsuite/ld-elf/pr26256-1b.d: Likewise.
* testsuite/ld-elf/pr26256-2.s: Likewise.
* testsuite/ld-elf/pr26256-2.t: Likewise.
* testsuite/ld-elf/pr26256-2a.d: Likewise.
* testsuite/ld-elf/pr26256-2b-alt.d: Likewise.
* testsuite/ld-elf/pr26256-2b.d: Likewise.
* testsuite/ld-elf/pr26256-3.s: Likewise.
* testsuite/ld-elf/pr26256-3a.d: Likewise.
* testsuite/ld-elf/pr26256-3a.t: Likewise.
* testsuite/ld-elf/pr26256-3b.d: Likewise.
* testsuite/ld-elf/pr26256-3b.t: Likewise.
2021-01-04 Alan Modra <amodra@gmail.com>
PR 26822

View file

@ -7488,7 +7488,7 @@ lang_reset_memory_regions (void)
static void
gc_section_callback (lang_wild_statement_type *ptr,
struct wildcard_list *sec ATTRIBUTE_UNUSED,
struct wildcard_list *sec,
asection *section,
struct flag_info *sflag_info ATTRIBUTE_UNUSED,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
@ -7498,6 +7498,8 @@ gc_section_callback (lang_wild_statement_type *ptr,
should be as well. */
if (ptr->keep_sections)
section->flags |= SEC_KEEP;
if (sec)
section->pattern = sec->spec.name;
}
/* Iterate over sections marking them against GC. */

View file

@ -0,0 +1,20 @@
.section .text.bar,"ax",%progbits
.globl bar
.type bar, %function
bar:
.section __patchable_function_entries,"awo",%progbits,bar
.dc.a .LPFE1
.section .text.bar,"ax",%progbits
.LPFE1:
.byte 0
.section .text._start,"ax",%progbits
.globl _start
.type _start, %function
_start:
.section __patchable_function_entries,"awo",%progbits,_start
.dc.a .LPFE2
.section .text._start,"ax",%progbits
.LPFE2:
.byte 0
.section .init.data,"aw",%progbits
.byte 0

View file

@ -0,0 +1,13 @@
SECTIONS
{
.text : { *(.text*) }
.init.data :
{
*(.init.data);
*(__patchable_function_entries);
}
/DISCARD/ :
{
*(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
}
}

View file

@ -0,0 +1,7 @@
#source: pr26256-1.s
#ld: -e _start -T pr26256-1.t
#nm: -n
#...
[0-9a-f]+ T _start
#pass

View file

@ -0,0 +1,7 @@
#source: pr26256-1.s
#ld: -e _start
#nm: -n
#...
[0-9a-f]+ T _start
#pass

View file

@ -0,0 +1,32 @@
.section .text,"ax",%progbits,unique,0
.globl text0
text0:
.nop
.section .text,"ax",%progbits,unique,1
.globl text1
text1:
.nop
.section .linkorder,"ao",%progbits,0,unique,0
.globl linkorder2
linkorder2:
.byte 0
.section .linkorder,"ao",%progbits,text0
.globl linkorder0
linkorder0:
.byte 1
.section .linkorder,"ao",%progbits,text1
.globl linkorder1
linkorder1:
.byte 2
.section .linkorder,"a",%progbits
.globl linkorder3
linkorder3:
.byte 3
.section .linkorder,"ao",%progbits,0,unique,3
.globl linkorder4
linkorder4:
.byte 4
.text
.global _start
_start:
.nop

View file

@ -0,0 +1,9 @@
SECTIONS
{
.linkorder : { *(.linkorder.*) }
.text : { *(.text) }
/DISCARD/ :
{
*(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
}
}

View file

@ -0,0 +1,20 @@
#source: pr26256-2.s
#ld: -e _start -T pr26256-2.t
#nm: -n
#xfail: [is_generic]
#...
[0-9a-f]+ R linkorder2
#...
[0-9a-f]+ R linkorder3
#...
[0-9a-f]+ R linkorder4
#...
[0-9a-f]+ R linkorder0
#...
[0-9a-f]+ R linkorder1
#...
[0-9a-f]+ T text0
#...
[0-9a-f]+ T text1
#pass

View file

@ -0,0 +1,21 @@
#source: pr26256-2.s
#ld: -e _start
#nm: -n
#target: fr30-*-* iq2000-*-* ip2k-*-* xstormy16-*-*
# These targets place .linkorder sections before .text sections.
#...
[0-9a-f]+ R linkorder2
#...
[0-9a-f]+ R linkorder3
#...
[0-9a-f]+ R linkorder4
#...
[0-9a-f]+ R linkorder0
#...
[0-9a-f]+ R linkorder1
#...
[0-9a-f]+ T text0
#...
[0-9a-f]+ T text1
#pass

View file

@ -0,0 +1,22 @@
#source: pr26256-2.s
#ld: -e _start
#nm: -n
#xfail: [is_generic]
#notarget: fr30-*-* iq2000-*-* ip2k-*-* xstormy16-*-*
# These targets place .linkorder sections before .text sections.
#...
[0-9a-f]+ T text0
#...
[0-9a-f]+ T text1
#...
[0-9a-f]+ R linkorder2
#...
[0-9a-f]+ R linkorder3
#...
[0-9a-f]+ R linkorder4
#...
[0-9a-f]+ R linkorder0
#...
[0-9a-f]+ R linkorder1
#pass

View file

@ -0,0 +1,27 @@
.text
.global _start
_start:
.long 0x33333333
.long 0x33333333
.long 0x33333333
.long 0x33333333
.section .rosection,"a"
.byte 9
.section .text.bar,"a",%progbits
.long 0x22222222
.long 0x22222222
.long 0x22222222
.long 0x22222222
.section .text.foo,"a",%progbits
.long 0x11111111
.long 0x11111111
.long 0x11111111
.long 0x11111111
.section .rodata.foo,"ao",%progbits,.text.foo
.byte 1
.section .rodata.bar,"a",%progbits
.byte 2
.section .rodata.bar,"ao",%progbits,.text.bar
.byte 3

View file

@ -0,0 +1,11 @@
#source: pr26256-3.s
#ld: -e _start -T pr26256-3a.t
#readelf: -x .rodata -x .text
Hex dump of section \'.rodata\':
0x[a-f0-9]+ +00010203 +040907 +.+
Hex dump of section \'.text\':
0x[a-f0-9]+ +22222222 +22222222 +22222222 +.+
0x[a-f0-9]+ +11111111 +11111111 +11111111 +.+
0x[a-f0-9]+ +33333333 +33333333 +33333333 +.+

View file

@ -0,0 +1,17 @@
SECTIONS
{
.rodata :
{
BYTE(0)
*(.rodata.foo)
*(.rodata.bar)
BYTE(4)
*(.rosection)
BYTE(7)
}
.text : {*(.text.bar) *(.text.foo)}
/DISCARD/ :
{
*(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
}
}

View file

@ -0,0 +1,12 @@
#source: pr26256-3.s
#ld: -e _start -T pr26256-3b.t
#readelf: -x .rodata -x .text
#xfail: [is_generic]
Hex dump of section \'.rodata\':
0x[a-f0-9]+ +00020301 +040907 +.+
Hex dump of section \'.text\':
0x[a-f0-9]+ +22222222 +22222222 +22222222 +.+
0x[a-f0-9]+ +11111111 +11111111 +11111111 +.+
0x[a-f0-9]+ +33333333 +33333333 +33333333 +.+

View file

@ -0,0 +1,16 @@
SECTIONS
{
.rodata :
{
BYTE(0)
*(.rodata*)
BYTE(4)
*(.rosection)
BYTE(7)
}
.text : {*(.text.bar) *(.text.foo)}
/DISCARD/ :
{
*(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
}
}