aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-12-09 14:32:22 +1030
committerAlan Modra <amodra@gmail.com>2014-12-10 09:55:31 +1030
commit28dbcedc7b1282b93c3f25c4e42ae71b44e8e2a8 (patch)
tree6aaf117e0769bdcf3eb2c5a989116b7543928344 /bfd/elflink.c
parent4e3272393ff1ab2c07d9fa209d2ae82954f7954c (diff)
downloadgdb-28dbcedc7b1282b93c3f25c4e42ae71b44e8e2a8.zip
gdb-28dbcedc7b1282b93c3f25c4e42ae71b44e8e2a8.tar.gz
gdb-28dbcedc7b1282b93c3f25c4e42ae71b44e8e2a8.tar.bz2
Don't sort ld -r relocs for mips
HI16/LO16 are deliberately put adjacent, which might mean relocs are then not sorted by r_offset. See tc-mips.c:mips_frob_file. Don't undo the HI16/LO16 sorting. PR 17666 * elf-bfd.h (struct elf_backend_data): Add sort_relocs_p. * elfxx-target.h (elf_backend_sort_relocs_p): Define. (elfNN_bed): Init new field. * elflink.c (elf_link_adjust_relocs): Conditionally sort. (bfd_elf_final_link): Control sorting of relocs. * elfxx-mips.c (_bfd_mips_elf_sort_relocs_p): New function. * elfxx-mips.h (_bfd_mips_elf_sort_relocs_p): Declare. * elf32-mips.c (elf_backend_sort_relocs_p): Define. * elf64-mips.c (elf_backend_sort_relocs_p): Define.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c51
1 files changed, 29 insertions, 22 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index e768634..b023ec5 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -8097,7 +8097,8 @@ cmp_ext64b_r_offset (const void *p, const void *q)
static void
elf_link_adjust_relocs (bfd *abfd,
- struct bfd_elf_section_reloc_data *reldata)
+ struct bfd_elf_section_reloc_data *reldata,
+ bfd_boolean sort)
{
unsigned int i;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -8108,7 +8109,6 @@ elf_link_adjust_relocs (bfd *abfd,
int r_sym_shift;
unsigned int count = reldata->count;
struct elf_link_hash_entry **rel_hash = reldata->hashes;
- int (*compare) (const void *, const void *);
if (reldata->hdr->sh_entsize == bed->s->sizeof_rel)
{
@@ -8155,29 +8155,34 @@ elf_link_adjust_relocs (bfd *abfd,
(*swap_out) (abfd, irela, erela);
}
- if (bed->s->arch_size == 32)
+ if (sort)
{
- if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
- compare = cmp_ext32l_r_offset;
- else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
- compare = cmp_ext32b_r_offset;
+ int (*compare) (const void *, const void *);
+
+ if (bed->s->arch_size == 32)
+ {
+ if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+ compare = cmp_ext32l_r_offset;
+ else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
+ compare = cmp_ext32b_r_offset;
+ else
+ abort ();
+ }
else
- abort ();
- }
- else
- {
+ {
#ifdef BFD_HOST_64_BIT
- if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
- compare = cmp_ext64l_r_offset;
- else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
- compare = cmp_ext64b_r_offset;
- else
+ if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+ compare = cmp_ext64l_r_offset;
+ else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
+ compare = cmp_ext64b_r_offset;
+ else
#endif
- abort ();
+ abort ();
+ }
+ qsort (reldata->hdr->contents, count, reldata->hdr->sh_entsize, compare);
+ free (reldata->hashes);
+ reldata->hashes = NULL;
}
- qsort (reldata->hdr->contents, count, reldata->hdr->sh_entsize, compare);
- free (reldata->hashes);
- reldata->hashes = NULL;
}
struct elf_link_sort_rela
@@ -11325,13 +11330,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
for (o = abfd->sections; o != NULL; o = o->next)
{
struct bfd_elf_section_data *esdo = elf_section_data (o);
+ bfd_boolean sort;
if ((o->flags & SEC_RELOC) == 0)
continue;
+ sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
if (esdo->rel.hdr != NULL)
- elf_link_adjust_relocs (abfd, &esdo->rel);
+ elf_link_adjust_relocs (abfd, &esdo->rel, sort);
if (esdo->rela.hdr != NULL)
- elf_link_adjust_relocs (abfd, &esdo->rela);
+ elf_link_adjust_relocs (abfd, &esdo->rela, sort);
/* Set the reloc_count field to 0 to prevent write_relocs from
trying to swap the relocs out itself. */