+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
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
/* 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 \
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;
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. */
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
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;
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);
-
- mask = ~(bfd_vma) 0 << s->alignment_power * opb;
- offset = (offset + ~mask) & mask;
- sections[n]->offset = s->output_offset = offset / opb;
- offset += sections[n]->size;
- }
+ 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;
+ }
+ else
+ offset = sections[n]->offset + sections[n]->size;
free (sections);
return TRUE;
/* 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;
}
. 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
. {* 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 \
+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
}
}
- 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
+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
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,
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. */
--- /dev/null
+ .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
--- /dev/null
+SECTIONS
+{
+ .text : { *(.text*) }
+ .init.data :
+ {
+ *(.init.data);
+ *(__patchable_function_entries);
+ }
+ /DISCARD/ :
+ {
+ *(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
+ }
+}
--- /dev/null
+#source: pr26256-1.s
+#ld: -e _start -T pr26256-1.t
+#nm: -n
+
+#...
+[0-9a-f]+ T _start
+#pass
--- /dev/null
+#source: pr26256-1.s
+#ld: -e _start
+#nm: -n
+
+#...
+[0-9a-f]+ T _start
+#pass
--- /dev/null
+ .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
--- /dev/null
+SECTIONS
+{
+ .linkorder : { *(.linkorder.*) }
+ .text : { *(.text) }
+ /DISCARD/ :
+ {
+ *(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+ .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
--- /dev/null
+#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 +.+
--- /dev/null
+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)
+ }
+}
--- /dev/null
+#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 +.+
--- /dev/null
+SECTIONS
+{
+ .rodata :
+ {
+ BYTE(0)
+ *(.rodata*)
+ BYTE(4)
+ *(.rosection)
+ BYTE(7)
+ }
+ .text : {*(.text.bar) *(.text.foo)}
+ /DISCARD/ :
+ {
+ *(.reginfo) *(.MIPS.abiflags) *(.MIPS.options) *(.trampolines)
+ }
+}