This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.

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/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/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/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)
 

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]