R_PPC64_ENTRY

Alan Modra amodra@gmail.com
Wed Nov 25 01:43:00 GMT 2015


Add a new relocation that marks large-model entry code, for edit back
to medium-model.

include/elf/
	* ppc64.h (R_PPC64_ENTRY): Define.
bfd/
	* reloc.c (BFD_RELOC_PPC64_ENTRY): New.
	* elf64-ppc.c (reloc_howto_type ppc64_elf_howto_raw): Add
	entry for R_PPC64_ENTRY.
	(LD_R2_0R12, ADD_R2_R2_R12, LIS_R2, ADDIS_R2_R12): Define.
	(ppc64_elf_reloc_type_lookup): Handle R_PPC64_ENTRY.
	(ppc64_elf_relocate_section): Edit code at R_PPC64_ENTTY.  Use
	new insn defines.
	* libbfd.h: Regenerate.
	* bfd-in2.h: Regenerate.

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index db54efe..606d11b 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3330,6 +3330,7 @@ instruction.  */
   BFD_RELOC_PPC64_ADDR16_HIGH,
   BFD_RELOC_PPC64_ADDR16_HIGHA,
   BFD_RELOC_PPC64_ADDR64_LOCAL,
+  BFD_RELOC_PPC64_ENTRY,
 
 /* PowerPC and PowerPC64 thread-local storage relocations.  */
   BFD_RELOC_PPC_TLS,
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 42356d8..303236e 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -173,8 +173,12 @@ static bfd_vma opd_entry_value
 #define LD_R2_0R2	0xe8420000	/* ld	 %r2,xxx+0(%r2)  */
 
 #define LD_R2_0R1	0xe8410000	/* ld    %r2,0(%r1)      */
+#define LD_R2_0R12	0xe84c0000	/* ld    %r2,0(%r12)     */
+#define ADD_R2_R2_R12	0x7c426214	/* add   %r2,%r2,%r12    */
 
-#define ADDIS_R12_R2	0x3d820000	/* addis %r12,%r2,xxx@ha     */
+#define LIS_R2		0x3c400000	/* lis %r2,xxx@ha         */
+#define ADDIS_R2_R12	0x3c4c0000	/* addis %r2,%r12,xxx@ha  */
+#define ADDIS_R12_R2	0x3d820000	/* addis %r12,%r2,xxx@ha  */
 #define ADDIS_R12_R12	0x3d8c0000	/* addis %r12,%r12,xxx@ha */
 #define LD_R12_0R12	0xe98c0000	/* ld    %r12,xxx@l(%r12) */
 
@@ -2127,6 +2131,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 0xffff,		/* dst_mask */
 	 FALSE),		/* pcrel_offset */
 
