From 4a9699735b04d4629bd3dc418c265e7f0bc1f9ce Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 29 Aug 2018 13:28:21 +0930 Subject: [PATCH] PowerPC64 higher REL16 relocations There are occasions where someone might want to build a 64-bit pc-relative offset from 16-bit pieces. This adds the necessary REL16 relocs corresponding to existing ADDR16 relocs that can be used to build 64-bit absolute values. include/ * elf/ppc64.h (R_PPC64_REL16_HIGH, R_PPC64_REL16_HIGHA), (R_PPC64_REL16_HIGHER, R_PPC64_REL16_HIGHERA), (R_PPC64_REL16_HIGHEST, R_PPC64_REL16_HIGHESTA): Define. (R_PPC64_LO_DS_OPT, R_PPC64_16DX_HA): Bump value. bfd/ * reloc.c (BFD_RELOC_PPC64_REL16_HIGH, BFD_RELOC_PPC64_REL16_HIGHA), (BFD_RELOC_PPC64_REL16_HIGHER, BFD_RELOC_PPC64_REL16_HIGHERA), (BFD_RELOC_PPC64_REL16_HIGHEST, BFD_RELOC_PPC64_REL16_HIGHESTA): Define. * elf64-ppc.c (ppc64_elf_howto_raw): Add new REL16 howtos. (ppc64_elf_reloc_type_lookup): Translate new REL16 relocs. (ppc64_elf_check_relocs, ppc64_elf_relocate_section): Handle them. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. gas/ * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Allow ADDR16 HIGH, HIGHA, HIGHER, HIGHERA, HIGHEST, and HIGHESTA relocs. Group 16-bit relocs. * config/tc-ppc.c (md_apply_fix): Translate those ADDR16 relocs to REL16 when pcrel. Sort relocs. --- bfd/ChangeLog | 12 ++++++++++++ bfd/bfd-in2.h | 6 ++++++ bfd/elf64-ppc.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ bfd/libbfd.h | 6 ++++++ bfd/reloc.c | 12 ++++++++++++ gas/ChangeLog | 8 ++++++++ gas/config/tc-ppc.c | 36 ++++++++++++++++++++++++++++++------ gas/config/tc-ppc.h | 20 +++++++++++++------- include/ChangeLog | 7 +++++++ include/elf/ppc64.h | 16 +++++++++++----- 10 files changed, 150 insertions(+), 18 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 35c4efa8f7..8538bcd943 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2018-08-31 Alan Modra + + * reloc.c (BFD_RELOC_PPC64_REL16_HIGH, BFD_RELOC_PPC64_REL16_HIGHA), + (BFD_RELOC_PPC64_REL16_HIGHER, BFD_RELOC_PPC64_REL16_HIGHERA), + (BFD_RELOC_PPC64_REL16_HIGHEST, BFD_RELOC_PPC64_REL16_HIGHESTA): + Define. + * elf64-ppc.c (ppc64_elf_howto_raw): Add new REL16 howtos. + (ppc64_elf_reloc_type_lookup): Translate new REL16 relocs. + (ppc64_elf_check_relocs, ppc64_elf_relocate_section): Handle them. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + 2018-08-31 Alan Modra * elf64-ppc.c: Correct _notoc stub comments. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 1412f8934f..e5f7101e52 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3436,6 +3436,12 @@ instruction. */ BFD_RELOC_PPC64_PLTGOT16_LO_DS, BFD_RELOC_PPC64_ADDR16_HIGH, BFD_RELOC_PPC64_ADDR16_HIGHA, + BFD_RELOC_PPC64_REL16_HIGH, + BFD_RELOC_PPC64_REL16_HIGHA, + BFD_RELOC_PPC64_REL16_HIGHER, + BFD_RELOC_PPC64_REL16_HIGHERA, + BFD_RELOC_PPC64_REL16_HIGHEST, + BFD_RELOC_PPC64_REL16_HIGHESTA, BFD_RELOC_PPC64_ADDR64_LOCAL, BFD_RELOC_PPC64_ENTRY, BFD_RELOC_PPC64_REL24_NOTOC, diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index e6fe2601da..5826c2288a 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -820,6 +820,24 @@ static reloc_howto_type ppc64_elf_howto_raw[] = HOW (R_PPC64_REL16_HA, 1, 16, 0xffff, 16, TRUE, signed, ppc64_elf_ha_reloc), + HOW (R_PPC64_REL16_HIGH, 1, 16, 0xffff, 16, TRUE, dont, + bfd_elf_generic_reloc), + + HOW (R_PPC64_REL16_HIGHA, 1, 16, 0xffff, 16, TRUE, dont, + ppc64_elf_ha_reloc), + + HOW (R_PPC64_REL16_HIGHER, 1, 16, 0xffff, 32, TRUE, dont, + bfd_elf_generic_reloc), + + HOW (R_PPC64_REL16_HIGHERA, 1, 16, 0xffff, 32, TRUE, dont, + ppc64_elf_ha_reloc), + + HOW (R_PPC64_REL16_HIGHEST, 1, 16, 0xffff, 48, TRUE, dont, + bfd_elf_generic_reloc), + + HOW (R_PPC64_REL16_HIGHESTA, 1, 16, 0xffff, 48, TRUE, dont, + ppc64_elf_ha_reloc), + /* Like R_PPC64_REL16_HA but for split field in addpcis. */ HOW (R_PPC64_REL16DX_HA, 2, 16, 0x1fffc1, 16, TRUE, signed, ppc64_elf_ha_reloc), @@ -1129,6 +1147,18 @@ ppc64_elf_reloc_type_lookup (bfd *abfd, break; case BFD_RELOC_HI16_S_PCREL: r = R_PPC64_REL16_HA; break; + case BFD_RELOC_PPC64_REL16_HIGH: r = R_PPC64_REL16_HIGH; + break; + case BFD_RELOC_PPC64_REL16_HIGHA: r = R_PPC64_REL16_HIGHA; + break; + case BFD_RELOC_PPC64_REL16_HIGHER: r = R_PPC64_REL16_HIGHER; + break; + case BFD_RELOC_PPC64_REL16_HIGHERA: r = R_PPC64_REL16_HIGHERA; + break; + case BFD_RELOC_PPC64_REL16_HIGHEST: r = R_PPC64_REL16_HIGHEST; + break; + case BFD_RELOC_PPC64_REL16_HIGHESTA: r = R_PPC64_REL16_HIGHESTA; + break; case BFD_RELOC_PPC_16DX_HA: r = R_PPC64_16DX_HA; break; case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC64_REL16DX_HA; @@ -4474,6 +4504,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_REL16_LO: case R_PPC64_REL16_HI: case R_PPC64_REL16_HA: + case R_PPC64_REL16_HIGH: + case R_PPC64_REL16_HIGHA: + case R_PPC64_REL16_HIGHER: + case R_PPC64_REL16_HIGHERA: + case R_PPC64_REL16_HIGHEST: + case R_PPC64_REL16_HIGHESTA: case R_PPC64_REL16DX_HA: break; @@ -14557,6 +14593,12 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_REL16_LO: case R_PPC64_REL16_HI: case R_PPC64_REL16_HA: + case R_PPC64_REL16_HIGH: + case R_PPC64_REL16_HIGHA: + case R_PPC64_REL16_HIGHER: + case R_PPC64_REL16_HIGHERA: + case R_PPC64_REL16_HIGHEST: + case R_PPC64_REL16_HIGHESTA: case R_PPC64_REL16DX_HA: break; @@ -15038,6 +15080,9 @@ ppc64_elf_relocate_section (bfd *output_bfd, break; case R_PPC64_REL16_HA: + case R_PPC64_REL16_HIGHA: + case R_PPC64_REL16_HIGHERA: + case R_PPC64_REL16_HIGHESTA: case R_PPC64_REL16DX_HA: case R_PPC64_ADDR16_HA: case R_PPC64_ADDR16_HIGHA: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6c1e1ea9a5..34f05dd2e7 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1467,6 +1467,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC64_PLTGOT16_LO_DS", "BFD_RELOC_PPC64_ADDR16_HIGH", "BFD_RELOC_PPC64_ADDR16_HIGHA", + "BFD_RELOC_PPC64_REL16_HIGH", + "BFD_RELOC_PPC64_REL16_HIGHA", + "BFD_RELOC_PPC64_REL16_HIGHER", + "BFD_RELOC_PPC64_REL16_HIGHERA", + "BFD_RELOC_PPC64_REL16_HIGHEST", + "BFD_RELOC_PPC64_REL16_HIGHESTA", "BFD_RELOC_PPC64_ADDR64_LOCAL", "BFD_RELOC_PPC64_ENTRY", "BFD_RELOC_PPC64_REL24_NOTOC", diff --git a/bfd/reloc.c b/bfd/reloc.c index 0dcf2be9a0..eba6091891 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2853,6 +2853,18 @@ ENUMX BFD_RELOC_PPC64_ADDR16_HIGH ENUMX BFD_RELOC_PPC64_ADDR16_HIGHA +ENUMX + BFD_RELOC_PPC64_REL16_HIGH +ENUMX + BFD_RELOC_PPC64_REL16_HIGHA +ENUMX + BFD_RELOC_PPC64_REL16_HIGHER +ENUMX + BFD_RELOC_PPC64_REL16_HIGHERA +ENUMX + BFD_RELOC_PPC64_REL16_HIGHEST +ENUMX + BFD_RELOC_PPC64_REL16_HIGHESTA ENUMX BFD_RELOC_PPC64_ADDR64_LOCAL ENUMX diff --git a/gas/ChangeLog b/gas/ChangeLog index d4ec42ba41..83249990b8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2018-08-31 Alan Modra + + * config/tc-ppc.h (TC_FORCE_RELOCATION_SUB_LOCAL): Allow ADDR16 + HIGH, HIGHA, HIGHER, HIGHERA, HIGHEST, and HIGHESTA relocs. + Group 16-bit relocs. + * config/tc-ppc.c (md_apply_fix): Translate those ADDR16 relocs + to REL16 when pcrel. Sort relocs. + 2018-08-31 H.J. Lu * testsuite/gas/elf/elf.exp: Pass -mx86-used-note=no to diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index d4cc2ff09e..a44b30068f 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -6624,6 +6624,18 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) { switch (fixP->fx_r_type) { + case BFD_RELOC_64: + fixP->fx_r_type = BFD_RELOC_64_PCREL; + break; + + case BFD_RELOC_32: + fixP->fx_r_type = BFD_RELOC_32_PCREL; + break; + + case BFD_RELOC_16: + fixP->fx_r_type = BFD_RELOC_16_PCREL; + break; + case BFD_RELOC_LO16: fixP->fx_r_type = BFD_RELOC_LO16_PCREL; break; @@ -6636,16 +6648,28 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL; break; - case BFD_RELOC_64: - fixP->fx_r_type = BFD_RELOC_64_PCREL; + case BFD_RELOC_PPC64_ADDR16_HIGH: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGH; break; - case BFD_RELOC_32: - fixP->fx_r_type = BFD_RELOC_32_PCREL; + case BFD_RELOC_PPC64_ADDR16_HIGHA: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHA; break; - case BFD_RELOC_16: - fixP->fx_r_type = BFD_RELOC_16_PCREL; + case BFD_RELOC_PPC64_HIGHER: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHER; + break; + + case BFD_RELOC_PPC64_HIGHER_S: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHERA; + break; + + case BFD_RELOC_PPC64_HIGHEST: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHEST; + break; + + case BFD_RELOC_PPC64_HIGHEST_S: + fixP->fx_r_type = BFD_RELOC_PPC64_REL16_HIGHESTA; break; case BFD_RELOC_PPC_16DX_HA: diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index cf627dec26..7047fe7491 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -264,13 +264,19 @@ extern int ppc_force_relocation (struct fix *); /* Don't allow the generic code to convert fixups involving the subtraction of a label in the current section to pc-relative if we don't have the necessary pc-relative relocation. */ -#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \ - (!((FIX)->fx_r_type == BFD_RELOC_LO16 \ - || (FIX)->fx_r_type == BFD_RELOC_HI16 \ - || (FIX)->fx_r_type == BFD_RELOC_HI16_S \ - || (FIX)->fx_r_type == BFD_RELOC_64 \ - || (FIX)->fx_r_type == BFD_RELOC_32 \ - || (FIX)->fx_r_type == BFD_RELOC_16 \ +#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \ + (!((FIX)->fx_r_type == BFD_RELOC_64 \ + || (FIX)->fx_r_type == BFD_RELOC_32 \ + || (FIX)->fx_r_type == BFD_RELOC_16 \ + || (FIX)->fx_r_type == BFD_RELOC_LO16 \ + || (FIX)->fx_r_type == BFD_RELOC_HI16 \ + || (FIX)->fx_r_type == BFD_RELOC_HI16_S \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGH \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_ADDR16_HIGHA \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHER_S \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST \ + || (FIX)->fx_r_type == BFD_RELOC_PPC64_HIGHEST_S \ || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA)) #endif diff --git a/include/ChangeLog b/include/ChangeLog index b8fcefdf6e..63fdde6349 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,10 @@ +2018-08-31 Alan Modra + + * elf/ppc64.h (R_PPC64_REL16_HIGH, R_PPC64_REL16_HIGHA), + (R_PPC64_REL16_HIGHER, R_PPC64_REL16_HIGHERA), + (R_PPC64_REL16_HIGHEST, R_PPC64_REL16_HIGHESTA): Define. + (R_PPC64_LO_DS_OPT, R_PPC64_16DX_HA): Bump value. + 2018-08-30 Kito Cheng * opcode/riscv.h (MAX_SUBSET_NUM): New. diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h index 387c1d6404..700c9a4403 100644 --- a/include/elf/ppc64.h +++ b/include/elf/ppc64.h @@ -159,14 +159,20 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type) RELOC_NUMBER (R_PPC64_PLTCALL, 120) #ifndef RELOC_MACROS_GEN_FUNC -/* Relocation only used internally by ld. If you need to use these - reloc numbers, you can change them to some other unused value +/* Relocation only used internally by gas or ld. If you need to use + these reloc numbers, you can change them to some other unused value without affecting the ABI. They will never appear in object files. */ - RELOC_NUMBER (R_PPC64_LO_DS_OPT, 128) -/* Reloc only used internally by gas. As above, value is unimportant. */ - RELOC_NUMBER (R_PPC64_16DX_HA, 129) + RELOC_NUMBER (R_PPC64_LO_DS_OPT, 200) + RELOC_NUMBER (R_PPC64_16DX_HA, 201) #endif + RELOC_NUMBER (R_PPC64_REL16_HIGH, 240) + RELOC_NUMBER (R_PPC64_REL16_HIGHA, 241) + RELOC_NUMBER (R_PPC64_REL16_HIGHER, 242) + RELOC_NUMBER (R_PPC64_REL16_HIGHERA, 243) + RELOC_NUMBER (R_PPC64_REL16_HIGHEST, 244) + RELOC_NUMBER (R_PPC64_REL16_HIGHESTA, 245) + /* Power9 split rel16 for addpcis. */ RELOC_NUMBER (R_PPC64_REL16DX_HA, 246)