From 6738c8a7c93cd77a0caa720c6cc21c422561be2c Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 12 Aug 2020 23:31:28 +0930 Subject: [PATCH] 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. --- bfd/ChangeLog | 7 +++ bfd/elf64-ppc.c | 116 +++++++++++++++++++-------------------- bfd/elf64-ppc.h | 3 + ld/ChangeLog | 7 +++ ld/emultempl/ppc64elf.em | 12 +++- 5 files changed, 86 insertions(+), 59 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0e22506e022..31a4c0be67d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2020-08-13 Alan Modra + + * 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 PR 26348 diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 4a75c25190e..5cbf9acfcd1 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 547971f8bec..a7230de81c0 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; diff --git a/ld/ChangeLog b/ld/ChangeLog index 64b2b637b22..71b0d45b140 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2020-08-13 Alan Modra + + * 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. + 2020-08-10 Nick Clifton PR ld/21351 diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 1331d03113b..42b9bd48fcc 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -38,7 +38,7 @@ static struct ppc64_elf_params params = { NULL, &ppc_layout_sections_again, 1, -1, -1, 0, ${DEFAULT_PLT_STATIC_CHAIN-0}, -1, 5, - -1, -1, 0, -1, -1, 0}; + -1, -1, 0, 0, -1, -1, 0}; /* Fake input file for stubs. */ static lang_input_statement_type *stub_file; @@ -686,6 +686,7 @@ enum ppc64_opt OPTION_NO_PLT_LOCALENTRY, OPTION_POWER10_STUBS, OPTION_NO_POWER10_STUBS, + OPTION_NO_PCREL_OPT, OPTION_STUBSYMS, OPTION_NO_STUBSYMS, OPTION_SAVRES, @@ -717,6 +718,7 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' { "plt-localentry", optional_argument, NULL, OPTION_PLT_LOCALENTRY }, { "no-plt-localentry", no_argument, NULL, OPTION_NO_PLT_LOCALENTRY }, { "power10-stubs", optional_argument, NULL, OPTION_POWER10_STUBS }, + { "no-pcrel-optimize", no_argument, NULL, OPTION_NO_PCREL_OPT }, { "no-power10-stubs", no_argument, NULL, OPTION_NO_POWER10_STUBS }, { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS }, { "no-emit-stub-syms", no_argument, NULL, OPTION_NO_STUBSYMS }, @@ -776,6 +778,9 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' --power10-stubs [=auto] Use Power10 PLT call stubs (default auto)\n" )); fprintf (file, _("\ + --no-pcrel-optimize Don'\''t perform R_PPC64_PCREL_OPT optimization\n" + )); + fprintf (file, _("\ --no-power10-stubs Don'\''t use Power10 PLT call stubs\n" )); fprintf (file, _("\ @@ -909,6 +914,10 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' params.power10_stubs = 0; break; + case OPTION_NO_PCREL_OPT: + params.no_pcrel_opt = 1; + break; + case OPTION_STUBSYMS: params.emit_stub_syms = 1; break; @@ -985,6 +994,7 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' params.no_multi_toc = 1; no_toc_sort = 1; params.plt_static_chain = 1; + params.no_pcrel_opt = 1; return FALSE; ' -- 2.30.2