diff options
author | Alan Modra <amodra@gmail.com> | 2014-12-09 14:32:22 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2014-12-10 09:55:31 +1030 |
commit | 28dbcedc7b1282b93c3f25c4e42ae71b44e8e2a8 (patch) | |
tree | 6aaf117e0769bdcf3eb2c5a989116b7543928344 /bfd/elflink.c | |
parent | 4e3272393ff1ab2c07d9fa209d2ae82954f7954c (diff) | |
download | gdb-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.c | 51 |
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. */ |