forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
29
gas/write.c
29
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
|
||||
|
||||
Reference in New Issue
Block a user