diff options
author | Tomoaki Kawada <kawada@kmckk.co.jp> | 2022-06-16 09:54:30 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-06-18 20:11:23 +0930 |
commit | fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4 (patch) | |
tree | 4122da4e90d8f5897cec0d8719132794548883de | |
parent | 3f52a09075e3c62f2150375bb7fca338e7db45e7 (diff) | |
download | gdb-fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4.zip gdb-fba1ac87dcb76e61f270d236f1e7c8aaec80f9c4.tar.gz gdb-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.
-rw-r--r-- | bfd/elflink.c | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/pr29259.d | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/pr29259.s | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/pr29259.t | 4 |
4 files changed, 41 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); diff --git a/ld/testsuite/ld-elf/pr29259.d b/ld/testsuite/ld-elf/pr29259.d new file mode 100644 index 0000000..c7eaa7a --- /dev/null +++ b/ld/testsuite/ld-elf/pr29259.d @@ -0,0 +1,13 @@ +#ld: -r -T pr29259.t +#readelf: -Wr + +Relocation section .* + +Offset +Info +Type .* +0+00 .* +#... +0+20 .* +#... +0+40 .* +#... +0+60 .* +#pass diff --git a/ld/testsuite/ld-elf/pr29259.s b/ld/testsuite/ld-elf/pr29259.s new file mode 100644 index 0000000..65fc73f --- /dev/null +++ b/ld/testsuite/ld-elf/pr29259.s @@ -0,0 +1,14 @@ + .data +.L1: + .section ".data.1", "aw", %progbits + .p2align 5 + .dc.a .L1 + .section ".data.2", "aw", %progbits + .p2align 5 + .dc.a .L1 + .section ".data.3", "aw", %progbits + .p2align 5 + .dc.a .L1 + .section ".data.4", "aw", %progbits + .p2align 5 + .dc.a .L1 diff --git a/ld/testsuite/ld-elf/pr29259.t b/ld/testsuite/ld-elf/pr29259.t new file mode 100644 index 0000000..ed80f87 --- /dev/null +++ b/ld/testsuite/ld-elf/pr29259.t @@ -0,0 +1,4 @@ +SECTIONS +{ + .data : { *(.data.1) *(.data.4) *(.data.3) *(.data.2) *(.data) } +} |