diff options
author | Alan Modra <amodra@gmail.com> | 2020-08-12 23:31:28 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-08-13 08:10:18 +0930 |
commit | 6738c8a7c93cd77a0caa720c6cc21c422561be2c (patch) | |
tree | fbb7e126a4d5a43d2292ecd1faafb1a781d08dde /bfd | |
parent | 75e100a30d5dfdd3ac2b0391c17173645fc77633 (diff) | |
download | gdb-6738c8a7c93cd77a0caa720c6cc21c422561be2c.zip gdb-6738c8a7c93cd77a0caa720c6cc21c422561be2c.tar.gz gdb-6738c8a7c93cd77a0caa720c6cc21c422561be2c.tar.bz2 |
PowerPC64 --no-pcrel-optimize
This new option effectively ignores R_PPC64_PCREL_OPT, disabling the
optimization of instructions marked by that relocation. The patch
also disables GOT indirect to GOT/TOC pointer relative code editing
when --no-toc-optimize.
bfd/
* elf64-ppc.h (struct ppc64_elf_params): Add no_pcrel_opt.
* elf64-ppc.c (ppc64_elf_relocate_section): Disable GOT reloc
optimizations when --no-toc-optimize. Disable R_PPC64_PCREL_OPT
optimization when --no-pcrel-optimize.
ld/
* emultempl/ppc64elf.em (params): Init new field.
(enum ppc64_opt): Add OPTION_NO_PCREL_OPT.
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS),
(PARSE_AND_LIST_ARGS_CASES): Support --no-pcrel-optimize.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 116 | ||||
-rw-r--r-- | bfd/elf64-ppc.h | 3 |
3 files changed, 68 insertions, 58 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0e22506..31a4c0b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,12 @@ 2020-08-13 Alan Modra <amodra@gmail.com> + * elf64-ppc.h (struct ppc64_elf_params): Add no_pcrel_opt. + * elf64-ppc.c (ppc64_elf_relocate_section): Disable GOT reloc + optimizations when --no-toc-optimize. Disable R_PPC64_PCREL_OPT + optimization when --no-pcrel-optimize. + +2020-08-13 Alan Modra <amodra@gmail.com> + PR 26348 * bfd.c (struct bfd): Add read_only. * elfcode.h (elf_swap_shdr_in): Test both sh_offset and sh_size. diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 4a75c25..5cbf9ac 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -15903,7 +15903,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, break; case R_PPC64_GOT16_DS: - if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC) + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) break; from = TOCstart + htab->sec_info[input_section->id].toc_off; if (relocation + addend - from + 0x8000 < 0x10000 @@ -15922,7 +15923,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GOT16_LO_DS: case R_PPC64_GOT16_HA: - if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC) + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) break; from = TOCstart + htab->sec_info[input_section->id].toc_off; if (relocation + addend - from + 0x80008000ULL < 0x100000000ULL @@ -15945,34 +15947,38 @@ ppc64_elf_relocate_section (bfd *output_bfd, break; case R_PPC64_GOT_PCREL34: - if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC) + if ((h ? h->elf.type : ELF_ST_TYPE (sym->st_info)) == STT_GNU_IFUNC + || !htab->do_toc_opt) break; from = (rel->r_offset + input_section->output_section->vma + input_section->output_offset); - if (relocation - from + (1ULL << 33) < 1ULL << 34 - && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) - { - offset = rel->r_offset; - pinsn = bfd_get_32 (input_bfd, contents + offset); - pinsn <<= 32; - pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); - if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) - == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */)) - { - /* Replace with paddi. */ - pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26); - r_type = R_PPC64_PCREL34; - rel->r_info = ELF64_R_INFO (r_symndx, r_type); - bfd_put_32 (input_bfd, pinsn >> 32, contents + offset); - bfd_put_32 (input_bfd, pinsn, contents + offset + 4); - goto pcrelopt; - } - } - break; + if (!(relocation - from + (1ULL << 33) < 1ULL << 34 + && SYMBOL_REFERENCES_LOCAL (info, &h->elf))) + break; + + offset = rel->r_offset; + pinsn = bfd_get_32 (input_bfd, contents + offset); + pinsn <<= 32; + pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); + if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) + != ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */)) + break; + + /* Replace with paddi. */ + pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26); + r_type = R_PPC64_PCREL34; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + bfd_put_32 (input_bfd, pinsn >> 32, contents + offset); + bfd_put_32 (input_bfd, pinsn, contents + offset + 4); + /* Fall through. */ case R_PPC64_PCREL34: - if (SYMBOL_REFERENCES_LOCAL (info, &h->elf)) + if (!htab->params->no_pcrel_opt + && rel + 1 < relend + && rel[1].r_offset == rel->r_offset + && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT) + && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) { offset = rel->r_offset; pinsn = bfd_get_32 (input_bfd, contents + offset); @@ -15982,43 +15988,37 @@ ppc64_elf_relocate_section (bfd *output_bfd, == ((1ULL << 58) | (2ULL << 56) | (1ULL << 52) | (14ULL << 26) /* paddi */)) { - pcrelopt: - if (rel + 1 < relend - && rel[1].r_offset == offset - && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)) + bfd_vma off2 = rel[1].r_addend; + if (off2 == 0) + /* zero means next insn. */ + off2 = 8; + off2 += offset; + if (off2 + 4 <= input_section->size) { - bfd_vma off2 = rel[1].r_addend; - if (off2 == 0) - /* zero means next insn. */ - off2 = 8; - off2 += offset; - if (off2 + 4 <= input_section->size) + uint64_t pinsn2; + bfd_signed_vma addend_off; + pinsn2 = bfd_get_32 (input_bfd, contents + off2); + pinsn2 <<= 32; + if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) { - uint64_t pinsn2; - bfd_signed_vma addend_off; - pinsn2 = bfd_get_32 (input_bfd, contents + off2); - pinsn2 <<= 32; + if (off2 + 8 > input_section->size) + break; + pinsn2 |= bfd_get_32 (input_bfd, + contents + off2 + 4); + } + if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off)) + { + addend += addend_off; + rel->r_addend = addend; + bfd_put_32 (input_bfd, pinsn >> 32, + contents + offset); + bfd_put_32 (input_bfd, pinsn, + contents + offset + 4); + bfd_put_32 (input_bfd, pinsn2 >> 32, + contents + off2); if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) - { - if (off2 + 8 > input_section->size) - break; - pinsn2 |= bfd_get_32 (input_bfd, - contents + off2 + 4); - } - if (xlate_pcrel_opt (&pinsn, &pinsn2, &addend_off)) - { - addend += addend_off; - rel->r_addend = addend; - bfd_put_32 (input_bfd, pinsn >> 32, - contents + offset); - bfd_put_32 (input_bfd, pinsn, - contents + offset + 4); - bfd_put_32 (input_bfd, pinsn2 >> 32, - contents + off2); - if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) - bfd_put_32 (input_bfd, pinsn2, - contents + off2 + 4); - } + bfd_put_32 (input_bfd, pinsn2, + contents + off2 + 4); } } } diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 547971f..a7230de 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -57,6 +57,9 @@ struct ppc64_elf_params /* Whether to use power10 instructions in linkage stubs. */ int power10_stubs; + /* Whether R_PPC64_PCREL_OPT should be ignored. */ + int no_pcrel_opt; + /* Whether to canonicalize .opd so that there are no overlapping .opd entries. */ int non_overlapping_opd; |