Blame SOURCES/gdb-rhbz1125820-ppc64le-enablement-10of37.patch

7ab123
commit b9e5796b0d6ebc355e4a6d06791b7366939d10f2
7ab123
Author: Alan Modra <amodra@gmail.com>
7ab123
Date:   Tue Oct 29 15:58:05 2013 +1030
7ab123
7ab123
    ELFv2 stub, plt and glink changes
7ab123
    
7ab123
    An ELFv2 PLT entry is simply the address of the target function rather
7ab123
    than three (or two) words to specify entry, toc and static chain.  PLT
7ab123
    call stubs are correspondingly simpler and need no thread safety
7ab123
    barrier.  The glink resolver stub and branch table also is simplified,
7ab123
    a change that could be applied to ELFv1 too, but isn't as yet.
7ab123
    
7ab123
    	* elf64-ppc.c (PLT_ENTRY_SIZE, PLT_INITIAL_ENTRY_SIZE): Add htab
7ab123
    	parameter and adjust for ELFv2.  Update all uses.
7ab123
    	(PLT_CALL_STUB_SIZE): Delete.
7ab123
    	(ppc64_elf_get_synthetic_symtab): Support new glink layout.
7ab123
    	(allocate_dynrelocs): Likewise.
7ab123
    	(plt_stub_size, build_plt_stub): Adjust for ELFv2.
7ab123
    	(get_r2off): Return 0 for ELFv2 -R.
7ab123
    	(ppc_build_one_stub, ppc_size_one_stub): Adjust for ELFv2.
7ab123
    	(ppc64_elf_size_stubs): Likewise.
7ab123
    	(ppc64_elf_build_stubs): Add new ELFv2 glink.
7ab123
7ab123
Index: gdb-7.6.1/bfd/elf64-ppc.c
7ab123
===================================================================
7ab123
--- gdb-7.6.1.orig/bfd/elf64-ppc.c
7ab123
+++ gdb-7.6.1/bfd/elf64-ppc.c
7ab123
@@ -125,10 +125,10 @@ static bfd_vma opd_entry_value
7ab123
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
7ab123
 
7ab123
 /* The size in bytes of an entry in the procedure linkage table.  */
7ab123
-#define PLT_ENTRY_SIZE 24
7ab123
+#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8)
7ab123
 
7ab123
 /* The initial size of the plt reserved for the dynamic linker.  */
7ab123
-#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE
7ab123
+#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
7ab123
 
7ab123
 /* TOC base pointers offset from start of TOC.  */
7ab123
 #define TOC_BASE_OFF	0x8000
7ab123
@@ -140,7 +140,6 @@ static bfd_vma opd_entry_value
7ab123
 /* .plt call stub instructions.  The normal stub is like this, but
7ab123
    sometimes the .plt entry crosses a 64k boundary and we need to
7ab123
    insert an addi to adjust r11.  */
7ab123
-#define PLT_CALL_STUB_SIZE (7*4)
7ab123
 #define STD_R2_40R1	0xf8410028	/* std	 %r2,40(%r1)	     */
7ab123
 #define ADDIS_R11_R2	0x3d620000	/* addis %r11,%r2,xxx@ha     */
7ab123
 #define LD_R12_0R11	0xe98b0000	/* ld	 %r12,xxx+0@l(%r11)  */
7ab123
@@ -184,6 +183,11 @@ static bfd_vma opd_entry_value
7ab123
 					/*  mtctr %12			*/
7ab123
 					/*  ld %11,16(%11)		*/
7ab123
 					/*  bctr			*/
7ab123
+#define MFLR_R0		0x7c0802a6	/*  mflr %r0			*/
7ab123
+#define MTLR_R0		0x7c0803a6	/*  mtlr %r0			*/
7ab123
+#define SUB_R12_R12_R11	0x7d8b6050	/*  subf %r12,%r11,%r12		*/
7ab123
+#define ADDI_R0_R12	0x380c0000	/*  addi %r0,%r12,0		*/
7ab123
+#define SRDI_R0_R0_2	0x7800f082	/*  rldicl %r0,%r0,62,2		*/
7ab123
 