+  /* Marker reloc on ELFv2 large-model function entry.  */
+  HOWTO (R_PPC64_ENTRY,
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_PPC64_ENTRY",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
   /* Like ADDR64, but use local entry point of function.  */
   HOWTO (R_PPC64_ADDR64_LOCAL,	/* type */
 	 0,			/* rightshift */
@@ -2429,6 +2448,8 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       break;
     case BFD_RELOC_PPC_REL16DX_HA:		r = R_PPC64_REL16DX_HA;
       break;
+    case BFD_RELOC_PPC64_ENTRY:			r = R_PPC64_ENTRY;
+      break;
     case BFD_RELOC_PPC64_ADDR64_LOCAL:		r = R_PPC64_ADDR64_LOCAL;
       break;
     case BFD_RELOC_VTABLE_INHERIT:		r = R_PPC64_GNU_VTINHERIT;
@@ -5575,6 +5596,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	  sec->has_toc_reloc = 1;
 	  break;
 
+	  /* Marker reloc.  */
+	case R_PPC64_ENTRY:
+	  break;
+
 	  /* This relocation describes the C++ object vtable hierarchy.
 	     Reconstruct it for later use during GC.  */
 	case R_PPC64_GNU_VTINHERIT:
@@ -13848,6 +13873,52 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	    }
 	  break;
 
+	case R_PPC64_ENTRY:
+	  relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
+	  if (!bfd_link_pic (info)
+	      && !info->traditional_format
+	      && relocation + 0x80008000 <= 0xffffffff)
+	    {
+	      unsigned int insn1, insn2;
+
+	      insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+	      insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+	      if ((insn1 & ~0xfffc) == LD_R2_0R12
+		  && insn2 == ADD_R2_R2_R12)
+		{
+		  bfd_put_32 (output_bfd,
+			      LIS_R2 + PPC_HA (relocation),
+			      contents + rel->r_offset);
+		  bfd_put_32 (output_bfd,
+			      ADDI_R2_R2 + PPC_LO (relocation),
+			      contents + rel->r_offset + 4);
+		}
+	    }
+	  else
+	    {
+	      relocation -= (rel->r_offset
+			     + input_section->output_offset
+			     + input_section->output_section->vma);
+	      if (relocation + 0x80008000 <= 0xffffffff)
+		{
+		  unsigned int insn1, insn2;
+
+		  insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
+		  insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
+		  if ((insn1 & ~0xfffc) == LD_R2_0R12
+		      && insn2 == ADD_R2_R2_R12)
+		    {
+		      bfd_put_32 (output_bfd,
+				  ADDIS_R2_R12 + PPC_HA (relocation),
+				  contents + rel->r_offset);
+		      bfd_put_32 (output_bfd,
+				  ADDI_R2_R2 + PPC_LO (relocation),
+				  contents + rel->r_offset + 4);
+		    }
+		}
+	    }
+	  break;
+
 	case R_PPC64_REL16_HA:
 	  /* If we are generating a non-PIC executable, edit
 	     .	0:	addis 2,12,.TOC.-0b@ha
@@ -13858,6 +13929,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	     if .TOC. is in range.  */
 	  if (!bfd_link_pic (info)
 	      && !info->traditional_format
+	      && !htab->opd_abi
 	      && h != NULL && &h->elf == htab->elf.hgot
 	      && rel + 1 < relend
 	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
@@ -13869,15 +13941,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	      bfd_vma offset = rel->r_offset - d_offset;
 	      insn1 = bfd_get_32 (output_bfd, contents + offset);
 	      insn2 = bfd_get_32 (output_bfd, contents + offset + 4);
-	      if ((insn1 & 0xffff0000) == 0x3c4c0000 /* addis 2,12 */
-		  && (insn2 & 0xffff0000) == 0x38420000 /* addi 2,2 */)
+	      if ((insn1 & 0xffff0000) == ADDIS_R2_R12
+		  && (insn2 & 0xffff0000) == ADDI_R2_R2)
 		{
 		  r_type = R_PPC64_ADDR16_HA;
 		  rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 		  rel->r_addend -= d_offset;
 		  rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_ADDR16_LO);
 		  rel[1].r_addend -= d_offset + 4;
-		  bfd_put_32 (output_bfd, 0x3c400000, contents + offset);
+		  bfd_put_32 (output_bfd, LIS_R2, contents + offset);
 		}
 	    }
 	  break;
@@ -14174,6 +14246,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TOCSAVE:
 	case R_PPC64_GNU_VTINHERIT:
 	case R_PPC64_GNU_VTENTRY:
+	case R_PPC64_ENTRY:
 	  goto copy_reloc;
 
 	  /* GOT16 relocations.  Like an ADDR16 using the symbol's
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index a6ed64e..1c93c91 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1418,6 +1418,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_PPC64_ADDR16_HIGH",
   "BFD_RELOC_PPC64_ADDR16_HIGHA",
   "BFD_RELOC_PPC64_ADDR64_LOCAL",
+  "BFD_RELOC_PPC64_ENTRY",
   "BFD_RELOC_PPC_TLS",
   "BFD_RELOC_PPC_TLSGD",
   "BFD_RELOC_PPC_TLSLD",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 17c470e..593e7c7 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2943,6 +2943,8 @@ ENUMX
   BFD_RELOC_PPC64_ADDR16_HIGHA
 ENUMX
   BFD_RELOC_PPC64_ADDR64_LOCAL
+ENUMX
+  BFD_RELOC_PPC64_ENTRY
 ENUMDOC
   Power(rs6000) and PowerPC relocations.
 
diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h
index 2cc24cc..9b47b52 100644
--- a/include/elf/ppc64.h
+++ b/include/elf/ppc64.h
@@ -152,6 +152,7 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
 /* Added for ELFv2.  */
   RELOC_NUMBER (R_PPC64_REL24_NOTOC,	   116)
   RELOC_NUMBER (R_PPC64_ADDR64_LOCAL,	   117)
+  RELOC_NUMBER (R_PPC64_ENTRY,		   118)
 
 #ifndef RELOC_MACROS_GEN_FUNC
 /* Fake relocation only used internally by ld.  */

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list