You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
8.6 KiB
223 lines
8.6 KiB
diff -rup binutils.orig/bfd/bfd-in2.h binutils-2.35.1/bfd/bfd-in2.h |
|
--- binutils.orig/bfd/bfd-in2.h 2021-01-04 13:18:10.234368481 +0000 |
|
+++ binutils-2.35.1/bfd/bfd-in2.h 2021-01-04 13:18:20.596301287 +0000 |
|
@@ -1177,6 +1177,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 |
|
@@ -1370,8 +1373,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 -rup binutils.orig/bfd/elflink.c binutils-2.35.1/bfd/elflink.c |
|
--- binutils.orig/bfd/elflink.c 2021-01-04 13:18:10.223368552 +0000 |
|
+++ binutils-2.35.1/bfd/elflink.c 2021-01-04 13:18:20.599301268 +0000 |
|
@@ -11662,8 +11662,21 @@ compare_link_order (const void *a, const |
|
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 ordered sections before unordered 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; |
|
@@ -11698,14 +11711,14 @@ compare_link_order (const void *a, const |
|
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. */ |
|
|
|
@@ -11736,7 +11749,9 @@ elf_fixup_link_order (bfd *abfd, asectio |
|
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 |
|
@@ -11756,6 +11771,10 @@ elf_fixup_link_order (bfd *abfd, asectio |
|
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; |
|
@@ -11764,22 +11783,51 @@ elf_fixup_link_order (bfd *abfd, asectio |
|
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;) |
|
+ { |
|
+ /* 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; |
|
+ } |
|
+ else |
|
+ { |
|
+ indirect_sections++; |
|
+ n++; |
|
+ } |
|
+ } |
|
|
|
- /* 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; |
|
@@ -12408,7 +12456,7 @@ bfd_elf_final_link (bfd *abfd, struct bf |
|
/* 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 -rup binutils.orig/bfd/section.c binutils-2.35.1/bfd/section.c |
|
--- binutils.orig/bfd/section.c 2021-01-04 13:18:10.233368487 +0000 |
|
+++ binutils-2.35.1/bfd/section.c 2021-01-04 13:18:20.599301268 +0000 |
|
@@ -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 \ |
|
diff -rup binutils.orig/gas/config/obj-elf.c binutils-2.35.1/gas/config/obj-elf.c |
|
--- binutils.orig/gas/config/obj-elf.c 2021-01-04 13:18:09.942370375 +0000 |
|
+++ binutils-2.35.1/gas/config/obj-elf.c 2021-01-04 13:18:20.599301268 +0000 |
|
@@ -659,7 +659,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 |
|
diff -rup binutils.orig/ld/ldlang.c binutils-2.35.1/ld/ldlang.c |
|
--- binutils.orig/ld/ldlang.c 2021-01-04 13:18:09.691372002 +0000 |
|
+++ binutils-2.35.1/ld/ldlang.c 2021-01-04 13:18:20.600301261 +0000 |
|
@@ -7421,7 +7421,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, |
|
@@ -7431,6 +7431,8 @@ gc_section_callback (lang_wild_statement |
|
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. */
|
|
|