qsort issues
authorAlan Modra <amodra@gmail.com>
Mon, 14 Oct 2019 03:05:21 +0000 (13:35 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 14 Oct 2019 06:17:12 +0000 (16:47 +1030)
commitdcea6a95d78370c8b4ac3c0033d9f15aaabf31bf
treeeb0093b4b0be719e02bebfd55874c649e32a8438
parentec9bd0a22dd42327ae9943937a96f1e865fb5d46
qsort issues

qsort isn't guaranteed to be a stable sort, that is, elements
comparing equal according to the comparison function may be reordered
relative to their original ordering.  Of course sometimes you may not
care, but even in those cases it is good to force some ordering
(ie. not have the comparison function return 0) so that linker output
is reproducible over different libc qsort implementations.

One way to make qsort stable (which the glibc manual incorrectly says
is the only way) is to augment the elements being sorted with a
monotonic counter of some kind, and use that counter as the final
arbiter of ordering in the comparison function.

Another way is to set up an array of pointers into the array of
elements, first pointer to first element, second pointer to second
element and so so, and sort the pointer array rather than the element
array.  Final arbiter in the comparison function then is the pointer
difference.  This works well with, for example, the symbol pointers
returned by _bfd_elf_canonicalize_symtab which point into a symbol
array.

This patch fixes a few places where sorting by symbol pointers is
appropriate, and adds comments where qsort stability is a non-issue.

* elf-strtab.c (strrevcmp): Comment.
* merge.c (strrevcmp): Likewise.
* elf64-ppc.c (compare_symbols): Correct final pointer comparison.
Comment on why comparing pointers ensures a stable sort.
* elflink.c (struct elf_symbol): Add void* to union.
(elf_sort_elf_symbol): Ensure a stable sort with pointer comparison.
(elf_sym_name_compare): Likewise.
(bfd_elf_match_symbols_in_sections): Style fix.
(elf_link_sort_cmp1): Comment.
bfd/ChangeLog
bfd/elf-strtab.c
bfd/elf64-ppc.c
bfd/elflink.c
bfd/merge.c
This page took 0.025425 seconds and 4 git commands to generate.