7ab123
 /* Pad with this.  */
7ab123
 #define NOP		0x60000000
7ab123
@@ -3238,9 +3242,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
7ab123
 
7ab123
 	      if (dyn.d_tag == DT_PPC64_GLINK)
7ab123
 		{
7ab123
-		  /* The first glink stub starts at offset 32; see comment in
7ab123
-		     ppc64_elf_finish_dynamic_sections. */
7ab123
-		  glink_vma = dyn.d_un.d_val + 32;
7ab123
+		  /* The first glink stub starts at offset 32; see
7ab123
+		     comment in ppc64_elf_finish_dynamic_sections. */
7ab123
+		  glink_vma = dyn.d_un.d_val + GLINK_CALL_STUB_SIZE - 8 * 4;
7ab123
 		  /* The .glink section usually does not survive the final
7ab123
 		     link; search for the section (usually .text) where the
7ab123
 		     glink stubs now reside.  */
7ab123
@@ -3258,13 +3262,21 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
7ab123
 	  /* Determine __glink trampoline by reading the relative branch
7ab123
 	     from the first glink stub.  */
7ab123
 	  bfd_byte buf[4];
7ab123
-	  if (bfd_get_section_contents (abfd, glink, buf,
7ab123
-					glink_vma + 4 - glink->vma, 4))
7ab123
+	  unsigned int off = 0;
7ab123
+
7ab123
+	  while (bfd_get_section_contents (abfd, glink, buf,
7ab123
+					   glink_vma + off - glink->vma, 4))
7ab123
 	    {
7ab123
 	      unsigned int insn = bfd_get_32 (abfd, buf);
7ab123
 	      insn ^= B_DOT;
7ab123
 	      if ((insn & ~0x3fffffc) == 0)
7ab123
-		resolv_vma = glink_vma + 4 + (insn ^ 0x2000000) - 0x2000000;
7ab123
+		{
7ab123
+		  resolv_vma = glink_vma + off + (insn ^ 0x2000000) - 0x2000000;
7ab123
+		  break;
7ab123
+		}
7ab123
+	      off += 4;
7ab123
+	      if (off > 4)
7ab123
+		break;
7ab123
 	    }
7ab123
 
7ab123
 	  if (resolv_vma)
7ab123
@@ -3417,8 +3429,13 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
7ab123
 	      memcpy (names, "@plt", sizeof ("@plt"));
7ab123
 	      names += sizeof ("@plt");
7ab123
 	      s++;
7ab123
-	      glink_vma += 8;
7ab123
-	      if (i >= 0x8000)
7ab123
+	      if (abi < 2)
7ab123
+		{
7ab123
+		  glink_vma += 8;
7ab123
+		  if (i >= 0x8000)
7ab123
+		    glink_vma += 4;
7ab123
+		}
7ab123
+	      else
7ab123
 		glink_vma += 4;
7ab123
 	    }
7ab123
 	  count += plt_count;
