diff options
author | Alan Modra <amodra@gmail.com> | 2021-12-21 01:09:13 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-12-28 23:00:01 +1030 |
commit | 443aa5f05edb58fc1774f926e9259b7c5a180926 (patch) | |
tree | ebc72377ef825f1da276fa3080f91fb49a143341 /gas/write.c | |
parent | 4748764aaba89b8515cbf8918dc0ada840cdfab7 (diff) | |
download | gdb-443aa5f05edb58fc1774f926e9259b7c5a180926.zip gdb-443aa5f05edb58fc1774f926e9259b7c5a180926.tar.gz gdb-443aa5f05edb58fc1774f926e9259b7c5a180926.tar.bz2 |
gas reloc sorting
In some cases, eg. riscv_pre_output_hook, gas generates out-of-order
relocations. Various places in the linker assume relocs are sorted
by increasing r_offset, which is normally the case. Provide
GAS_SORT_RELOCS to handle unsorted relocs.
bfd/
PR 28709
* elf32-nds32.c (nds32_insertion_sort): Make static.
* elf32-nds32.h (nds32_insertion_sort): Delete declaration.
gas/
PR 28709
* write.c (write_relocs): Implement reloc sorting by r_offset
when GAS_SORT_RELOCS.
* config/tc-nds32.c (compar_relent, nds32_set_section_relocs): Delete.
* config/tc-nds32.h (nds32_set_section_relocs): Don't declare.
(SET_SECTION_RELOCS): Don't define.
(GAS_SORT_RELOCS): Define.
* config/tc-riscv.h (GAS_SORT_RELOCS): Define.
Diffstat (limited to 'gas/write.c')
-rw-r--r-- | gas/write.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/gas/write.c b/gas/write.c index e2c7bf2..eaa9d21 100644 --- a/gas/write.c +++ b/gas/write.c @@ -1315,7 +1315,34 @@ write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, } r = r->next; } - relocs[n++] = *reloc; +#ifdef GAS_SORT_RELOCS + if (n != 0 && (*reloc)->address < relocs[n - 1]->address) + { + size_t lo = 0; + size_t hi = n - 1; + bfd_vma look = (*reloc)->address; + while (lo < hi) + { + size_t mid = (lo + hi) / 2; + if (relocs[mid]->address > look) + hi = mid; + else + { + lo = mid + 1; + if (relocs[mid]->address == look) + break; + } + } + while (lo < hi && relocs[lo]->address == look) + lo++; + memmove (relocs + lo + 1, relocs + lo, + (n - lo) * sizeof (*relocs)); + n++; + relocs[lo] = *reloc; + } + else +#endif + relocs[n++] = *reloc; install_reloc (sec, *reloc, fixp->fx_frag, fixp->fx_file, fixp->fx_line); #ifndef RELOC_EXPANSION_POSSIBLE |