aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorTomoaki Kawada <kawada@kmckk.co.jp>2022-06-16 09:54:30 +0000
committerAlan Modra <amodra@gmail.com>2022-06-18 20:11:23 +0930
commitfba1ac87dcb76e61f270d236f1e7c8aaec80f9c4 (patch)
tree4122da4e90d8f5897cec0d8719132794548883de /bfd/elflink.c
parent3f52a09075e3c62f2150375bb7fca338e7db45e7 (diff)
downloadbinutils-fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4.zip
binutils-fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4.tar.gz
binutils-fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4.tar.bz2
Fix the sorting algorithm for reloc entries
The optimized insertion sort algorithm in `elf_link_adjust_relocs` incorrectly assembled "runs" from unsorted entries and inserted them to an already-sorted prefix, breaking the loop invariants of insertion sort. This commit updates the run assembly loop to break upon encountering a non-monotonic change in the sort key. PR 29259 bfd/ * elflink.c (elf_link_adjust_relocs): Ensure run being inserted is sorted. ld/ * testsuite/ld-elf/pr29259.d, * testsuite/ld-elf/pr29259.s, * testsuite/ld-elf/pr29259.t: New test.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e4f6df4..dcafac3 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9548,12 +9548,20 @@ elf_link_adjust_relocs (bfd *abfd,
size_t sortlen = p - loc;
bfd_vma r_off2 = (*ext_r_off) (loc);
size_t runlen = elt_size;
+ bfd_vma r_off_runend = r_off;
+ bfd_vma r_off_runend_next;
size_t buf_size = 96 * 1024;
while (p + runlen < end
&& (sortlen <= buf_size
|| runlen + elt_size <= buf_size)
- && r_off2 > (*ext_r_off) (p + runlen))
- runlen += elt_size;
+ /* run must not break the ordering of base..loc+1 */
+ && r_off2 > (r_off_runend_next = (*ext_r_off) (p + runlen))
+ /* run must be already sorted */
+ && r_off_runend_next >= r_off_runend)
+ {
+ runlen += elt_size;
+ r_off_runend = r_off_runend_next;
+ }
if (buf == NULL)
{
buf = bfd_malloc (buf_size);