7ab123
@@ -9021,7 +9038,7 @@ allocate_dynrelocs (struct elf_link_hash
7ab123
 	      {
7ab123
 		s = htab->iplt;
7ab123
 		pent->plt.offset = s->size;
7ab123
-		s->size += PLT_ENTRY_SIZE;
7ab123
+		s->size += PLT_ENTRY_SIZE (htab);
7ab123
 		s = htab->reliplt;
7ab123
 	      }
7ab123
 	    else
7ab123
@@ -9030,21 +9047,26 @@ allocate_dynrelocs (struct elf_link_hash
7ab123
 		   first entry.  */
7ab123
 		s = htab->plt;
7ab123
 		if (s->size == 0)
7ab123
-		  s->size += PLT_INITIAL_ENTRY_SIZE;
7ab123
+		  s->size += PLT_INITIAL_ENTRY_SIZE (htab);
7ab123
 
7ab123
 		pent->plt.offset = s->size;
7ab123
 
7ab123
 		/* Make room for this entry.  */
7ab123
-		s->size += PLT_ENTRY_SIZE;
7ab123
+		s->size += PLT_ENTRY_SIZE (htab);
7ab123
 
7ab123
 		/* Make room for the .glink code.  */
7ab123
 		s = htab->glink;
7ab123
 		if (s->size == 0)
7ab123
 		  s->size += GLINK_CALL_STUB_SIZE;
7ab123
-		/* We need bigger stubs past index 32767.  */
7ab123
-		if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
7ab123
+		if (htab->opd_abi)
7ab123
+		  {
7ab123
+		    /* We need bigger stubs past index 32767.  */
7ab123
+		    if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
7ab123
+		      s->size += 4;
7ab123
+		    s->size += 2*4;
7ab123
+		  }
7ab123
+		else
7ab123
 		  s->size += 4;
7ab123
-		s->size += 2*4;
7ab123
 
7ab123
 		/* We also need to make an entry in the .rela.plt section.  */
7ab123
 		s = htab->relplt;
7ab123
@@ -9393,7 +9415,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
7ab123
 	      {
7ab123
 		s = htab->iplt;
7ab123
 		ent->plt.offset = s->size;
7ab123
-		s->size += PLT_ENTRY_SIZE;
7ab123
+		s->size += PLT_ENTRY_SIZE (htab);
7ab123
 
7ab123
 		htab->reliplt->size += sizeof (Elf64_External_Rela);
7ab123
 	      }
7ab123
@@ -9727,19 +9749,23 @@ plt_stub_size (struct ppc_link_hash_tabl
7ab123
 	       struct ppc_stub_hash_entry *stub_entry,
7ab123
 	       bfd_vma off)
7ab123
 {
7ab123
-  unsigned size = PLT_CALL_STUB_SIZE;
7ab123
+  unsigned size = 12;
7ab123
 
7ab123
-  if (!(ALWAYS_EMIT_R2SAVE
7ab123
-	|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
7ab123
-    size -= 4;
7ab123
-  if (!htab->plt_static_chain)
7ab123
-    size -= 4;
7ab123
-  if (htab->plt_thread_safe)
7ab123
-    size += 8;
7ab123
-  if (PPC_HA (off) == 0)
7ab123
-    size -= 4;
7ab123
-  if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
7ab123
+  if (ALWAYS_EMIT_R2SAVE
7ab123
+      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
7ab123
     size += 4;
7ab123
+  if (PPC_HA (off) != 0)
7ab123
+    size += 4;
7ab123
+  if (htab->opd_abi)
7ab123
+    {
7ab123
+      size += 4;
7ab123
+      if (htab->plt_static_chain)
7ab123
+	size += 4;
7ab123
+      if (htab->plt_thread_safe)
7ab123
+	size += 8;
7ab123
+      if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
7ab123
+	size += 4;
7ab123
+    }
7ab123
   if (stub_entry->h != NULL
7ab123
       && (stub_entry->h == htab->tls_get_addr_fd
7ab123
 	  || stub_entry->h == htab->tls_get_addr)
7ab123
@@ -9773,12 +9799,14 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 		bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
7ab123
 {
7ab123
   bfd *obfd = htab->stub_bfd;
7ab123
+  bfd_boolean plt_load_toc = htab->opd_abi;
7ab123
   bfd_boolean plt_static_chain = htab->plt_static_chain;
7ab123
   bfd_boolean plt_thread_safe = htab->plt_thread_safe;
7ab123
   bfd_boolean use_fake_dep = plt_thread_safe;
7ab123
   bfd_vma cmp_branch_off = 0;
7ab123
 
7ab123
   if (!ALWAYS_USE_FAKE_DEP
7ab123
+      && plt_load_toc
7ab123
       && plt_thread_safe
7ab123
       && !(stub_entry->h != NULL
7ab123
 	   && (stub_entry->h == htab->tls_get_addr_fd
7ab123
@@ -9786,7 +9814,8 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 	   && !htab->no_tls_get_addr_opt))
7ab123
     {
7ab123
       bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
7ab123
-      bfd_vma pltindex = (pltoff - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE;
7ab123
+      bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
7ab123
+			  / PLT_ENTRY_SIZE (htab));
7ab123
       bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
7ab123
       bfd_vma to, from;
7ab123
 
7ab123
@@ -9820,22 +9849,25 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 	  r[1].r_offset = r[0].r_offset + 4;
7ab123
 	  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
7ab123
 	  r[1].r_addend = r[0].r_addend;
7ab123
-	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
-	    {
7ab123
-	      r[2].r_offset = r[1].r_offset + 4;
7ab123
-	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
7ab123
-	      r[2].r_addend = r[0].r_addend;
7ab123
-	    }
7ab123
-	  else
7ab123
+	  if (plt_load_toc)
7ab123
 	    {
7ab123
-	      r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
7ab123
-	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
7ab123
-	      r[2].r_addend = r[0].r_addend + 8;
7ab123
-	      if (plt_static_chain)
7ab123
-		{
7ab123
-		  r[3].r_offset = r[2].r_offset + 4;
7ab123
-		  r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
7ab123
-		  r[3].r_addend = r[0].r_addend + 16;
7ab123
+	      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
+		{
7ab123
+		  r[2].r_offset = r[1].r_offset + 4;
7ab123
+		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
7ab123
+		  r[2].r_addend = r[0].r_addend;
7ab123
+		}
7ab123
+	      else
7ab123
+		{
7ab123
+		  r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
7ab123
+		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
7ab123
+		  r[2].r_addend = r[0].r_addend + 8;
7ab123
+		  if (plt_static_chain)
7ab123
+		    {
7ab123
+		      r[3].r_offset = r[2].r_offset + 4;
7ab123
+		      r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
7ab123
+		      r[3].r_addend = r[0].r_addend + 16;
7ab123
+		    }
7ab123
 		}
7ab123
 	    }
7ab123
 	}
7ab123
@@ -9844,20 +9876,24 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 	bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
7ab123
       bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p),	p += 4;
7ab123
       bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p),	p += 4;
7ab123
-      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
+      if (plt_load_toc
7ab123
+	  && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
 	{
7ab123
 	  bfd_put_32 (obfd, ADDI_R11_R11 | PPC_LO (offset), p),	p += 4;
7ab123
 	  offset = 0;
7ab123
 	}
7ab123
       bfd_put_32 (obfd, MTCTR_R12, p),				p += 4;
7ab123
-      if (use_fake_dep)
7ab123
+      if (plt_load_toc)
7ab123
 	{
7ab123
-	  bfd_put_32 (obfd, XOR_R2_R12_R12, p),			p += 4;
7ab123
-	  bfd_put_32 (obfd, ADD_R11_R11_R2, p),			p += 4;
7ab123
+	  if (use_fake_dep)
7ab123
+	    {
7ab123
+	      bfd_put_32 (obfd, XOR_R2_R12_R12, p),		p += 4;
7ab123
+	      bfd_put_32 (obfd, ADD_R11_R11_R2, p),		p += 4;
7ab123
+	    }
7ab123
+	  bfd_put_32 (obfd, LD_R2_0R11 | PPC_LO (offset + 8), p), p += 4;
7ab123
+	  if (plt_static_chain)
7ab123
+	    bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
7ab123
 	}
7ab123
-      bfd_put_32 (obfd, LD_R2_0R11 | PPC_LO (offset + 8), p),	p += 4;
7ab123
-      if (plt_static_chain)
7ab123
-	bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
7ab123
     }
7ab123
   else
7ab123
     {
7ab123
@@ -9867,22 +9903,25 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 	      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
7ab123
 	    r[0].r_offset += 4;
7ab123
 	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
-	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
+	  if (plt_load_toc)
7ab123
 	    {
7ab123
-	      r[1].r_offset = r[0].r_offset + 4;
7ab123
-	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
7ab123
-	      r[1].r_addend = r[0].r_addend;
7ab123
-	    }
7ab123
-	  else
7ab123
-	    {
7ab123
-	      r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
7ab123
-	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
-	      r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
7ab123
-	      if (plt_static_chain)
7ab123
+	      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
 		{
7ab123
-		  r[2].r_offset = r[1].r_offset + 4;
7ab123
-		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
-		  r[2].r_addend = r[0].r_addend + 8;
7ab123
+		  r[1].r_offset = r[0].r_offset + 4;
7ab123
+		  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
7ab123
+		  r[1].r_addend = r[0].r_addend;
7ab123
+		}
7ab123
+	      else
7ab123
+		{
7ab123
+		  r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
7ab123
+		  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
+		  r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
7ab123
+		  if (plt_static_chain)
7ab123
+		    {
7ab123
+		      r[2].r_offset = r[1].r_offset + 4;
7ab123
+		      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
+		      r[2].r_addend = r[0].r_addend + 8;
7ab123
+		    }
7ab123
 		}
7ab123
 	    }
7ab123
 	}
7ab123
@@ -9890,22 +9929,26 @@ build_plt_stub (struct ppc_link_hash_tab
7ab123
 	  || stub_entry->stub_type == ppc_stub_plt_call_r2save)
7ab123
 	bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
7ab123
       bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (offset), p),	p += 4;
7ab123
-      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
+      if (plt_load_toc
7ab123
+	  && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
7ab123
 	{
7ab123
 	  bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p),	p += 4;
7ab123
 	  offset = 0;
7ab123
 	}
7ab123
       bfd_put_32 (obfd, MTCTR_R12, p),				p += 4;
7ab123
-      if (use_fake_dep)
7ab123
+      if (plt_load_toc)
7ab123
 	{
7ab123
-	  bfd_put_32 (obfd, XOR_R11_R12_R12, p),		p += 4;
7ab123
-	  bfd_put_32 (obfd, ADD_R2_R2_R11, p),			p += 4;
7ab123
+	  if (use_fake_dep)
7ab123
+	    {
7ab123
+	      bfd_put_32 (obfd, XOR_R11_R12_R12, p),		p += 4;
7ab123
+	      bfd_put_32 (obfd, ADD_R2_R2_R11, p),		p += 4;
7ab123
+	    }
7ab123
+	  if (plt_static_chain)
7ab123
+	    bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
7ab123
+	  bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
7ab123
 	}
7ab123
-      if (plt_static_chain)
7ab123
-	bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
7ab123
-      bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p),	p += 4;
7ab123
     }
7ab123
-  if (plt_thread_safe && !use_fake_dep)
7ab123
+  if (plt_load_toc && plt_thread_safe && !use_fake_dep)
7ab123
     {
7ab123
       bfd_put_32 (obfd, CMPLDI_R2_0, p),			p += 4;
7ab123
       bfd_put_32 (obfd, BNECTR_P4, p),				p += 4;
7ab123
@@ -10004,6 +10047,8 @@ get_r2off (struct bfd_link_info *info,
7ab123
       /* Support linking -R objects.  Get the toc pointer from the
7ab123
 	 opd entry.  */
7ab123
       char buf[8];
7ab123
+      if (!htab->opd_abi)
7ab123
+	return r2off;
7ab123
       asection *opd = stub_entry->h->elf.root.u.def.section;
7ab123
       bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
7ab123
 
7ab123
@@ -10233,7 +10278,8 @@ ppc_build_one_stub (struct bfd_hash_entr
7ab123
 	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
7ab123
 	  if (bfd_big_endian (info->output_bfd))
7ab123
 	    r[0].r_offset += 2;
7ab123
-	  if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
7ab123
+	  if (stub_entry->stub_type == ppc_stub_plt_branch_r2off
7ab123
+	      && htab->opd_abi)
7ab123
 	    r[0].r_offset += 4;
7ab123
 	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
7ab123
 	  r[0].r_addend = dest;
7ab123
@@ -10246,7 +10292,8 @@ ppc_build_one_stub (struct bfd_hash_entr
7ab123
 	    }
7ab123
 	}
7ab123
 
7ab123
-      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
7ab123
+      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
7ab123
+	  || !htab->opd_abi)
7ab123
 	{
7ab123
 	  if (PPC_HA (off) != 0)
7ab123
 	    {
7ab123
@@ -10497,10 +10544,11 @@ ppc_size_one_stub (struct bfd_hash_entry
7ab123
       if (info->emitrelocations)
7ab123
 	{
7ab123
 	  stub_entry->stub_sec->reloc_count
7ab123
-	    += (2
7ab123
-		+ (PPC_HA (off) != 0)
7ab123
-		+ (htab->plt_static_chain
7ab123
-		   && PPC_HA (off + 16) == PPC_HA (off)));
7ab123
+	    += ((PPC_HA (off) != 0)
7ab123
+		+ (htab->opd_abi
7ab123
+		   ? 2 + (htab->plt_static_chain
7ab123
+			  && PPC_HA (off + 16) == PPC_HA (off))
7ab123
+		   : 1));
7ab123
 	  stub_entry->stub_sec->flags |= SEC_RELOC;
7ab123
 	}
7ab123
     }
7ab123
@@ -10527,7 +10575,7 @@ ppc_size_one_stub (struct bfd_hash_entry
7ab123
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
7ab123
 	{
7ab123
 	  r2off = get_r2off (info, stub_entry);
7ab123
-	  if (r2off == 0)
7ab123
+	  if (r2off == 0 && htab->opd_abi)
7ab123
 	    {
7ab123
 	      htab->stub_error = TRUE;
7ab123
 	      return FALSE;
7ab123
@@ -10540,8 +10588,11 @@ ppc_size_one_stub (struct bfd_hash_entry
7ab123
 
7ab123
       local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
7ab123
 
7ab123
-      /* If the branch offset if too big, use a ppc_stub_plt_branch.  */
7ab123
-      if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off)
7ab123
+      /* If the branch offset if too big, use a ppc_stub_plt_branch.
7ab123
+	 Do the same for -R objects without function descriptors.  */
7ab123
+      if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
7ab123
+	  || (stub_entry->stub_type == ppc_stub_long_branch_r2off
7ab123
+	      && r2off == 0))
7ab123
 	{
7ab123
 	  struct ppc_branch_hash_entry *br_entry;
7ab123
 
7ab123
@@ -10584,7 +10635,8 @@ ppc_size_one_stub (struct bfd_hash_entry
7ab123
 	      stub_entry->stub_sec->flags |= SEC_RELOC;
7ab123
 	    }
7ab123
 
7ab123
-	  if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
7ab123
+	  if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
7ab123
+	      || !htab->opd_abi)
7ab123
 	    {
7ab123
 	      size = 12;
7ab123
 	      if (PPC_HA (off) != 0)
7ab123
@@ -11487,7 +11539,9 @@ ppc64_elf_size_stubs (struct bfd_link_in
7ab123
   htab->plt_stub_align = plt_stub_align;
7ab123
   if (plt_thread_safe == -1 && !info->executable)
7ab123
     plt_thread_safe = 1;
7ab123
-  if (plt_thread_safe == -1)
7ab123
+  if (!htab->opd_abi)
7ab123
+    plt_thread_safe = 0;
7ab123
+  else if (plt_thread_safe == -1)
7ab123
     {
7ab123
       static const char *const thread_starter[] =
7ab123
 	{
7ab123
@@ -12059,26 +12113,56 @@ ppc64_elf_build_stubs (bfd_boolean emit_
7ab123
       plt0 -= htab->glink->output_section->vma + htab->glink->output_offset;
7ab123
       bfd_put_64 (htab->glink->owner, plt0, p);
7ab123
       p += 8;
7ab123
-      bfd_put_32 (htab->glink->owner, MFLR_R12, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, BCL_20_31, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, MFLR_R11, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, MTLR_R12, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, LD_R2_0R11 | 8, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
7ab123
-      p += 4;
7ab123
-      bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
7ab123
-      p += 4;
7ab123
+      if (htab->opd_abi)
7ab123
+	{
7ab123
+	  bfd_put_32 (htab->glink->owner, MFLR_R12, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, BCL_20_31, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MFLR_R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MTLR_R12, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | 8, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
7ab123
+	  p += 4;
7ab123
+	}
7ab123
+      else
7ab123
+	{
7ab123
+	  bfd_put_32 (htab->glink->owner, MFLR_R0, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, BCL_20_31, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MFLR_R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MTLR_R0, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-48 & 0xffff), p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, SRDI_R0_R0_2, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
7ab123
+	  p += 4;
7ab123
+	  bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 8, p);
7ab123
+	  p += 4;
7ab123
+	}
7ab123
       bfd_put_32 (htab->glink->owner, BCTR, p);
7ab123
       p += 4;
7ab123
       while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
7ab123
@@ -12091,17 +12175,21 @@ ppc64_elf_build_stubs (bfd_boolean emit_
7ab123
       indx = 0;
7ab123
       while (p < htab->glink->contents + htab->glink->size)
7ab123
 	{
7ab123
-	  if (indx < 0x8000)
7ab123
-	    {
7ab123
-	      bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
7ab123
-	      p += 4;
7ab123
-	    }
7ab123
-	  else
7ab123
+	  if (htab->opd_abi)
7ab123
 	    {
7ab123
-	      bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
7ab123
-	      p += 4;
7ab123
-	      bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
7ab123
-	      p += 4;
7ab123
+	      if (indx < 0x8000)
7ab123
+		{
7ab123
+		  bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
7ab123
+		  p += 4;
7ab123
+		}
7ab123
+	      else
7ab123
+		{
7ab123
+		  bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
7ab123
+		  p += 4;
7ab123
+		  bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx),
7ab123
+			      p);
7ab123
+		  p += 4;
7ab123
+		}
7ab123
 	    }
7ab123
 	  bfd_put_32 (htab->glink->owner,
7ab123
 		      B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
7ab123
@@ -14192,8 +14280,8 @@ ppc64_elf_finish_dynamic_symbol (bfd *ou
7ab123
 	    rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
7ab123
 	    rela.r_addend = ent->addend;
7ab123
 	    loc = (htab->relplt->contents
7ab123
-		   + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
7ab123
-		      / (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
7ab123
+		   + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
7ab123
+		      / PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
7ab123
 	  }
7ab123
 	bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
7ab123
       }
7ab123
@@ -14288,7 +14376,7 @@ ppc64_elf_finish_dynamic_sections (bfd *
7ab123
 		 of glink rather than the first entry point, which is
7ab123
 		 what ld.so needs, and now have a bigger stub to
7ab123
 		 support automatic multiple TOCs.  */
7ab123
-	      dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32;
7ab123
+	      dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 8 * 4;
7ab123
 	      break;
7ab123
 
7ab123
 	    case DT_PPC64_OPD:
7ab123
@@ -14361,7 +14449,7 @@ ppc64_elf_finish_dynamic_sections (bfd *
7ab123
     {
7ab123
       /* Set .plt entry size.  */
7ab123
       elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
7ab123
-	= PLT_ENTRY_SIZE;
7ab123
+	= PLT_ENTRY_SIZE (htab);
7ab123
     }
7ab123
 
7ab123
   /* brlt is SEC_LINKER_CREATED, so we need to write out relocs for