summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2021-01-04 12:37:49 -0800
committerH.J. Lu <hjl.tools@gmail.com>2021-01-04 12:38:05 -0800
commitcd6d537c48fa862e8a5888b648102d7b2330ef81 (patch)
tree1ab9bc928a0acb1a3acc04f6d985338ae45f279e /bfd
parente4ad960a577405c4d0f7593f439ad560fabc9d49 (diff)
downloadbinutils-gdb-cd6d537c48fa862e8a5888b648102d7b2330ef81.tar.gz
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog15
-rw-r--r--bfd/bfd-in2.h7
-rw-r--r--bfd/elflink.c83
-rw-r--r--bfd/section.c7
4 files changed, 89 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index df9cb205012..f1ae342b4c3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 5196bb6940d..43ead185c19 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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 \
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 448989a2827..df5b997cf00 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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);
-
- 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;
@@ -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;
}
diff --git a/bfd/section.c b/bfd/section.c
index 3e6ba0c0938..10efc3c4aa7 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -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 \