Blob Blame History Raw
2014-03-12  Aldy Hernandez  <aldyh@redhat.com>

	* Partial PowerPC little endian patch for binutils.

diff --git a/IBM-binutils-2.24-2013-11-11-ppc64le_abiv2.patch.gz b/IBM-binutils-2.24-2013-11-11-ppc64le_abiv2.patch.gz
new file mode 100644
index 0000000..e869701
Binary files /dev/null and b/IBM-binutils-2.24-2013-11-11-ppc64le_abiv2.patch.gz differ
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8c9903f..af72703 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3189,6 +3189,8 @@ instruction.  */
   BFD_RELOC_PPC64_TOC16_LO_DS,
   BFD_RELOC_PPC64_PLTGOT16_DS,
   BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+  BFD_RELOC_PPC64_ADDR16_HIGH,
+  BFD_RELOC_PPC64_ADDR16_HIGHA,
 
 /* PowerPC and PowerPC64 thread-local storage relocations.  */
   BFD_RELOC_PPC_TLS,
@@ -3233,6 +3235,10 @@ instruction.  */
   BFD_RELOC_PPC64_DTPREL16_HIGHERA,
   BFD_RELOC_PPC64_DTPREL16_HIGHEST,
   BFD_RELOC_PPC64_DTPREL16_HIGHESTA,
+  BFD_RELOC_PPC64_TPREL16_HIGH,
+  BFD_RELOC_PPC64_TPREL16_HIGHA,
+  BFD_RELOC_PPC64_DTPREL16_HIGH,
+  BFD_RELOC_PPC64_DTPREL16_HIGHA,
 
 /* IBM 370/390 relocations  */
   BFD_RELOC_I370_D12,
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index fbc4e54..a3680f2 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6443,7 +6443,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	  if (!htab->no_tls_get_addr_opt
 	      && htab->tls_get_addr != NULL
 	      && htab->tls_get_addr->plt.plist != NULL
-	      && !add_dynamic_entry (DT_PPC_TLSOPT, 0))
+	      && !add_dynamic_entry (DT_PPC_OPT, PPC_OPT_TLS))
 	    return FALSE;
 	}
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 8872673..80c2a4d 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -81,7 +81,8 @@ static bfd_vma opd_entry_value
 #define bfd_elf64_mkobject		      ppc64_elf_mkobject
 #define bfd_elf64_bfd_reloc_type_lookup	      ppc64_elf_reloc_type_lookup
 #define bfd_elf64_bfd_reloc_name_lookup	      ppc64_elf_reloc_name_lookup
-#define bfd_elf64_bfd_merge_private_bfd_data  _bfd_generic_verify_endian_match
+#define bfd_elf64_bfd_merge_private_bfd_data  ppc64_elf_merge_private_bfd_data
+#define bfd_elf64_bfd_print_private_bfd_data  ppc64_elf_print_private_bfd_data
 #define bfd_elf64_new_section_hook	      ppc64_elf_new_section_hook
 #define bfd_elf64_bfd_link_hash_table_create  ppc64_elf_link_hash_table_create
 #define bfd_elf64_bfd_link_hash_table_free    ppc64_elf_link_hash_table_free
@@ -108,6 +109,7 @@ static bfd_vma opd_entry_value
 #define elf_backend_maybe_function_sym	      ppc64_elf_maybe_function_sym
 #define elf_backend_always_size_sections      ppc64_elf_func_desc_adjust
 #define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
+#define elf_backend_hash_symbol		      ppc64_elf_hash_symbol
 #define elf_backend_init_index_section	      _bfd_elf_init_2_index_sections
 #define elf_backend_action_discarded	      ppc64_elf_action_discarded
 #define elf_backend_relocate_section	      ppc64_elf_relocate_section
@@ -117,16 +119,25 @@ static bfd_vma opd_entry_value
 #define elf_backend_link_output_symbol_hook   ppc64_elf_output_symbol_hook
 #define elf_backend_special_sections	      ppc64_elf_special_sections
 #define elf_backend_post_process_headers      _bfd_elf_set_osabi
+#define elf_backend_merge_symbol_attribute    ppc64_elf_merge_symbol_attribute
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
 
 /* The size in bytes of an entry in the procedure linkage table.  */
-#define PLT_ENTRY_SIZE 24
+#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8)
 
 /* The initial size of the plt reserved for the dynamic linker.  */
-#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE
+#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
+
+/* Offsets to some stack save slots.  */
+#define STK_LR 16
+#define STK_TOC(htab) (htab->opd_abi ? 40 : 24)
+/* This one is dodgy.  ABIv2 does not have a linker word, so use the
+   CR save slot.  Used only by optimised __tls_get_addr call stub,
+   relying on __tls_get_addr_opt not saving CR..  */
+#define STK_LINKER(htab) (htab->opd_abi ? 32 : 8)
 
 /* TOC base pointers offset from start of TOC.  */
 #define TOC_BASE_OFF	0x8000
@@ -137,33 +148,35 @@ static bfd_vma opd_entry_value
 
 /* .plt call stub instructions.  The normal stub is like this, but
    sometimes the .plt entry crosses a 64k boundary and we need to
-   insert an addi to adjust r12.  */
-#define PLT_CALL_STUB_SIZE (7*4)
-#define ADDIS_R12_R2	0x3d820000	/* addis %r12,%r2,xxx@ha     */
-#define STD_R2_40R1	0xf8410028	/* std	 %r2,40(%r1)	     */
-#define LD_R11_0R12	0xe96c0000	/* ld	 %r11,xxx+0@l(%r12)  */
-#define MTCTR_R11	0x7d6903a6	/* mtctr %r11		     */
-#define LD_R2_0R12	0xe84c0000	/* ld	 %r2,xxx+8@l(%r12)   */
-					/* ld	 %r11,xxx+16@l(%r12) */
+   insert an addi to adjust r11.  */
+#define STD_R2_0R1	0xf8410000	/* std	 %r2,0+40(%r1)	     */
+#define ADDIS_R11_R2	0x3d620000	/* addis %r11,%r2,xxx@ha     */
+#define LD_R12_0R11	0xe98b0000	/* ld	 %r12,xxx+0@l(%r11)  */
+#define MTCTR_R12	0x7d8903a6	/* mtctr %r12		     */
+#define LD_R2_0R11	0xe84b0000	/* ld	 %r2,xxx+8@l(%r11)   */
+#define LD_R11_0R11	0xe96b0000	/* ld	 %r11,xxx+16@l(%r11) */
 #define BCTR		0x4e800420	/* bctr			     */
 
-
-#define ADDIS_R12_R12	0x3d8c0000	/* addis %r12,%r12,off@ha  */
-#define ADDI_R12_R12	0x398c0000	/* addi %r12,%r12,off@l  */
+#define ADDI_R11_R11	0x396b0000	/* addi %r11,%r11,off@l  */
 #define ADDIS_R2_R2	0x3c420000	/* addis %r2,%r2,off@ha  */
 #define ADDI_R2_R2	0x38420000	/* addi  %r2,%r2,off@l   */
 
-#define XOR_R11_R11_R11	0x7d6b5a78	/* xor   %r11,%r11,%r11  */
-#define ADD_R12_R12_R11	0x7d8c5a14	/* add   %r12,%r12,%r11  */
+#define XOR_R2_R12_R12	0x7d826278	/* xor   %r2,%r12,%r12   */
+#define ADD_R11_R11_R2	0x7d6b1214	/* add   %r11,%r11,%r2   */
+#define XOR_R11_R12_R12	0x7d8b6278	/* xor   %r11,%r12,%r12  */
 #define ADD_R2_R2_R11	0x7c425a14	/* add   %r2,%r2,%r11    */
 #define CMPLDI_R2_0	0x28220000	/* cmpldi %r2,0          */
 #define BNECTR		0x4ca20420	/* bnectr+               */
 #define BNECTR_P4	0x4ce20420	/* bnectr+               */
 
+#define LD_R12_0R2	0xe9820000	/* ld	 %r12,xxx+0(%r2) */
 #define LD_R11_0R2	0xe9620000	/* ld	 %r11,xxx+0(%r2) */
 #define LD_R2_0R2	0xe8420000	/* ld	 %r2,xxx+0(%r2)  */
 
-#define LD_R2_40R1	0xe8410028	/* ld    %r2,40(%r1)     */
+#define LD_R2_0R1	0xe8410000	/* ld    %r2,0(%r1)      */
+
+#define ADDIS_R12_R12	0x3d8c0000	/* addis %r12,%r12,xxx@ha */
+#define LD_R12_0R12	0xe98c0000	/* ld    %r12,xxx@l(%r12) */
 
 /* glink call stub instructions.  We enter with the index in R0.  */
 #define GLINK_CALL_STUB_SIZE (16*4)
@@ -174,14 +187,19 @@ static bfd_vma opd_entry_value
 #define BCL_20_31	0x429f0005	/*  bcl 20,31,1f		*/
 					/* 1:				*/
 #define MFLR_R11	0x7d6802a6	/*  mflr %11			*/
-#define LD_R2_M16R11	0xe84bfff0	/*  ld %2,(0b-1b)(%11)		*/
+					/*  ld %2,(0b-1b)(%11)		*/
 #define MTLR_R12	0x7d8803a6	/*  mtlr %12			*/
-#define ADD_R12_R2_R11	0x7d825a14	/*  add %12,%2,%11		*/
-					/*  ld %11,0(%12)		*/
-					/*  ld %2,8(%12)		*/
-					/*  mtctr %11			*/
-					/*  ld %11,16(%12)		*/
+#define ADD_R11_R2_R11	0x7d625a14	/*  add %11,%2,%11		*/
+					/*  ld %12,0(%11)		*/
+					/*  ld %2,8(%11)		*/
+					/*  mtctr %12			*/
+					/*  ld %11,16(%11)		*/
 					/*  bctr			*/
+#define MFLR_R0		0x7c0802a6	/*  mflr %r0			*/
+#define MTLR_R0		0x7c0803a6	/*  mtlr %r0			*/
+#define SUB_R12_R12_R11	0x7d8b6050	/*  subf %r12,%r11,%r12		*/
+#define ADDI_R0_R12	0x380c0000	/*  addi %r0,%r12,0		*/
+#define SRDI_R0_R0_2	0x7800f082	/*  rldicl %r0,%r0,62,2		*/
 
 /* Pad with this.  */
 #define NOP		0x60000000
@@ -309,7 +327,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 bfd_elf_generic_reloc,	/* special_function */
 	 "R_PPC64_ADDR16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -325,7 +343,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_ha_reloc,	/* special_function */
 	 "R_PPC64_ADDR16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -487,7 +505,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont,/* complain_on_overflow */
+	 complain_overflow_signed,/* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -503,7 +521,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont,/* complain_on_overflow */
+	 complain_overflow_signed,/* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -680,7 +698,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_PLT16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -696,7 +714,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_PLT16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -741,7 +759,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_sectoff_reloc, /* special_function */
 	 "R_PPC64_SECTOFF_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -756,7 +774,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_sectoff_ha_reloc, /* special_function */
 	 "R_PPC64_SECTOFF_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -963,7 +981,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_toc_reloc,	/* special_function */
 	 "R_PPC64_TOC16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -982,7 +1000,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_toc_ha_reloc, /* special_function */
 	 "R_PPC64_TOC16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1054,7 +1072,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_PLTGOT16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1072,7 +1090,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont,/* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_PLTGOT16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1374,7 +1392,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_DTPREL16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1389,7 +1407,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_DTPREL16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1540,7 +1558,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_TPREL16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1555,7 +1573,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_TPREL16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1692,7 +1710,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TLSGD16_HI", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1707,7 +1725,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TLSGD16_HA", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1754,7 +1772,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TLSLD16_HI", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1769,7 +1787,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TLSLD16_HA", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1815,7 +1833,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_DTPREL16_HI", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1830,7 +1848,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_DTPREL16_HA", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1876,7 +1894,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TPREL16_HI", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1891,7 +1909,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 FALSE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_unhandled_reloc, /* special_function */
 	 "R_PPC64_GOT_TPREL16_HA", /* name */
 	 FALSE,			/* partial_inplace */
@@ -1964,7 +1982,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 bfd_elf_generic_reloc,	/* special_function */
 	 "R_PPC64_REL16_HI",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1980,7 +1998,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 16,			/* bitsize */
 	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
-	 complain_overflow_dont, /* complain_on_overflow */
+	 complain_overflow_signed, /* complain_on_overflow */
 	 ppc64_elf_ha_reloc,	/* special_function */
 	 "R_PPC64_REL16_HA",	/* name */
 	 FALSE,			/* partial_inplace */
@@ -1988,6 +2006,96 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
 	 0xffff,		/* dst_mask */
 	 TRUE),			/* pcrel_offset */
 
+  /* Like R_PPC64_ADDR16_HI, but no overflow.  */
+  HOWTO (R_PPC64_ADDR16_HIGH,	/* type */
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special_function */
+	 "R_PPC64_ADDR16_HIGH",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Like R_PPC64_ADDR16_HA, but no overflow.  */
+  HOWTO (R_PPC64_ADDR16_HIGHA,	/* type */
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 ppc64_elf_ha_reloc,	/* special_function */
+	 "R_PPC64_ADDR16_HIGHA",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Like R_PPC64_DTPREL16_HI, but no overflow.  */
+  HOWTO (R_PPC64_DTPREL16_HIGH,
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 ppc64_elf_unhandled_reloc, /* special_function */
+	 "R_PPC64_DTPREL16_HIGH", /* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Like R_PPC64_DTPREL16_HA, but no overflow.  */
+  HOWTO (R_PPC64_DTPREL16_HIGHA,
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 ppc64_elf_unhandled_reloc, /* special_function */
+	 "R_PPC64_DTPREL16_HIGHA", /* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Like R_PPC64_TPREL16_HI, but no overflow.  */
+  HOWTO (R_PPC64_TPREL16_HIGH,
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 ppc64_elf_unhandled_reloc, /* special_function */
+	 "R_PPC64_TPREL16_HIGH",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
+  /* Like R_PPC64_TPREL16_HA, but no overflow.  */
+  HOWTO (R_PPC64_TPREL16_HIGHA,
+	 16,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 FALSE,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 ppc64_elf_unhandled_reloc, /* special_function */
+	 "R_PPC64_TPREL16_HIGHA",	/* name */
+	 FALSE,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 FALSE),		/* pcrel_offset */
+
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_PPC64_GNU_VTINHERIT,	/* type */
 	 0,			/* rightshift */
@@ -2066,8 +2174,12 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       break;
     case BFD_RELOC_HI16:			r = R_PPC64_ADDR16_HI;
       break;
+    case BFD_RELOC_PPC64_ADDR16_HIGH:		r = R_PPC64_ADDR16_HIGH;
+      break;
     case BFD_RELOC_HI16_S:			r = R_PPC64_ADDR16_HA;
       break;
+    case BFD_RELOC_PPC64_ADDR16_HIGHA:		r = R_PPC64_ADDR16_HIGHA;
+      break;
     case BFD_RELOC_PPC_BA16:			r = R_PPC64_ADDR14;
       break;
     case BFD_RELOC_PPC_BA16_BRTAKEN:		r = R_PPC64_ADDR14_BRTAKEN;
@@ -2186,8 +2298,12 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       break;
     case BFD_RELOC_PPC_TPREL16_HI:		r = R_PPC64_TPREL16_HI;
       break;
+    case BFD_RELOC_PPC64_TPREL16_HIGH:		r = R_PPC64_TPREL16_HIGH;
+      break;
     case BFD_RELOC_PPC_TPREL16_HA:		r = R_PPC64_TPREL16_HA;
       break;
+    case BFD_RELOC_PPC64_TPREL16_HIGHA:		r = R_PPC64_TPREL16_HIGHA;
+      break;
     case BFD_RELOC_PPC_TPREL:			r = R_PPC64_TPREL64;
       break;
     case BFD_RELOC_PPC_DTPREL16:		r = R_PPC64_DTPREL16;
@@ -2196,8 +2312,12 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       break;
     case BFD_RELOC_PPC_DTPREL16_HI:		r = R_PPC64_DTPREL16_HI;
       break;
+    case BFD_RELOC_PPC64_DTPREL16_HIGH:		r = R_PPC64_DTPREL16_HIGH;
+      break;
     case BFD_RELOC_PPC_DTPREL16_HA:		r = R_PPC64_DTPREL16_HA;
       break;
+    case BFD_RELOC_PPC64_DTPREL16_HIGHA:	r = R_PPC64_DTPREL16_HIGHA;
+      break;
     case BFD_RELOC_PPC_DTPREL:			r = R_PPC64_DTPREL64;
       break;
     case BFD_RELOC_PPC_GOT_TLSGD16:		r = R_PPC64_GOT_TLSGD16;
@@ -2836,6 +2956,19 @@ get_opd_info (asection * sec)
     return &ppc64_elf_section_data (sec)->u.opd;
   return NULL;
 }
+
+static inline int
+abiversion (bfd *abfd)
+{
+  return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
+}
+
+static inline void
+set_abiversion (bfd *abfd, int ver)
+{
+  elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
+  elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
+}
 
 /* Parameters for the qsort hook.  */
 static bfd_boolean synthetic_relocatable;
@@ -2982,15 +3115,19 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
   long count;
   char *names;
   long symcount, codesecsym, codesecsymend, secsymend, opdsymend;
-  asection *opd;
+  asection *opd = NULL;
   bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
   asymbol **syms;
+  int abi = abiversion (abfd);
 
   *ret = NULL;
 
-  opd = bfd_get_section_by_name (abfd, ".opd");
-  if (opd == NULL)
-    return 0;
+  if (abi < 2)
+    {
+      opd = bfd_get_section_by_name (abfd, ".opd");
+      if (opd == NULL && abi == 1)
+	return 0;
+    }
 
   symcount = static_count;
   if (!relocatable)
@@ -3159,20 +3296,18 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
   else
     {
       bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
-      bfd_byte *contents;
+      bfd_byte *contents = NULL;
       size_t size;
       long plt_count = 0;
       bfd_vma glink_vma = 0, resolv_vma = 0;
       asection *dynamic, *glink = NULL, *relplt = NULL;
       arelent *p;
 
-      if (!bfd_malloc_and_get_section (abfd, opd, &contents))
+      if (opd != NULL && !bfd_malloc_and_get_section (abfd, opd, &contents))
 	{
+	free_contents_and_exit:
 	  if (contents)
-	    {
-	    free_contents_and_exit:
-	      free (contents);
-	    }
+	    free (contents);
 	  count = -1;
 	  goto done;
 	}
@@ -3221,9 +3356,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 
 	      if (dyn.d_tag == DT_PPC64_GLINK)
 		{
-		  /* The first glink stub starts at offset 32; see comment in
-		     ppc64_elf_finish_dynamic_sections. */
-		  glink_vma = dyn.d_un.d_val + 32;
+		  /* The first glink stub starts at offset 32; see
+		     comment in ppc64_elf_finish_dynamic_sections. */
+		  glink_vma = dyn.d_un.d_val + GLINK_CALL_STUB_SIZE - 8 * 4;
 		  /* The .glink section usually does not survive the final
 		     link; search for the section (usually .text) where the
 		     glink stubs now reside.  */
@@ -3241,13 +3376,21 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 	  /* Determine __glink trampoline by reading the relative branch
 	     from the first glink stub.  */
 	  bfd_byte buf[4];
-	  if (bfd_get_section_contents (abfd, glink, buf,
-					glink_vma + 4 - glink->vma, 4))
+	  unsigned int off = 0;
+
+	  while (bfd_get_section_contents (abfd, glink, buf,
+					   glink_vma + off - glink->vma, 4))
 	    {
 	      unsigned int insn = bfd_get_32 (abfd, buf);
 	      insn ^= B_DOT;
 	      if ((insn & ~0x3fffffc) == 0)
-		resolv_vma = glink_vma + 4 + (insn ^ 0x2000000) - 0x2000000;
+		{
+		  resolv_vma = glink_vma + off + (insn ^ 0x2000000) - 0x2000000;
+		  break;
+		}
+	      off += 4;
+	      if (off > 4)
+		break;
 	    }
 
 	  if (resolv_vma)
@@ -3400,8 +3543,13 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
 	      memcpy (names, "@plt", sizeof ("@plt"));
 	      names += sizeof ("@plt");
 	      s++;
-	      glink_vma += 8;
-	      if (i >= 0x8000)
+	      if (abi < 2)
+		{
+		  glink_vma += 8;
+		  if (i >= 0x8000)
+		    glink_vma += 4;
+		}
+	      else
 		glink_vma += 4;
 	    }
 	  count += plt_count;
@@ -3452,13 +3600,13 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
    .
    .
    .	.foo_stub:
-   .		addis	12,2,Lfoo@toc@ha	# in practice, the call stub
-   .		addi	12,12,Lfoo@toc@l	# is slightly optimized, but
-   .		std	2,40(1)			# this is the general idea
-   .		ld	11,0(12)
-   .		ld	2,8(12)
-   .		mtctr	11
-   .		ld	11,16(12)
+   .		std	2,40(1)			# in practice, the call stub
+   .		addis	11,2,Lfoo@toc@ha	# is slightly optimized, but
+   .		addi	11,11,Lfoo@toc@l	# this is the general idea
+   .		ld	12,0(11)
+   .		ld	2,8(11)
+   .		mtctr	12
+   .		ld	11,16(11)
    .		bctr
    .
    .		.section .plt
@@ -3509,6 +3657,8 @@ must_be_dyn_reloc (struct bfd_link_info *info,
     case R_PPC64_TPREL16_HA:
     case R_PPC64_TPREL16_DS:
     case R_PPC64_TPREL16_LO_DS:
+    case R_PPC64_TPREL16_HIGH:
+    case R_PPC64_TPREL16_HIGHA:
     case R_PPC64_TPREL16_HIGHER:
     case R_PPC64_TPREL16_HIGHERA:
     case R_PPC64_TPREL16_HIGHEST:
@@ -3548,21 +3698,21 @@ must_be_dyn_reloc (struct bfd_link_info *info,
    ppc_stub_plt_branch:
    Similar to the above, but a 24 bit branch in the stub section won't
    reach its destination.
-   .	addis	%r12,%r2,xxx@toc@ha
-   .	ld	%r11,xxx@toc@l(%r12)
-   .	mtctr	%r11
+   .	addis	%r11,%r2,xxx@toc@ha
+   .	ld	%r12,xxx@toc@l(%r11)
+   .	mtctr	%r12
    .	bctr
 
    ppc_stub_plt_call:
    Used to call a function in a shared library.  If it so happens that
    the plt entry referenced crosses a 64k boundary, then an extra
-   "addi %r12,%r12,xxx@toc@l" will be inserted before the "mtctr".
-   .	addis	%r12,%r2,xxx@toc@ha
+   "addi %r11,%r11,xxx@toc@l" will be inserted before the "mtctr".
    .	std	%r2,40(%r1)
-   .	ld	%r11,xxx+0@toc@l(%r12)
-   .	mtctr	%r11
-   .	ld	%r2,xxx+8@toc@l(%r12)
-   .	ld	%r11,xxx+16@toc@l(%r12)
+   .	addis	%r11,%r2,xxx@toc@ha
+   .	ld	%r12,xxx+0@toc@l(%r11)
+   .	mtctr	%r12
+   .	ld	%r2,xxx+8@toc@l(%r11)
+   .	ld	%r11,xxx+16@toc@l(%r11)
    .	bctr
 
    ppc_stub_long_branch and ppc_stub_plt_branch may also have additional
@@ -3575,11 +3725,11 @@ must_be_dyn_reloc (struct bfd_link_info *info,
 
    A ppc_stub_plt_branch with an r2 offset looks like:
    .	std	%r2,40(%r1)
-   .	addis	%r12,%r2,xxx@toc@ha
-   .	ld	%r11,xxx@toc@l(%r12)
+   .	addis	%r11,%r2,xxx@toc@ha
+   .	ld	%r12,xxx@toc@l(%r11)
    .	addis	%r2,%r2,off@ha
    .	addi	%r2,%r2,off@l
-   .	mtctr	%r11
+   .	mtctr	%r12
    .	bctr
 
    In cases where the "addis" instruction would add zero, the "addis" is
@@ -3624,6 +3774,9 @@ struct ppc_stub_hash_entry {
   /* Where this stub is being called from, or, in the case of combined
      stub sections, the first input section in the group.  */
   asection *id_sec;
+
+  /* Symbol st_other.  */
+  unsigned char other;
 };
 
 struct ppc_branch_hash_entry {
@@ -3772,6 +3925,9 @@ struct ppc_link_hash_table
   /* Alignment of PLT call stubs.  */
   unsigned int plt_stub_align:4;
 
+  /* Set if we're linking code with function descriptors.  */
+  unsigned int opd_abi:1;
+
   /* Set if PLT call stubs should load r11.  */
   unsigned int plt_static_chain:1;
 
@@ -3867,7 +4023,9 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
       eh->target_value = 0;
       eh->target_section = NULL;
       eh->h = NULL;
+      eh->plt_ent = NULL;
       eh->id_sec = NULL;
+      eh->other = 0;
     }
 
   return entry;
@@ -4452,6 +4610,7 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   edir->elf.ref_regular |= eind->elf.ref_regular;
   edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
   edir->elf.needs_plt |= eind->elf.needs_plt;
+  edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
 
   /* Copy over any dynamic relocs we may have on the indirect sym.  */
   if (eind->dyn_relocs != NULL)
@@ -4610,7 +4769,7 @@ static bfd_boolean
 ppc64_elf_add_symbol_hook (bfd *ibfd,
 			   struct bfd_link_info *info,
 			   Elf_Internal_Sym *isym,
-			   const char **name ATTRIBUTE_UNUSED,
+			   const char **name,
 			   flagword *flags ATTRIBUTE_UNUSED,
 			   asection **sec,
 			   bfd_vma *value ATTRIBUTE_UNUSED)
@@ -4630,9 +4789,35 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
 	   && strcmp ((*sec)->name, ".opd") == 0)
     isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
 
+  if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
+    {
+      if (abiversion (ibfd) == 0)
+	set_abiversion (ibfd, 2);
+      else if (abiversion (ibfd) == 1)
+	{
+	  info->callbacks->einfo (_("%P: symbol '%s' has invalid st_other"
+				    " for ABI version 1\n"), name);
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+    }
+
   return TRUE;
 }
 
+/* Merge non-visibility st_other attributes: local entry point.  */
+
+static void
+ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
+				  const Elf_Internal_Sym *isym,
+				  bfd_boolean definition,
+				  bfd_boolean dynamic)
+{
+  if (definition && !dynamic)
+    h->other = ((isym->st_other & ~ELF_ST_VISIBILITY (-1))
+		| ELF_ST_VISIBILITY (h->other));
+}
+
 /* This function makes an old ABI object reference to ".bar" cause the
    inclusion of a new ABI object archive that defines "bar".
    NAME is a symbol defined in an archive.  Return a symbol in the hash
@@ -4959,6 +5144,15 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	 information about the associated function section.  */
       bfd_size_type amt;
 
+      if (abiversion (abfd) == 0)
+	set_abiversion (abfd, 1);
+      else if (abiversion (abfd) == 2)
+	{
+	  info->callbacks->einfo (_("%P: .opd not allowed in ABI version %d\n"),
+				  abiversion (abfd));
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
       amt = sec->size * sizeof (*opd_sym_map) / 8;
       opd_sym_map = bfd_zalloc (abfd, amt);
       if (opd_sym_map == NULL)
@@ -5134,6 +5328,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
 					rel->r_addend, tls_type))
 	      return FALSE;
+
+	  /* We may also need a plt entry if the symbol turns out to be
+	     an ifunc.  */
+	  if (h != NULL && !info->shared && abiversion (abfd) == 2)
+	    {
+	      if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
+		return FALSE;
+	    }
 	  break;
 
 	case R_PPC64_PLT16_HA:
@@ -5179,6 +5381,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_PPC64_DTPREL16_HA:
 	case R_PPC64_DTPREL16_DS:
 	case R_PPC64_DTPREL16_LO_DS:
+	case R_PPC64_DTPREL16_HIGH:
+	case R_PPC64_DTPREL16_HIGHA:
 	case R_PPC64_DTPREL16_HIGHER:
 	case R_PPC64_DTPREL16_HIGHERA:
 	case R_PPC64_DTPREL16_HIGHEST:
@@ -5339,6 +5543,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	case R_PPC64_TPREL16_HA:
 	case R_PPC64_TPREL16_DS:
 	case R_PPC64_TPREL16_LO_DS:
+	case R_PPC64_TPREL16_HIGH:
+	case R_PPC64_TPREL16_HIGHA:
 	case R_PPC64_TPREL16_HIGHER:
 	case R_PPC64_TPREL16_HIGHERA:
 	case R_PPC64_TPREL16_HIGHEST:
@@ -5382,22 +5588,35 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    }
 	  /* Fall through.  */
 
-	case R_PPC64_REL30:
-	case R_PPC64_REL32:
-	case R_PPC64_REL64:
-	case R_PPC64_ADDR14:
-	case R_PPC64_ADDR14_BRNTAKEN:
-	case R_PPC64_ADDR14_BRTAKEN:
 	case R_PPC64_ADDR16:
 	case R_PPC64_ADDR16_DS:
 	case R_PPC64_ADDR16_HA:
 	case R_PPC64_ADDR16_HI:
+	case R_PPC64_ADDR16_HIGH:
+	case R_PPC64_ADDR16_HIGHA:
 	case R_PPC64_ADDR16_HIGHER:
 	case R_PPC64_ADDR16_HIGHERA:
 	case R_PPC64_ADDR16_HIGHEST:
 	case R_PPC64_ADDR16_HIGHESTA:
 	case R_PPC64_ADDR16_LO:
 	case R_PPC64_ADDR16_LO_DS:
+	  if (h != NULL && !info->shared && abiversion (abfd) == 2
+	      && rel->r_addend == 0)
+	    {
+	      /* We may need a .plt entry if this reloc refers to a
+		 function in a shared lib.  */
+	      if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
+		return FALSE;
+	      h->pointer_equality_needed = 1;
+	    }
+	  /* Fall through.  */
+
+	case R_PPC64_REL30:
+	case R_PPC64_REL32:
+	case R_PPC64_REL64:
+	case R_PPC64_ADDR14:
+	case R_PPC64_ADDR14_BRNTAKEN:
+	case R_PPC64_ADDR14_BRTAKEN:
 	case R_PPC64_ADDR24:
 	case R_PPC64_ADDR32:
 	case R_PPC64_UADDR16:
@@ -5518,6 +5737,78 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   return TRUE;
 }
 
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+ppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  unsigned long iflags, oflags;
+
+  if ((ibfd->flags & BFD_LINKER_CREATED) != 0)
+    return TRUE;
+
+  if (!is_ppc64_elf (ibfd) || !is_ppc64_elf (obfd))
+    return TRUE;
+
+  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  iflags = elf_elfheader (ibfd)->e_flags;
+  oflags = elf_elfheader (obfd)->e_flags;
+
+  if (!elf_flags_init (obfd) || oflags == 0)
+    {
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = iflags;
+    }
+  else if (iflags == oflags || iflags == 0)
+    ;
+  else if (iflags & ~EF_PPC64_ABI)
+    {
+      (*_bfd_error_handler)
+	(_("%B uses unknown e_flags 0x%lx"), ibfd, iflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+  else
+    {
+      (*_bfd_error_handler)
+	(_("%B: ABI version %ld is not compatible with ABI version %ld output"),
+	 ibfd, iflags, oflags);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  _bfd_elf_merge_object_attributes (ibfd, obfd);
+
+  return TRUE;
+}
+
+static bfd_boolean
+ppc64_elf_print_private_bfd_data (bfd *abfd, void *ptr)
+{
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  if (elf_elfheader (abfd)->e_flags != 0)
+    {
+      FILE *file = ptr;
+
+      /* xgettext:c-format */
+      fprintf (file, _("private flags = 0x%lx:"),
+	       elf_elfheader (abfd)->e_flags);
+
+      if ((elf_elfheader (abfd)->e_flags & EF_PPC64_ABI) != 0)
+	fprintf (file, _(" [abiv%ld]"),
+		 elf_elfheader (abfd)->e_flags & EF_PPC64_ABI);
+      fputc ('\n', file);
+    }
+
+  return TRUE;
+}
+
 /* OFFSET in OPD_SEC specifies a function descriptor.  Return the address
    of the code entry point, and its section.  */
 
@@ -6177,7 +6468,7 @@ static bfd_byte *
 savegpr0_tail (bfd *abfd, bfd_byte *p, int r)
 {
   p = savegpr0 (abfd, p, r);
-  bfd_put_32 (abfd, STD_R0_0R1 + 16, p);
+  bfd_put_32 (abfd, STD_R0_0R1 + STK_LR, p);
   p = p + 4;
   bfd_put_32 (abfd, BLR, p);
   return p + 4;
@@ -6193,7 +6484,7 @@ restgpr0 (bfd *abfd, bfd_byte *p, int r)
 static bfd_byte *
 restgpr0_tail (bfd *abfd, bfd_byte *p, int r)
 {
-  bfd_put_32 (abfd, LD_R0_0R1 + 16, p);
+  bfd_put_32 (abfd, LD_R0_0R1 + STK_LR, p);
   p = p + 4;
   p = restgpr0 (abfd, p, r);
   bfd_put_32 (abfd, MTLR_R0, p);
@@ -6248,7 +6539,7 @@ static bfd_byte *
 savefpr0_tail (bfd *abfd, bfd_byte *p, int r)
 {
   p = savefpr (abfd, p, r);
-  bfd_put_32 (abfd, STD_R0_0R1 + 16, p);
+  bfd_put_32 (abfd, STD_R0_0R1 + STK_LR, p);
   p = p + 4;
   bfd_put_32 (abfd, BLR, p);
   return p + 4;
@@ -6264,7 +6555,7 @@ restfpr (bfd *abfd, bfd_byte *p, int r)
 static bfd_byte *
 restfpr0_tail (bfd *abfd, bfd_byte *p, int r)
 {
-  bfd_put_32 (abfd, LD_R0_0R1 + 16, p);
+  bfd_put_32 (abfd, LD_R0_0R1 + STK_LR, p);
   p = p + 4;
   p = restfpr (abfd, p, r);
   bfd_put_32 (abfd, MTLR_R0, p);
@@ -6510,6 +6801,25 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
   return TRUE;
 }
 
+/* Return true if we have dynamic relocs that apply to read-only sections.  */
+
+static bfd_boolean
+readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+  struct ppc_link_hash_entry *eh;
+  struct elf_dyn_relocs *p;
+
+  eh = (struct ppc_link_hash_entry *) h;
+  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+    {
+      asection *s = p->sec->output_section;
+
+      if (s != NULL && (s->flags & SEC_READONLY) != 0)
+	return TRUE;
+    }
+  return FALSE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -6547,6 +6857,26 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 	  h->plt.plist = NULL;
 	  h->needs_plt = 0;
 	}
+      else if (abiversion (info->output_bfd) == 2)
+	{
+	  /* After adjust_dynamic_symbol, non_got_ref set in the
+	     non-shared case means that we have allocated space in
+	     .dynbss for the symbol and thus dyn_relocs for this
+	     symbol should be discarded.
+	     If we get here we know we are making a PLT entry for this
+	     symbol, and in an executable we'd normally resolve
+	     relocations against this symbol to the PLT entry.  Allow
+	     dynamic relocs if the reference is weak, and the dynamic
+	     relocs will not cause text relocation.  */
+	  if (!h->ref_regular_nonweak
+	      && h->non_got_ref
+	      && h->type != STT_GNU_IFUNC
+	      && !readonly_dynrelocs (h))
+	    h->non_got_ref = 0;
+
+	  /* If making a plt entry, then we don't need copy relocs.  */
+	  return TRUE;
+	}
     }
   else
     h->plt.plist = NULL;
@@ -6581,26 +6911,12 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   if (!h->def_dynamic || !h->ref_regular || h->def_regular)
     return TRUE;
 
-  if (ELIMINATE_COPY_RELOCS)
+  /* If we didn't find any dynamic relocs in read-only sections, then
+     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
+  if (ELIMINATE_COPY_RELOCS && !readonly_dynrelocs (h))
     {
-      struct ppc_link_hash_entry * eh;
-      struct elf_dyn_relocs *p;
-
-      eh = (struct ppc_link_hash_entry *) h;
-      for (p = eh->dyn_relocs; p != NULL; p = p->next)
-	{
-	  s = p->sec->output_section;
-	  if (s != NULL && (s->flags & SEC_READONLY) != 0)
-	    break;
-	}
-
-      /* If we didn't find any dynamic relocs in read-only sections, then
-	 we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-      if (p == NULL)
-	{
-	  h->non_got_ref = 0;
-	  return TRUE;
-	}
+      h->non_got_ref = 0;
+      return TRUE;
     }
 
   if (h->plt.plist != NULL)
@@ -6980,6 +7296,8 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_TPREL16_HA:
     case R_PPC64_TPREL16_DS:
     case R_PPC64_TPREL16_LO_DS:
+    case R_PPC64_TPREL16_HIGH:
+    case R_PPC64_TPREL16_HIGHA:
     case R_PPC64_TPREL16_HIGHER:
     case R_PPC64_TPREL16_HIGHERA:
     case R_PPC64_TPREL16_HIGHEST:
@@ -7001,6 +7319,8 @@ dec_dynrel_count (bfd_vma r_info,
     case R_PPC64_ADDR16_DS:
     case R_PPC64_ADDR16_HA:
     case R_PPC64_ADDR16_HI:
+    case R_PPC64_ADDR16_HIGH:
+    case R_PPC64_ADDR16_HIGHA:
     case R_PPC64_ADDR16_HIGHER:
     case R_PPC64_ADDR16_HIGHERA:
     case R_PPC64_ADDR16_HIGHEST:
@@ -7504,6 +7824,9 @@ ppc64_elf_tls_setup (struct bfd_link_info *info,
   if (htab == NULL)
     return NULL;
 
+  if (abiversion (info->output_bfd) == 1)
+    htab->opd_abi = 1;
+
   if (*no_multi_toc)
     htab->do_multi_toc = 0;
   else if (!htab->do_multi_toc)
@@ -8287,7 +8610,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
 		  || discarded_section (sym_sec))
 		continue;
 
-	      if (!SYMBOL_CALLS_LOCAL (info, h))
+	      if (!SYMBOL_REFERENCES_LOCAL (info, h))
 		continue;
 
 	      if (h != NULL)
@@ -8886,7 +9209,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 	      {
 		s = htab->iplt;
 		pent->plt.offset = s->size;
-		s->size += PLT_ENTRY_SIZE;
+		s->size += PLT_ENTRY_SIZE (htab);
 		s = htab->reliplt;
 	      }
 	    else
@@ -8895,21 +9218,26 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 		   first entry.  */
 		s = htab->plt;
 		if (s->size == 0)
-		  s->size += PLT_INITIAL_ENTRY_SIZE;
+		  s->size += PLT_INITIAL_ENTRY_SIZE (htab);
 
 		pent->plt.offset = s->size;
 
 		/* Make room for this entry.  */
-		s->size += PLT_ENTRY_SIZE;
+		s->size += PLT_ENTRY_SIZE (htab);
 
 		/* Make room for the .glink code.  */
 		s = htab->glink;
 		if (s->size == 0)
 		  s->size += GLINK_CALL_STUB_SIZE;
-		/* We need bigger stubs past index 32767.  */
-		if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
+		if (htab->opd_abi)
+		  {
+		    /* We need bigger stubs past index 32767.  */
+		    if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
+		      s->size += 4;
+		    s->size += 2*4;
+		  }
+		else
 		  s->size += 4;
-		s->size += 2*4;
 
 		/* We also need to make an entry in the .rela.plt section.  */
 		s = htab->relplt;
@@ -9002,7 +9330,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   if (eh->dyn_relocs == NULL
       || (!htab->elf.dynamic_sections_created
-	  && h->type != STT_GNU_IFUNC))
+	  && (h->type != STT_GNU_IFUNC
+	      || !htab->opd_abi)))
     return TRUE;
 
   /* In the shared -Bsymbolic case, discard space allocated for
@@ -9098,28 +9427,65 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
-/* Find any dynamic relocs that apply to read-only sections.  */
+/* Called via elf_link_hash_traverse from ppc64_elf_size_dynamic_sections
+   to set up space for global entry stubs.  These are put in glink,
+   after the branch table.  */
 
 static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+size_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
 {
-  struct ppc_link_hash_entry *eh;
-  struct elf_dyn_relocs *p;
+  struct bfd_link_info *info;
+  struct ppc_link_hash_table *htab;
+  struct plt_entry *pent;
+  asection *s;
 
-  eh = (struct ppc_link_hash_entry *) h;
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
-    {
-      asection *s = p->sec->output_section;
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
 
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-	{
-	  struct bfd_link_info *info = inf;
+  if (!h->pointer_equality_needed)
+    return TRUE;
 
-	  info->flags |= DF_TEXTREL;
+  if (h->def_regular)
+    return TRUE;
 
-	  /* Not an error, just cut short the traversal.  */
-	  return FALSE;
-	}
+  info = inf;
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
+  s = htab->glink;
+  for (pent = h->plt.plist; pent != NULL; pent = pent->next)
+    if (pent->plt.offset != (bfd_vma) -1
+	&& pent->addend == 0)
+      {
+	/* For ELFv2, if this symbol is not defined in a regular file
+	   and we are not generating a shared library or pie, then we
+	   need to define the symbol in the executable on a call stub.
+	   This is to avoid text relocations.  */
+	s->size = (s->size + 15) & -16;
+	h->root.u.def.section = s;
+	h->root.u.def.value = s->size;
+	s->size += 16;
+	break;
+      }
+  return TRUE;
+}
+
+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
+   read-only sections.  */
+
+static bfd_boolean
+maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
+{
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (readonly_dynrelocs (h))
+    {
+      ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+
+      /* Not an error, just cut short the traversal.  */
+      return FALSE;
     }
   return TRUE;
 }
@@ -9127,7 +9493,7 @@ readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
-ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+ppc64_elf_size_dynamic_sections (bfd *output_bfd,
 				 struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
@@ -9258,7 +9624,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	      {
 		s = htab->iplt;
 		ent->plt.offset = s->size;
-		s->size += PLT_ENTRY_SIZE;
+		s->size += PLT_ENTRY_SIZE (htab);
 
 		htab->reliplt->size += sizeof (Elf64_External_Rela);
 	      }
@@ -9270,6 +9636,12 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
+  /* Stash the end of glink branch table.  */
+  if (htab->glink != NULL)
+    htab->glink->rawsize = htab->glink->size;
+
+  if (!htab->opd_abi && !info->shared)
+    elf_link_hash_traverse (&htab->elf, size_global_entry_stubs, info);
 
   first_tlsld = NULL;
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
@@ -9415,6 +9787,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   if (htab->elf.dynamic_sections_created)
     {
+      bfd_boolean tls_opt;
+
       /* Add some entries to the .dynamic section.  We fill in the
 	 values later, in ppc64_elf_finish_dynamic_sections, but we
 	 must add the entries now so that we get the correct size for
@@ -9439,18 +9813,21 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	    return FALSE;
 	}
 
-      if (NO_OPD_RELOCS)
+      if (NO_OPD_RELOCS && abiversion (output_bfd) <= 1)
 	{
 	  if (!add_dynamic_entry (DT_PPC64_OPD, 0)
 	      || !add_dynamic_entry (DT_PPC64_OPDSZ, 0))
 	    return FALSE;
 	}
 
-      if (!htab->no_tls_get_addr_opt
-	  && htab->tls_get_addr_fd != NULL
-	  && htab->tls_get_addr_fd->elf.plt.plist != NULL
-	  && !add_dynamic_entry (DT_PPC64_TLSOPT, 0))
-	return FALSE;
+      tls_opt = (!htab->no_tls_get_addr_opt
+		 && htab->tls_get_addr_fd != NULL
+		 && htab->tls_get_addr_fd->elf.plt.plist != NULL);
+      if (tls_opt || !htab->opd_abi)
+	{
+	  if (!add_dynamic_entry (DT_PPC64_OPT, tls_opt ? PPC64_OPT_TLS : 0))
+	    return FALSE;
+	}
 
       if (relocs)
 	{
@@ -9462,7 +9839,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 	  /* If any dynamic relocs apply to a read-only section,
 	     then we need a DT_TEXTREL entry.  */
 	  if ((info->flags & DF_TEXTREL) == 0)
-	    elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, info);
+	    elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
 
 	  if ((info->flags & DF_TEXTREL) != 0)
 	    {
@@ -9476,6 +9853,19 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   return TRUE;
 }
 
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
+
+static bfd_boolean
+ppc64_elf_hash_symbol (struct elf_link_hash_entry *h)
+{
+  if (h->plt.plist != NULL
+      && !h->def_regular
+      && !h->pointer_equality_needed)
+    return FALSE;
+
+  return _bfd_elf_hash_symbol (h);
+}
+
 /* Determine the type of stub needed, if any, for a call.  */
 
 static inline enum ppc_stub_type
@@ -9483,7 +9873,8 @@ ppc_type_of_stub (asection *input_sec,
 		  const Elf_Internal_Rela *rel,
 		  struct ppc_link_hash_entry **hash,
 		  struct plt_entry **plt_ent,
-		  bfd_vma destination)
+		  bfd_vma destination,
+		  unsigned long local_off)
 {
   struct ppc_link_hash_entry *h = *hash;
   bfd_vma location;
@@ -9552,7 +9943,7 @@ ppc_type_of_stub (asection *input_sec,
   if (r_type != R_PPC64_REL24)
     max_branch_offset = 1 << 15;
 
-  if (branch_offset + max_branch_offset >= 2 * max_branch_offset)
+  if (branch_offset + max_branch_offset >= 2 * max_branch_offset - local_off)
     /* We need a stub.  Figure out whether a long_branch or plt_branch
        is needed later.  */
     return ppc_stub_long_branch;
@@ -9569,9 +9960,9 @@ ppc_type_of_stub (asection *input_sec,
    the appropriate glink entry if so.
 
    .	fake dep barrier	compare
-   .	ld 11,xxx(2)		ld 11,xxx(2)
-   .	mtctr 11		mtctr 11
-   .	xor 11,11,11		ld 2,xxx+8(2)
+   .	ld 12,xxx(2)		ld 12,xxx(2)
+   .	mtctr 12		mtctr 12
+   .	xor 11,12,12		ld 2,xxx+8(2)
    .	add 2,2,11		cmpldi 2,0
    .	ld 2,xxx+8(2)		bnectr+
    .	bctr			b <glink_entry>
@@ -9591,19 +9982,23 @@ plt_stub_size (struct ppc_link_hash_table *htab,
 	       struct ppc_stub_hash_entry *stub_entry,
 	       bfd_vma off)
 {
-  unsigned size = PLT_CALL_STUB_SIZE;
-
-  if (!(ALWAYS_EMIT_R2SAVE
-	|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
-    size -= 4;
-  if (!htab->plt_static_chain)
-    size -= 4;
-  if (htab->plt_thread_safe)
-    size += 8;
-  if (PPC_HA (off) == 0)
-    size -= 4;
-  if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
+  unsigned size = 12;
+
+  if (ALWAYS_EMIT_R2SAVE
+      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+    size += 4;
+  if (PPC_HA (off) != 0)
     size += 4;
+  if (htab->opd_abi)
+    {
+      size += 4;
+      if (htab->plt_static_chain)
+	size += 4;
+      if (htab->plt_thread_safe)
+	size += 8;
+      if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
+	size += 4;
+    }
   if (stub_entry->h != NULL
       && (stub_entry->h == htab->tls_get_addr_fd
 	  || stub_entry->h == htab->tls_get_addr)
@@ -9637,12 +10032,14 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 		bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
 {
   bfd *obfd = htab->stub_bfd;
+  bfd_boolean plt_load_toc = htab->opd_abi;
   bfd_boolean plt_static_chain = htab->plt_static_chain;
   bfd_boolean plt_thread_safe = htab->plt_thread_safe;
   bfd_boolean use_fake_dep = plt_thread_safe;
   bfd_vma cmp_branch_off = 0;
 
   if (!ALWAYS_USE_FAKE_DEP
+      && plt_load_toc
       && plt_thread_safe
       && !(stub_entry->h != NULL
 	   && (stub_entry->h == htab->tls_get_addr_fd
@@ -9650,7 +10047,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 	   && !htab->no_tls_get_addr_opt))
     {
       bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
-      bfd_vma pltindex = (pltoff - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE;
+      bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
+			  / PLT_ENTRY_SIZE (htab));
       bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
       bfd_vma to, from;
 
@@ -9684,44 +10082,51 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 	  r[1].r_offset = r[0].r_offset + 4;
 	  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
 	  r[1].r_addend = r[0].r_addend;
-	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
-	    {
-	      r[2].r_offset = r[1].r_offset + 4;
-	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
-	      r[2].r_addend = r[0].r_addend;
-	    }
-	  else
+	  if (plt_load_toc)
 	    {
-	      r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
-	      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
-	      r[2].r_addend = r[0].r_addend + 8;
-	      if (plt_static_chain)
+	      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
 		{
-		  r[3].r_offset = r[2].r_offset + 4;
-		  r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
-		  r[3].r_addend = r[0].r_addend + 16;
+		  r[2].r_offset = r[1].r_offset + 4;
+		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
+		  r[2].r_addend = r[0].r_addend;
+		}
+	      else
+		{
+		  r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
+		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+		  r[2].r_addend = r[0].r_addend + 8;
+		  if (plt_static_chain)
+		    {
+		      r[3].r_offset = r[2].r_offset + 4;
+		      r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
+		      r[3].r_addend = r[0].r_addend + 16;
+		    }
 		}
 	    }
 	}
       if (ALWAYS_EMIT_R2SAVE
 	  || stub_entry->stub_type == ppc_stub_plt_call_r2save)
-	bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
-      bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),	p += 4;
-      bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p),	p += 4;
-      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+	bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p),	p += 4;
+      bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p),	p += 4;
+      bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p),	p += 4;
+      if (plt_load_toc
+	  && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
 	{
-	  bfd_put_32 (obfd, ADDI_R12_R12 | PPC_LO (offset), p),	p += 4;
+	  bfd_put_32 (obfd, ADDI_R11_R11 | PPC_LO (offset), p),	p += 4;
 	  offset = 0;
 	}
-      bfd_put_32 (obfd, MTCTR_R11, p),				p += 4;
-      if (use_fake_dep)
+      bfd_put_32 (obfd, MTCTR_R12, p),				p += 4;
+      if (plt_load_toc)
 	{
-	  bfd_put_32 (obfd, XOR_R11_R11_R11, p),		p += 4;
-	  bfd_put_32 (obfd, ADD_R12_R12_R11, p),		p += 4;
+	  if (use_fake_dep)
+	    {
+	      bfd_put_32 (obfd, XOR_R2_R12_R12, p),		p += 4;
+	      bfd_put_32 (obfd, ADD_R11_R11_R2, p),		p += 4;
+	    }
+	  bfd_put_32 (obfd, LD_R2_0R11 | PPC_LO (offset + 8), p), p += 4;
+	  if (plt_static_chain)
+	    bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
 	}
-      bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset + 8), p),	p += 4;
-      if (plt_static_chain)
-	bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset + 16), p), p += 4;
     }
   else
     {
@@ -9731,45 +10136,52 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 	      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
 	    r[0].r_offset += 4;
 	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
-	  if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+	  if (plt_load_toc)
 	    {
-	      r[1].r_offset = r[0].r_offset + 4;
-	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
-	      r[1].r_addend = r[0].r_addend;
-	    }
-	  else
-	    {
-	      r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
-	      r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
-	      r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
-	      if (plt_static_chain)
+	      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
 		{
-		  r[2].r_offset = r[1].r_offset + 4;
-		  r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
-		  r[2].r_addend = r[0].r_addend + 8;
+		  r[1].r_offset = r[0].r_offset + 4;
+		  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
+		  r[1].r_addend = r[0].r_addend;
+		}
+	      else
+		{
+		  r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
+		  r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+		  r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
+		  if (plt_static_chain)
+		    {
+		      r[2].r_offset = r[1].r_offset + 4;
+		      r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
+		      r[2].r_addend = r[0].r_addend + 8;
+		    }
 		}
 	    }
 	}
       if (ALWAYS_EMIT_R2SAVE
 	  || stub_entry->stub_type == ppc_stub_plt_call_r2save)
-	bfd_put_32 (obfd, STD_R2_40R1, p),			p += 4;
-      bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset), p),	p += 4;
-      if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+	bfd_put_32 (obfd, STD_R2_0R1 + STK_TOC (htab), p),	p += 4;
+      bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (offset), p),	p += 4;
+      if (plt_load_toc
+	  && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
 	{
 	  bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p),	p += 4;
 	  offset = 0;
 	}
-      bfd_put_32 (obfd, MTCTR_R11, p),				p += 4;
-      if (use_fake_dep)
+      bfd_put_32 (obfd, MTCTR_R12, p),				p += 4;
+      if (plt_load_toc)
 	{
-	  bfd_put_32 (obfd, XOR_R11_R11_R11, p),		p += 4;
-	  bfd_put_32 (obfd, ADD_R2_R2_R11, p),			p += 4;
+	  if (use_fake_dep)
+	    {
+	      bfd_put_32 (obfd, XOR_R11_R12_R12, p),		p += 4;
+	      bfd_put_32 (obfd, ADD_R2_R2_R11, p),		p += 4;
+	    }
+	  if (plt_static_chain)
+	    bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
+	  bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
 	}
-      if (plt_static_chain)
-	bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
-      bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p),	p += 4;
     }
-  if (plt_thread_safe && !use_fake_dep)
+  if (plt_load_toc && plt_thread_safe && !use_fake_dep)
     {
       bfd_put_32 (obfd, CMPLDI_R2_0, p),			p += 4;
       bfd_put_32 (obfd, BNECTR_P4, p),				p += 4;
@@ -9789,11 +10201,9 @@ build_plt_stub (struct ppc_link_hash_table *htab,
 #define ADD_R3_R12_R13	0x7c6c6a14
 #define BEQLR		0x4d820020
 #define MR_R3_R0	0x7c030378
-#define MFLR_R11	0x7d6802a6
 #define STD_R11_0R1	0xf9610000
 #define BCTRL		0x4e800421
 #define LD_R11_0R1	0xe9610000
-#define LD_R2_0R1	0xe8410000
 #define MTLR_R11	0x7d6803a6
 
 static inline bfd_byte *
@@ -9811,15 +10221,15 @@ build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
   bfd_put_32 (obfd, BEQLR, p),			p += 4;
   bfd_put_32 (obfd, MR_R3_R0, p),		p += 4;
   bfd_put_32 (obfd, MFLR_R11, p),		p += 4;
-  bfd_put_32 (obfd, STD_R11_0R1 + 32, p),	p += 4;
+  bfd_put_32 (obfd, STD_R11_0R1 + STK_LINKER (htab), p), p += 4;
 
   if (r != NULL)
     r[0].r_offset += 9 * 4;
   p = build_plt_stub (htab, stub_entry, p, offset, r);
   bfd_put_32 (obfd, BCTRL, p - 4);
 
-  bfd_put_32 (obfd, LD_R11_0R1 + 32, p),	p += 4;
-  bfd_put_32 (obfd, LD_R2_0R1 + 40, p),		p += 4;
+  bfd_put_32 (obfd, LD_R11_0R1 + STK_LINKER (htab), p),	p += 4;
+  bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p),	p += 4;
   bfd_put_32 (obfd, MTLR_R11, p),		p += 4;
   bfd_put_32 (obfd, BLR, p),			p += 4;
 
@@ -9868,6 +10278,8 @@ get_r2off (struct bfd_link_info *info,
       /* Support linking -R objects.  Get the toc pointer from the
 	 opd entry.  */
       char buf[8];
+      if (!htab->opd_abi)
+	return r2off;
       asection *opd = stub_entry->h->elf.root.u.def.section;
       bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
 
@@ -9920,9 +10332,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     case ppc_stub_long_branch:
     case ppc_stub_long_branch_r2off:
       /* Branches are relative.  This is where we are going to.  */
-      off = dest = (stub_entry->target_value
-		    + stub_entry->target_section->output_offset
-		    + stub_entry->target_section->output_section->vma);
+      dest = (stub_entry->target_value
+	      + stub_entry->target_section->output_offset
+	      + stub_entry->target_section->output_section->vma);
+      dest += PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
+      off = dest;
 
       /* And this is where we are coming from.  */
       off -= (stub_entry->stub_offset
@@ -9939,7 +10353,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	      htab->stub_error = TRUE;
 	      return FALSE;
 	    }
-	  bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc);
+	  bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
 	  loc += 4;
 	  size = 12;
 	  if (PPC_HA (r2off) != 0)
@@ -10025,6 +10439,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       dest = (stub_entry->target_value
 	      + stub_entry->target_section->output_offset
 	      + stub_entry->target_section->output_section->vma);
+      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
+	dest += PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
 
       bfd_put_64 (htab->brlt->owner, dest,
 		  htab->brlt->contents + br_entry->offset);
@@ -10093,7 +10509,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  r[0].r_offset = loc - stub_entry->stub_sec->contents;
 	  if (bfd_big_endian (info->output_bfd))
 	    r[0].r_offset += 2;
-	  if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
+	  if (stub_entry->stub_type == ppc_stub_plt_branch_r2off
+	      && htab->opd_abi)
 	    r[0].r_offset += 4;
 	  r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
 	  r[0].r_addend = dest;
@@ -10106,19 +10523,20 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	    }
 	}
 
-      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
+      if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
+	  || !htab->opd_abi)
 	{
 	  if (PPC_HA (off) != 0)
 	    {
 	      size = 16;
-	      bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (off), loc);
+	      bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc);
 	      loc += 4;
-	      bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (off), loc);
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc);
 	    }
 	  else
 	    {
 	      size = 12;
-	      bfd_put_32 (htab->stub_bfd, LD_R11_0R2 | PPC_LO (off), loc);
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc);
 	    }
 	}
       else
@@ -10131,20 +10549,20 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	      return FALSE;
 	    }
 
-	  bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc);
+	  bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
 	  loc += 4;
 	  size = 20;
 	  if (PPC_HA (off) != 0)
 	    {
 	      size += 4;
-	      bfd_put_32 (htab->stub_bfd, ADDIS_R12_R2 | PPC_HA (off), loc);
+	      bfd_put_32 (htab->stub_bfd, ADDIS_R11_R2 | PPC_HA (off), loc);
 	      loc += 4;
-	      bfd_put_32 (htab->stub_bfd, LD_R11_0R12 | PPC_LO (off), loc);
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc);
 	      loc += 4;
 	    }
 	  else
 	    {
-	      bfd_put_32 (htab->stub_bfd, LD_R11_0R2 | PPC_LO (off), loc);
+	      bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc);
 	      loc += 4;
 	    }
 
@@ -10157,7 +10575,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc);
 	}
       loc += 4;
-      bfd_put_32 (htab->stub_bfd, MTCTR_R11, loc);
+      bfd_put_32 (htab->stub_bfd, MTCTR_R12, loc);
       loc += 4;
       bfd_put_32 (htab->stub_bfd, BCTR, loc);
       break;
@@ -10202,7 +10620,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  bfd_byte *rl;
 
 	  rela.r_offset = dest;
-	  rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
+	  if (htab->opd_abi)
+	    rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
+	  else
+	    rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
 	  rela.r_addend = (stub_entry->target_value
 			   + stub_entry->target_section->output_offset
 			   + stub_entry->target_section->output_section->vma);
@@ -10354,10 +10775,11 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (info->emitrelocations)
 	{
 	  stub_entry->stub_sec->reloc_count
-	    += (2
-		+ (PPC_HA (off) != 0)
-		+ (htab->plt_static_chain
-		   && PPC_HA (off + 16) == PPC_HA (off)));
+	    += ((PPC_HA (off) != 0)
+		+ (htab->opd_abi
+		   ? 2 + (htab->plt_static_chain
+			  && PPC_HA (off + 16) == PPC_HA (off))
+		   : 1));
 	  stub_entry->stub_sec->flags |= SEC_RELOC;
 	}
     }
@@ -10366,6 +10788,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       /* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off
 	 variants.  */
       bfd_vma r2off = 0;
+      bfd_vma local_off = 0;
 
       off = (stub_entry->target_value
 	     + stub_entry->target_section->output_offset
@@ -10383,7 +10806,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
 	{
 	  r2off = get_r2off (info, stub_entry);
-	  if (r2off == 0)
+	  if (r2off == 0 && htab->opd_abi)
 	    {
 	      htab->stub_error = TRUE;
 	      return FALSE;
@@ -10394,8 +10817,13 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	  off -= size - 4;
 	}
 
-      /* If the branch offset if too big, use a ppc_stub_plt_branch.  */
-      if (off + (1 << 25) >= (bfd_vma) (1 << 26))
+      local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
+
+      /* If the branch offset if too big, use a ppc_stub_plt_branch.
+	 Do the same for -R objects without function descriptors.  */
+      if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
+	  || (stub_entry->stub_type == ppc_stub_long_branch_r2off
+	      && r2off == 0))
 	{
 	  struct ppc_branch_hash_entry *br_entry;
 
@@ -10438,7 +10866,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 	      stub_entry->stub_sec->flags |= SEC_RELOC;
 	    }
 
-	  if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
+	  if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
+	      || !htab->opd_abi)
 	    {
 	      size = 12;
 	      if (PPC_HA (off) != 0)
@@ -10991,7 +11420,10 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
 	     need a plt_branch stub.  A plt_branch stub uses r2.  */
 	  else if (dest - (isec->output_offset
 			   + isec->output_section->vma
-			   + rel->r_offset) + (1 << 25) >= (2 << 25))
+			   + rel->r_offset) + (1 << 25)
+		   >= (2u << 25) - PPC64_LOCAL_ENTRY_OFFSET (h
+							     ? h->other
+							     : sym->st_other))
 	    {
 	      ret = 1;
 	      break;
@@ -11338,7 +11770,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
   htab->plt_stub_align = plt_stub_align;
   if (plt_thread_safe == -1 && !info->executable)
     plt_thread_safe = 1;
-  if (plt_thread_safe == -1)
+  if (!htab->opd_abi)
+    plt_thread_safe = 0;
+  else if (plt_thread_safe == -1)
     {
       static const char *const thread_starter[] =
 	{
@@ -11447,6 +11881,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
 		  asection *sym_sec, *code_sec;
 		  bfd_vma sym_value, code_value;
 		  bfd_vma destination;
+		  unsigned long local_off;
 		  bfd_boolean ok_dest;
 		  struct ppc_link_hash_entry *hash;
 		  struct ppc_link_hash_entry *fdh;
@@ -11523,12 +11958,16 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
 		    }
 
 		  destination = 0;
+		  local_off = 0;
 		  if (ok_dest)
 		    {
 		      sym_value += irela->r_addend;
 		      destination = (sym_value
 				     + sym_sec->output_offset
 				     + sym_sec->output_section->vma);
+		      local_off = PPC64_LOCAL_ENTRY_OFFSET (hash
+							    ? hash->elf.other
+							    : sym->st_other);
 		    }
 
 		  code_sec = sym_sec;
@@ -11565,7 +12004,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
 		  /* Determine what (if any) linker stub is needed.  */
 		  plt_ent = NULL;
 		  stub_type = ppc_type_of_stub (section, irela, &hash,
-						&plt_ent, destination);
+						&plt_ent, destination,
+						local_off);
 
 		  if (stub_type != ppc_stub_plt_call)
 		    {
@@ -11828,6 +12268,72 @@ ppc64_elf_toc (bfd *obfd)
   return TOCstart;
 }
 
+/* Called via elf_link_hash_traverse from ppc64_elf_build_stubs to
+   write out any global entry stubs.  */
+
+static bfd_boolean
+build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info;
+  struct ppc_link_hash_table *htab;
+  struct plt_entry *pent;
+  asection *s;
+
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
+
+  if (!h->pointer_equality_needed)
+    return TRUE;
+
+  if (h->def_regular)
+    return TRUE;
+
+  info = inf;
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
+  s = htab->glink;
+  for (pent = h->plt.plist; pent != NULL; pent = pent->next)
+    if (pent->plt.offset != (bfd_vma) -1
+	&& pent->addend == 0)
+      {
+	bfd_byte *p;
+	asection *plt;
+	bfd_vma off;
+
+	p = s->contents + h->root.u.def.value;
+	plt = htab->plt;
+	if (!htab->elf.dynamic_sections_created
+	    || h->dynindx == -1)
+	  plt = htab->iplt;
+	off = pent->plt.offset + plt->output_offset + plt->output_section->vma;
+	off -= h->root.u.def.value + s->output_offset + s->output_section->vma;
+
+	if (off + 0x80008000 > 0xffffffff || (off & 3) != 0)
+	  {
+	    info->callbacks->einfo
+	      (_("%P: linkage table error against `%T'\n"),
+	       h->root.root.string);
+	    bfd_set_error (bfd_error_bad_value);
+	    htab->stub_error = TRUE;
+	  }
+
+	if (PPC_HA (off) != 0)
+	  {
+	    bfd_put_32 (s->owner, ADDIS_R12_R12 | PPC_HA (off), p);
+	    p += 4;
+	  }
+	bfd_put_32 (s->owner, LD_R12_0R12 | PPC_LO (off), p);
+	p += 4;
+	bfd_put_32 (s->owner, MTCTR_R12, p);
+	p += 4;
+	bfd_put_32 (s->owner, BCTR, p);
+	break;
+      }
+  return TRUE;
+}
+
 /* Build all the stubs associated with the current output file.
    The stubs are kept in a hash table attached to the main linker
    hash table.  This function is called via gldelf64ppc_finish.  */
@@ -11903,26 +12409,56 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
       plt0 -= htab->glink->output_section->vma + htab->glink->output_offset;
       bfd_put_64 (htab->glink->owner, plt0, p);
       p += 8;
-      bfd_put_32 (htab->glink->owner, MFLR_R12, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, BCL_20_31, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, MFLR_R11, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, LD_R2_M16R11, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, MTLR_R12, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, ADD_R12_R2_R11, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, LD_R11_0R12, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, LD_R2_0R12 | 8, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, MTCTR_R11, p);
-      p += 4;
-      bfd_put_32 (htab->glink->owner, LD_R11_0R12 | 16, p);
-      p += 4;
+      if (htab->opd_abi)
+	{
+	  bfd_put_32 (htab->glink->owner, MFLR_R12, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, BCL_20_31, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MFLR_R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MTLR_R12, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | 8, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
+	  p += 4;
+	}
+      else
+	{
+	  bfd_put_32 (htab->glink->owner, MFLR_R0, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, BCL_20_31, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MFLR_R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MTLR_R0, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-48 & 0xffff), p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, SRDI_R0_R0_2, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
+	  p += 4;
+	  bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 8, p);
+	  p += 4;
+	}
       bfd_put_32 (htab->glink->owner, BCTR, p);
       p += 4;
       while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
@@ -11933,26 +12469,33 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
 
       /* Build the .glink lazy link call stubs.  */
       indx = 0;
-      while (p < htab->glink->contents + htab->glink->size)
+      while (p < htab->glink->contents + htab->glink->rawsize)
 	{
-	  if (indx < 0x8000)
-	    {
-	      bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
-	      p += 4;
-	    }
-	  else
+	  if (htab->opd_abi)
 	    {
-	      bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
-	      p += 4;
-	      bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
-	      p += 4;
+	      if (indx < 0x8000)
+		{
+		  bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
+		  p += 4;
+		}
+	      else
+		{
+		  bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
+		  p += 4;
+		  bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx),
+			      p);
+		  p += 4;
+		}
 	    }
 	  bfd_put_32 (htab->glink->owner,
 		      B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
 	  indx++;
 	  p += 4;
 	}
-      htab->glink->rawsize = p - htab->glink->contents;
+
+      /* Build .glink global entry stubs.  */
+      if (htab->glink->size > htab->glink->rawsize)
+	elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
     }
 
   if (htab->brlt->size != 0)
@@ -12056,7 +12599,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
 	  bfd_put_32 (htab->elf.dynobj, val, p);
 	  p += 4;
 	  /* .glink size.  */
-	  bfd_put_32 (htab->elf.dynobj, htab->glink->rawsize - 8, p);
+	  bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
 	  p += 4;
 	  /* Augmentation.  */
 	  p += 1;
@@ -12106,7 +12649,6 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
       }
 
   if (stub_sec != NULL
-      || htab->glink->rawsize != htab->glink->size
       || (htab->glink_eh_frame != NULL
 	  && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
     {
@@ -12849,6 +13391,39 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	      rel->r_info = ELF64_R_INFO (r_symndx, r_type);
 	    }
 	  break;
+
+	case R_PPC64_REL16_HA:
+	  /* If we are generating a non-PIC executable, edit
+	     .	0:	addis 2,12,.TOC.-0b@ha
+	     .		addi 2,2,.TOC.-0b@l
+	     used by ELFv2 global entry points to set up r2, to
+	     .		lis 2,.TOC.@ha
+	     .		addi 2,2,.TOC.@l
+	     if .TOC. is in range.  */
+	  if (!info->shared
+	      && h != NULL && &h->elf == htab->elf.hgot
+	      && rel + 1 < relend
+	      && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
+	      && rel[1].r_offset == rel->r_offset + 4
+	      && rel[1].r_addend == rel->r_addend + 4
+	      && relocation + 0x80008000 <= 0xffffffff)
+	    {
+	      unsigned int insn1, insn2;
+	      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 */)
+		{
+		  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);
+		}
+	    }
+	  break;
 	}
 
       /* Handle other relocations that tweak non-addend part of insn.  */
@@ -12871,7 +13446,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	      insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
 	      if (insn == NOP
 		  || insn == CROR_151515 || insn == CROR_313131)
-		bfd_put_32 (input_bfd, STD_R2_40R1,
+		bfd_put_32 (input_bfd,
+			    STD_R2_0R1 + STK_TOC (htab),
 			    contents + rel->r_offset);
 	    }
 	  break;
@@ -13001,6 +13577,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 		  + input_section->output_offset
 		  + input_section->output_section->vma);
 
+	  relocation += PPC64_LOCAL_ENTRY_OFFSET (fdh
+						  ? fdh->elf.other
+						  : sym->st_other);
+
 	  if (stub_entry != NULL
 	      && (stub_entry->stub_type == ppc_stub_long_branch
 		  || stub_entry->stub_type == ppc_stub_plt_branch)
@@ -13154,7 +13734,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 		    if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared,
 							  &h->elf)
 			|| (info->shared
-			    && SYMBOL_CALLS_LOCAL (info, &h->elf)))
+			    && SYMBOL_REFERENCES_LOCAL (info, &h->elf)))
 		      /* This is actually a static link, or it is a
 			 -Bsymbolic link and the symbol is defined
 			 locally, or the symbol was forced to be local
@@ -13329,13 +13909,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	    {
 	      struct plt_entry *ent;
 	      for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
-		if (ent->addend == orig_rel.r_addend
-		    && ent->plt.offset != (bfd_vma) -1)
+		if (ent->plt.offset != (bfd_vma) -1
+		    && ent->addend == orig_rel.r_addend)
 		  {
 		    relocation = (htab->plt->output_section->vma
 				  + htab->plt->output_offset
 				  + ent->plt.offset);
 		    unresolved_reloc = FALSE;
+		    break;
 		  }
 	    }
 	  break;
@@ -13395,6 +13976,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_TPREL16_HA:
 	case R_PPC64_TPREL16_DS:
 	case R_PPC64_TPREL16_LO_DS:
+	case R_PPC64_TPREL16_HIGH:
+	case R_PPC64_TPREL16_HIGHA:
 	case R_PPC64_TPREL16_HIGHER:
 	case R_PPC64_TPREL16_HIGHERA:
 	case R_PPC64_TPREL16_HIGHEST:
@@ -13429,6 +14012,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_DTPREL16_HA:
 	case R_PPC64_DTPREL16_DS:
 	case R_PPC64_DTPREL16_LO_DS:
+	case R_PPC64_DTPREL16_HIGH:
+	case R_PPC64_DTPREL16_HIGHA:
 	case R_PPC64_DTPREL16_HIGHER:
 	case R_PPC64_DTPREL16_HIGHERA:
 	case R_PPC64_DTPREL16_HIGHEST:
@@ -13461,6 +14046,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	case R_PPC64_ADDR16_DS:
 	case R_PPC64_ADDR16_HA:
 	case R_PPC64_ADDR16_HI:
+	case R_PPC64_ADDR16_HIGH:
+	case R_PPC64_ADDR16_HIGHA:
 	case R_PPC64_ADDR16_HIGHER:
 	case R_PPC64_ADDR16_HIGHERA:
 	case R_PPC64_ADDR16_HIGHEST:
@@ -13532,7 +14119,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
 	      if (skip)
 		memset (&outrel, 0, sizeof outrel);
-	      else if (!SYMBOL_CALLS_LOCAL (info, &h->elf)
+	      else if (!SYMBOL_REFERENCES_LOCAL (info, &h->elf)
 		       && !is_opd
 		       && r_type != R_PPC64_TOC)
 		{
@@ -13776,21 +14363,20 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 	default:
 	  break;
 
-	case R_PPC64_ADDR16_HA:
 	case R_PPC64_REL16_HA:
+	case R_PPC64_ADDR16_HA:
+	case R_PPC64_ADDR16_HIGHA:
 	case R_PPC64_ADDR16_HIGHERA:
 	case R_PPC64_ADDR16_HIGHESTA:
 	case R_PPC64_TOC16_HA:
 	case R_PPC64_SECTOFF_HA:
 	case R_PPC64_TPREL16_HA:
-	case R_PPC64_DTPREL16_HA:
-	case R_PPC64_TPREL16_HIGHER:
+	case R_PPC64_TPREL16_HIGHA:
 	case R_PPC64_TPREL16_HIGHERA:
-	case R_PPC64_TPREL16_HIGHEST:
 	case R_PPC64_TPREL16_HIGHESTA:
-	case R_PPC64_DTPREL16_HIGHER:
+	case R_PPC64_DTPREL16_HA:
+	case R_PPC64_DTPREL16_HIGHA:
 	case R_PPC64_DTPREL16_HIGHERA:
-	case R_PPC64_DTPREL16_HIGHEST:
 	case R_PPC64_DTPREL16_HIGHESTA:
 	  /* It's just possible that this symbol is a weak symbol
 	     that's not actually defined anywhere. In that case,
@@ -14017,7 +14603,10 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
 	    rela.r_offset = (htab->iplt->output_section->vma
 			     + htab->iplt->output_offset
 			     + ent->plt.offset);
-	    rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
+	    if (htab->opd_abi)
+	      rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
+	    else
+	      rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
 	    rela.r_addend = (h->root.u.def.value
 			     + h->root.u.def.section->output_offset
 			     + h->root.u.def.section->output_section->vma
@@ -14034,10 +14623,34 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
 	    rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
 	    rela.r_addend = ent->addend;
 	    loc = (htab->relplt->contents
-		   + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
-		      / (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
+		   + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
+		      / PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
 	  }
 	bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+
+	if (!htab->opd_abi)
+	  {
+	    if (!h->def_regular)
+	      {
+		/* Mark the symbol as undefined, rather than as
+		   defined in glink.  Leave the value if there were
+		   any relocations where pointer equality matters
+		   (this is a clue for the dynamic linker, to make
+		   function pointer comparisons work between an
+		   application and shared library), otherwise set it
+		   to zero.  */
+		sym->st_shndx = SHN_UNDEF;
+		if (!h->pointer_equality_needed)
+		  sym->st_value = 0;
+		else if (!h->ref_regular_nonweak)
+		  {
+		    /* This breaks function pointer comparisons, but
+		       that is better than breaking tests for a NULL
+		       function pointer.  */
+		    sym->st_value = 0;
+		  }
+	      }
+	  }
       }
 
   if (h->needs_copy)
@@ -14130,7 +14743,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
 		 of glink rather than the first entry point, which is
 		 what ld.so needs, and now have a bigger stub to
 		 support automatic multiple TOCs.  */
-	      dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32;
+	      dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 8 * 4;
 	      break;
 
 	    case DT_PPC64_OPD:
@@ -14140,6 +14753,11 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
 	      dyn.d_un.d_ptr = s->vma;
 	      break;
 
+	    case DT_PPC64_OPT:
+	      if (htab->do_multi_toc && htab->multi_toc_needed)
+		dyn.d_un.d_val |= PPC64_OPT_MULTI_TOC;
+	      break;
+
 	    case DT_PPC64_OPDSZ:
 	      s = bfd_get_section_by_name (output_bfd, ".opd");
 	      if (s == NULL)
@@ -14203,7 +14821,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
     {
       /* Set .plt entry size.  */
       elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
-	= PLT_ENTRY_SIZE;
+	= PLT_ENTRY_SIZE (htab);
     }
 
   /* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index bcd76a0..d3b7950 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1396,6 +1396,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_PPC64_TOC16_LO_DS",
   "BFD_RELOC_PPC64_PLTGOT16_DS",
   "BFD_RELOC_PPC64_PLTGOT16_LO_DS",
+  "BFD_RELOC_PPC64_ADDR16_HIGH",
+  "BFD_RELOC_PPC64_ADDR16_HIGHA",
   "BFD_RELOC_PPC_TLS",
   "BFD_RELOC_PPC_TLSGD",
   "BFD_RELOC_PPC_TLSLD",
@@ -1438,6 +1440,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_PPC64_DTPREL16_HIGHERA",
   "BFD_RELOC_PPC64_DTPREL16_HIGHEST",
   "BFD_RELOC_PPC64_DTPREL16_HIGHESTA",
+  "BFD_RELOC_PPC64_TPREL16_HIGH",
+  "BFD_RELOC_PPC64_TPREL16_HIGHA",
+  "BFD_RELOC_PPC64_DTPREL16_HIGH",
+  "BFD_RELOC_PPC64_DTPREL16_HIGHA",
   "BFD_RELOC_I370_D12",
   "BFD_RELOC_CTOR",
   "BFD_RELOC_ARM_PCREL_BRANCH",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 626c818..b924974 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2892,6 +2892,10 @@ ENUMX
   BFD_RELOC_PPC64_PLTGOT16_DS
 ENUMX
   BFD_RELOC_PPC64_PLTGOT16_LO_DS
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_ADDR16_HIGHA
 ENUMDOC
   Power(rs6000) and PowerPC relocations.
 
@@ -2979,6 +2983,14 @@ ENUMX
   BFD_RELOC_PPC64_DTPREL16_HIGHEST
 ENUMX
   BFD_RELOC_PPC64_DTPREL16_HIGHESTA
+ENUMX
+  BFD_RELOC_PPC64_TPREL16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_TPREL16_HIGHA
+ENUMX
+  BFD_RELOC_PPC64_DTPREL16_HIGH
+ENUMX
+  BFD_RELOC_PPC64_DTPREL16_HIGHA
 ENUMDOC
   PowerPC and PowerPC64 thread-local storage relocations.
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 67aeaa8..2046ec5 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1556,7 +1556,7 @@ get_ppc_dynamic_type (unsigned long type)
   switch (type)
     {
     case DT_PPC_GOT:    return "PPC_GOT";
-    case DT_PPC_TLSOPT: return "PPC_TLSOPT";
+    case DT_PPC_OPT:    return "PPC_OPT";
     default:
       return NULL;
     }
@@ -1570,7 +1570,7 @@ get_ppc64_dynamic_type (unsigned long type)
     case DT_PPC64_GLINK:  return "PPC64_GLINK";
     case DT_PPC64_OPD:    return "PPC64_OPD";
     case DT_PPC64_OPDSZ:  return "PPC64_OPDSZ";
-    case DT_PPC64_TLSOPT: return "PPC64_TLSOPT";
+    case DT_PPC64_OPT:    return "PPC64_OPT";
     default:
       return NULL;
     }
@@ -2442,6 +2442,16 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
 	    strcat (buf, _(", relocatable-lib"));
 	  break;
 
+	case EM_PPC64:
+	  if (e_flags & EF_PPC64_ABI)
+	    {
+	      char abi[] = ", abiv0";
+
+	      abi[6] += e_flags & EF_PPC64_ABI;
+	      strcat (buf, abi);
+	    }
+	  break;
+
 	case EM_V800:
 	  if ((e_flags & EF_RH850_ABI) == EF_RH850_ABI)
 	    strcat (buf, ", RH850 ABI");
@@ -9122,6 +9132,19 @@ get_ia64_symbol_other (unsigned int other)
 }
 
 static const char *
+get_ppc64_symbol_other (unsigned int other)
+{
+  if (PPC64_LOCAL_ENTRY_OFFSET (other) != 0)
+    {
+      static char buf[32];
+      snprintf (buf, sizeof buf, _("<localentry>: %d"),
+		PPC64_LOCAL_ENTRY_OFFSET (other));
+      return buf;
+    }
+  return NULL;
+}
+
+static const char *
 get_symbol_other (unsigned int other)
 {
   const char * result = NULL;
@@ -9138,6 +9161,9 @@ get_symbol_other (unsigned int other)
     case EM_IA_64:
       result = get_ia64_symbol_other (other);
       break;
+    case EM_PPC64:
+      result = get_ppc64_symbol_other (other);
+      break;
     default:
       break;
     }
diff --git a/elfcpp/powerpc.h b/elfcpp/powerpc.h
index 2c803af..879055e 100644
--- a/elfcpp/powerpc.h
+++ b/elfcpp/powerpc.h
@@ -164,11 +164,17 @@ enum
   R_PPC_EMB_SDA21 = 109,
   R_PPC64_TOCSAVE = 109,
   R_PPC_EMB_MRKREF = 110,
+  R_PPC64_ADDR16_HIGH = 110,
   R_PPC_EMB_RELSEC16 = 111,
+  R_PPC64_ADDR16_HIGHA = 111,
   R_PPC_EMB_RELST_LO = 112,
+  R_PPC64_TPREL16_HIGH = 112,
   R_PPC_EMB_RELST_HI = 113,
+  R_PPC64_TPREL16_HIGHA = 113,
   R_PPC_EMB_RELST_HA = 114,
+  R_PPC64_DTPREL16_HIGH = 114,
   R_PPC_EMB_BIT_FLD = 115,
+  R_PPC64_DTPREL16_HIGHA = 115,
   R_PPC_EMB_RELSDA = 116,
 
   R_PPC_VLE_REL8 = 216,
@@ -208,6 +214,59 @@ enum
   EF_PPC_RELOCATABLE_LIB = 0x00008000, // PowerPC -mrelocatable-lib flag.  */
 };
 
+// e_flags values defined for powerpc64
+enum
+{
+  // ABI version
+  // 1 for original function descriptor using ABI,
+  // 2 for revised ABI without function descriptors,
+  // 0 for unspecified or not using any features affected by the differences.
+  EF_PPC64_ABI = 3
+};
+
+enum
+{
+  // The ELFv2 ABI uses three bits in the symbol st_other field of a
+  // function definition to specify the number of instructions between a
+  // function's global entry point and local entry point.
+  // The global entry point is used when it is necessary to set up the
+  // toc pointer (r2) for the function.  Callers must enter the global
+  // entry point with r12 set to the global entry point address.  On
+  // return from the function, r2 may have a different value to that
+  // which it had on entry.
+  // The local entry point is used when r2 is known to already be valid
+  // for the function.  There is no requirement on r12 when using the
+  // local entry point, and on return r2 will contain the same value as
+  // at entry.
+  // A value of zero in these bits means that the function has a single
+  // entry point with no requirement on r12 or r2, and that on return r2
+  // will contain the same value as at entry.
+  // Values of one and seven are reserved.
+
+  STO_PPC64_LOCAL_BIT = 5,
+  STO_PPC64_LOCAL_MASK = 0xE0
+};
+
+// 3 bit other field to bytes.
+static inline unsigned int
+ppc64_decode_local_entry(unsigned int other)
+{
+  return ((1 << other) >> 2) << 2;
+}
+
+// bytes to field value.
+static inline unsigned int
+ppc64_encode_local_entry(unsigned int val)
+{
+  return (val >= 4 * 4
+	  ? (val >= 8 * 4
+	     ? (val >= 16 * 4 ? 6 : 5)
+	     : 4)
+	  : (val >= 2 * 4
+	     ? 3
+	     : (val >= 1 * 4 ? 2 : 0)));
+}
+
 } // End namespace elfcpp.
 
 #endif // !defined(ELFCPP_POWERPC_H)
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index e55d8a9..99e893d 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -29,6 +29,7 @@
 
 #ifdef OBJ_ELF
 #include "elf/ppc.h"
+#include "elf/ppc64.h"
 #include "dwarf2dbg.h"
 #endif
 
@@ -112,7 +113,11 @@ static int set_target_endian = 0;
    compensating for #lo being treated as a signed number.  */
 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
 
-#define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000)
+#define SEX16(val) (((val) ^ 0x8000) - 0x8000)
+
+/* For the time being on ppc64, don't report overflow on @h and @ha
+   applied to constants.  */
+#define REPORT_OVERFLOW_HI 0
 
 static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
 
@@ -155,6 +160,8 @@ static void ppc_vbyte (int);
 static void ppc_elf_cons (int);
 static void ppc_elf_rdata (int);
 static void ppc_elf_lcomm (int);
+static void ppc_elf_localentry (int);
+static void ppc_elf_abiversion (int);
 #endif
 
 #ifdef TE_PE
@@ -225,6 +232,9 @@ unsigned long nop_limit = 4;
 ppc_cpu_t ppc_cpu = 0;
 ppc_cpu_t sticky = 0;
 
+/* Value for ELF e_flags EF_PPC64_ABI.  */
+unsigned int ppc_abiversion = 0;
+
 /* Flags set on encountering toc relocs.  */
 enum {
   has_large_toc_reloc = 1,
@@ -283,6 +293,8 @@ const pseudo_typeS md_pseudo_table[] =
   { "rdata",	ppc_elf_rdata,	0 },
   { "rodata",	ppc_elf_rdata,	0 },
   { "lcomm",	ppc_elf_lcomm,	0 },
+  { "localentry", ppc_elf_localentry,	0 },
+  { "abiversion", ppc_elf_abiversion,	0 },
 #endif
 
 #ifdef TE_PE
@@ -1949,6 +1961,8 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
     MAP32 ("bitfld",		BFD_RELOC_PPC_EMB_BIT_FLD),
     MAP32 ("relsda",		BFD_RELOC_PPC_EMB_RELSDA),
     MAP32 ("xgot",		BFD_RELOC_PPC_TOC16),
+    MAP64 ("high",		BFD_RELOC_PPC64_ADDR16_HIGH),
+    MAP64 ("higha",		BFD_RELOC_PPC64_ADDR16_HIGHA),
     MAP64 ("higher",		BFD_RELOC_PPC64_HIGHER),
     MAP64 ("highera",		BFD_RELOC_PPC64_HIGHER_S),
     MAP64 ("highest",		BFD_RELOC_PPC64_HIGHEST),
@@ -1958,10 +1972,14 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
     MAP64 ("toc@l",		BFD_RELOC_PPC64_TOC16_LO),
     MAP64 ("toc@h",		BFD_RELOC_PPC64_TOC16_HI),
     MAP64 ("toc@ha",		BFD_RELOC_PPC64_TOC16_HA),
+    MAP64 ("dtprel@high",	BFD_RELOC_PPC64_DTPREL16_HIGH),
+    MAP64 ("dtprel@higha",	BFD_RELOC_PPC64_DTPREL16_HIGHA),
     MAP64 ("dtprel@higher",	BFD_RELOC_PPC64_DTPREL16_HIGHER),
     MAP64 ("dtprel@highera",	BFD_RELOC_PPC64_DTPREL16_HIGHERA),
     MAP64 ("dtprel@highest",	BFD_RELOC_PPC64_DTPREL16_HIGHEST),
     MAP64 ("dtprel@highesta",	BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
+    MAP64 ("tprel@high",	BFD_RELOC_PPC64_TPREL16_HIGH),
+    MAP64 ("tprel@higha",	BFD_RELOC_PPC64_TPREL16_HIGHA),
     MAP64 ("tprel@higher",	BFD_RELOC_PPC64_TPREL16_HIGHER),
     MAP64 ("tprel@highera",	BFD_RELOC_PPC64_TPREL16_HIGHERA),
     MAP64 ("tprel@highest",	BFD_RELOC_PPC64_TPREL16_HIGHEST),
@@ -2237,6 +2255,101 @@ ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Pseudo op to set symbol local entry point.  */
+static void
+ppc_elf_localentry (int ignore ATTRIBUTE_UNUSED)
+{
+  char *name = input_line_pointer;
+  char c = get_symbol_end ();
+  char *p;
+  expressionS exp;
+  symbolS *sym;
+  asymbol *bfdsym;
+  elf_symbol_type *elfsym;
+
+  p = input_line_pointer;
+  *p = c;
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer != ',')
+    {
+      *p = 0;
+      as_bad (_("expected comma after name `%s' in .localentry directive"),
+	      name);
+      *p = c;
+      ignore_rest_of_line ();
+      return;
+    }
+  input_line_pointer++;
+  expression (&exp);
+  if (exp.X_op == O_absent)
+    {
+      as_bad (_("missing expression in .localentry directive"));
+      exp.X_op = O_constant;
+      exp.X_add_number = 0;
+    }
+  *p = 0;
+  sym = symbol_find_or_make (name);
+  *p = c;
+
+  if (resolve_expression (&exp)
+      && exp.X_op == O_constant)
+    {
+      unsigned char encoded = PPC64_SET_LOCAL_ENTRY_OFFSET (exp.X_add_number);
+
+      if (exp.X_add_number != PPC64_LOCAL_ENTRY_OFFSET (encoded))
+        as_bad (_(".localentry expression for `%s' "
+		  "is not a valid power of 2"), S_GET_NAME (sym));
+      else
+	{
+	  bfdsym = symbol_get_bfdsym (sym);
+	  elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
+	  gas_assert (elfsym);
+	  elfsym->internal_elf_sym.st_other &= ~STO_PPC64_LOCAL_MASK;
+	  elfsym->internal_elf_sym.st_other |= encoded;
+	  if (ppc_abiversion == 0)
+	    ppc_abiversion = 2;
+	}
+    }
+  else
+    as_bad (_(".localentry expression for `%s' "
+	      "does not evaluate to a constant"), S_GET_NAME (sym));
+
+  demand_empty_rest_of_line ();
+}
+
+/* Pseudo op to set ABI version.  */
+static void
+ppc_elf_abiversion (int ignore ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+
+  expression (&exp);
+  if (exp.X_op == O_absent)
+    {
+      as_bad (_("missing expression in .abiversion directive"));
+      exp.X_op = O_constant;
+      exp.X_add_number = 0;
+    }
+
+  if (resolve_expression (&exp)
+      && exp.X_op == O_constant)
+    ppc_abiversion = exp.X_add_number;
+  else
+    as_bad (_(".abiversion expression does not evaluate to a constant"));
+  demand_empty_rest_of_line ();
+}
+
+/* Set ABI version in output file.  */
+void
+ppc_elf_end (void)
+{
+  if (ppc_obj64 && ppc_abiversion != 0)
+    {
+      elf_elfheader (stdoutput)->e_flags &= ~EF_PPC64_ABI;
+      elf_elfheader (stdoutput)->e_flags |= ppc_abiversion & EF_PPC64_ABI;
+    }
+}
+
 /* Validate any relocations emitted for -mrelocatable, possibly adding
    fixups for word relocations in writable segments, so we can adjust
    them at runtime.  */
@@ -2838,55 +2951,76 @@ md_assemble (char *str)
 		break;
 
 	      case BFD_RELOC_LO16:
-		/* X_unsigned is the default, so if the user has done
-		   something which cleared it, we always produce a
-		   signed value.  */
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number &= 0xffff;
-		else
+		ex.X_add_number &= 0xffff;
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
 		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_HI16:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HI (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HI (ex.X_add_number));
+		if (REPORT_OVERFLOW_HI && ppc_obj64)
+		  {
+		    /* PowerPC64 @h is tested for overflow.  */
+		    ex.X_add_number = (addressT) ex.X_add_number >> 16;
+		    if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		      {
+			addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
+			ex.X_add_number
+			  = ((addressT) ex.X_add_number ^ sign) - sign;
+		      }
+		    break;
+		  }
+		/* Fall thru */
+
+	      case BFD_RELOC_PPC64_ADDR16_HIGH:
+		ex.X_add_number = PPC_HI (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_HI16_S:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HA (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HA (ex.X_add_number));
+		if (REPORT_OVERFLOW_HI && ppc_obj64)
+		  {
+		    /* PowerPC64 @ha is tested for overflow.  */
+		    ex.X_add_number
+		      = ((addressT) ex.X_add_number + 0x8000) >> 16;
+		    if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		      {
+			addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
+			ex.X_add_number
+			  = ((addressT) ex.X_add_number ^ sign) - sign;
+		      }
+		    break;
+		  }
+		/* Fall thru */
+
+	      case BFD_RELOC_PPC64_ADDR16_HIGHA:
+		ex.X_add_number = PPC_HA (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_PPC64_HIGHER:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HIGHER (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HIGHER (ex.X_add_number));
+		ex.X_add_number = PPC_HIGHER (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_PPC64_HIGHER_S:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HIGHERA (ex.X_add_number));
+		ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_PPC64_HIGHEST:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HIGHEST (ex.X_add_number));
+		ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 
 	      case BFD_RELOC_PPC64_HIGHEST_S:
-		if (ex.X_unsigned && ! (operand->flags & PPC_OPERAND_SIGNED))
-		  ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
-		else
-		  ex.X_add_number = SEX16 (PPC_HIGHESTA (ex.X_add_number));
+		ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
+		if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+		  ex.X_add_number = SEX16 (ex.X_add_number);
 		break;
 	      }
 #endif /* OBJ_ELF */
@@ -6172,6 +6306,22 @@ ppc_force_relocation (fixS *fix)
     case BFD_RELOC_24_PLT_PCREL:
     case BFD_RELOC_PPC64_TOC:
       return 1;
+    case BFD_RELOC_PPC_B26:
+    case BFD_RELOC_PPC_BA26:
+    case BFD_RELOC_PPC_B16:
+    case BFD_RELOC_PPC_BA16:
+      /* All branch fixups targeting a localentry symbol must
+         force a relocation.  */
+      if (fix->fx_addsy)
+	{
+	  asymbol *bfdsym = symbol_get_bfdsym (fix->fx_addsy);
+	  elf_symbol_type *elfsym
+	    = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
+	  gas_assert (elfsym);
+	  if ((STO_PPC64_LOCAL_MASK & elfsym->internal_elf_sym.st_other) != 0)
+	    return 1;
+	}
+      break;
     default:
       break;
     }
@@ -6186,6 +6336,32 @@ ppc_force_relocation (fixS *fix)
 int
 ppc_fix_adjustable (fixS *fix)
 {
+  switch (fix->fx_r_type)
+    {
+      /* All branch fixups targeting a localentry symbol must
+         continue using the symbol.  */
+    case BFD_RELOC_PPC_B26:
+    case BFD_RELOC_PPC_BA26:
+    case BFD_RELOC_PPC_B16:
+    case BFD_RELOC_PPC_BA16:
+    case BFD_RELOC_PPC_B16_BRTAKEN:
+    case BFD_RELOC_PPC_B16_BRNTAKEN:
+    case BFD_RELOC_PPC_BA16_BRTAKEN:
+    case BFD_RELOC_PPC_BA16_BRNTAKEN:
+      if (fix->fx_addsy)
+	{
+	  asymbol *bfdsym = symbol_get_bfdsym (fix->fx_addsy);
+	  elf_symbol_type *elfsym
+	    = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
+	  gas_assert (elfsym);
+	  if ((STO_PPC64_LOCAL_MASK & elfsym->internal_elf_sym.st_other) != 0)
+	    return 0;
+	}
+      break;
+    default:
+      break;
+    }
+
   return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
 	  && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
 	  && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF
@@ -6465,10 +6641,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	case BFD_RELOC_PPC_GOT_DTPREL16_HA:
 	case BFD_RELOC_PPC64_TPREL16_DS:
 	case BFD_RELOC_PPC64_TPREL16_LO_DS:
+	case BFD_RELOC_PPC64_TPREL16_HIGH:
+	case BFD_RELOC_PPC64_TPREL16_HIGHA:
 	case BFD_RELOC_PPC64_TPREL16_HIGHER:
 	case BFD_RELOC_PPC64_TPREL16_HIGHERA:
 	case BFD_RELOC_PPC64_TPREL16_HIGHEST:
 	case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+	case BFD_RELOC_PPC64_DTPREL16_HIGH:
+	case BFD_RELOC_PPC64_DTPREL16_HIGHA:
 	case BFD_RELOC_PPC64_DTPREL16_DS:
 	case BFD_RELOC_PPC64_DTPREL16_LO_DS:
 	case BFD_RELOC_PPC64_DTPREL16_HIGHER:
@@ -6836,10 +7016,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	case BFD_RELOC_PPC64_TOC16_LO:
 	case BFD_RELOC_PPC64_TOC16_HI:
 	case BFD_RELOC_PPC64_TOC16_HA:
+	case BFD_RELOC_PPC64_DTPREL16_HIGH:
+	case BFD_RELOC_PPC64_DTPREL16_HIGHA:
 	case BFD_RELOC_PPC64_DTPREL16_HIGHER:
 	case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
 	case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
 	case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+	case BFD_RELOC_PPC64_TPREL16_HIGH:
+	case BFD_RELOC_PPC64_TPREL16_HIGHA:
 	case BFD_RELOC_PPC64_TPREL16_HIGHER:
 	case BFD_RELOC_PPC64_TPREL16_HIGHERA:
 	case BFD_RELOC_PPC64_TPREL16_HIGHEST:
diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h
index 3dd3f81..6095416 100644
--- a/gas/config/tc-ppc.h
+++ b/gas/config/tc-ppc.h
@@ -238,6 +238,9 @@ extern void ppc_frob_file_before_adjust (void);
 #define tc_adjust_symtab() ppc_elf_adjust_symtab ()
 extern void ppc_elf_adjust_symtab (void);
 
+extern void ppc_elf_end (void);
+#define md_end ppc_elf_end
+
 #endif /* OBJ_ELF */
 
 #if defined (OBJ_ELF) || defined (OBJ_XCOFF)
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index e192885..38a36ac 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -72,12 +72,19 @@ public:
 		 const typename elfcpp::Ehdr<size, big_endian>& ehdr)
     : Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
       special_(0), has_small_toc_reloc_(false), opd_valid_(false),
-      opd_ent_(), access_from_map_(), has14_(), stub_table_()
-  { }
+      opd_ent_(), access_from_map_(), has14_(), stub_table_(),
+      e_flags_(ehdr.get_e_flags()), st_other_()
+  {
+    this->set_abiversion(0);
+  }
 
   ~Powerpc_relobj()
   { }
 
+  // Read the symbols then set up st_other vector.
+  void
+  do_read_symbols(Read_symbols_data*);
+
   // The .got2 section shndx.
   unsigned int
   got2_shndx() const
@@ -263,6 +270,22 @@ public:
     return NULL;
   }
 
+  int
+  abiversion() const
+  { return this->e_flags_ & elfcpp::EF_PPC64_ABI; }
+
+  // Set ABI version for input and output
+  void
+  set_abiversion(int ver);
+
+  unsigned int
+  ppc64_local_entry_offset(const Symbol* sym) const
+  { return elfcpp::ppc64_decode_local_entry(sym->nonvis() >> 3); }
+
+  unsigned int
+  ppc64_local_entry_offset(unsigned int symndx) const
+  { return elfcpp::ppc64_decode_local_entry(this->st_other_[symndx] >> 5); }
+
 private:
   struct Opd_ent
   {
@@ -316,6 +339,12 @@ private:
 
   // The stub table to use for a given input section.
   std::vector<Stub_table<size, big_endian>*> stub_table_;
+
+  // Header e_flags
+  elfcpp::Elf_Word e_flags_;
+
+  // ELF st_other field for local symbols.
+  std::vector<unsigned char> st_other_;
 };
 
 template<int size, bool big_endian>
@@ -1305,6 +1334,14 @@ public:
     STATUS_OVERFLOW
   };
 
+  int
+  abiversion() const
+  { return this->e_flags_ & elfcpp::EF_PPC64_ABI; }
+
+  // Set ABI version for input and output.
+  void
+  set_abiversion(int ver);
+
 private:
   typedef Powerpc_relocate_functions<size, big_endian> This;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
@@ -1930,6 +1967,24 @@ class Stub_control
   output_section()
   { return output_section_; }
 
+  int
+  abiversion () const
+  { return this->processor_specific_flags() & elfcpp::EF_PPC64_ABI; }
+
+  void
+  set_abiversion (int ver)
+  {
+    elfcpp::Elf_Word flags = this->processor_specific_flags();
+    flags &= ~elfcpp::EF_PPC64_ABI;
+    flags |= ver & elfcpp::EF_PPC64_ABI;
+    this->set_processor_specific_flags(flags);
+  }
+
+  // Offset to to save stack slot
+  int
+  stk_toc () const
+  { return this->abiversion() < 2 ? 40 : 24; }
+
  private:
   typedef enum
   {
@@ -3605,6 +3660,26 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
 	    }
 	}
     }
+  else
+    {
+      // Define .TOC. as for 32-bit _GLOBAL_OFFSET_TABLE_
+      Symbol *gotsym = symtab->lookup(".TOC.", NULL);
+      if (gotsym != NULL && gotsym->is_undefined())
+	{
+	  Target_powerpc<size, big_endian>* target =
+	    static_cast<Target_powerpc<size, big_endian>*>(
+		parameters->sized_target<size, big_endian>());
+	  Output_data_got_powerpc<size, big_endian>* got
+	    = target->got_section(symtab, layout);
+	  symtab->define_in_output_data(".TOC.", NULL,
+					Symbol_table::PREDEFINED,
+					got, 0x8000, 0,
+					elfcpp::STT_OBJECT,
+					elfcpp::STB_LOCAL,
+					elfcpp::STV_HIDDEN, 0,
+					false, false);
+	}
+    }
 }
 
 // Write out .glink.
@@ -3632,16 +3707,34 @@ Output_data_glink<size, big_endian>::do_write(Output_file* of)
 
       elfcpp::Swap<64, big_endian>::writeval(p, pltoff),	p += 8;
 
-      write_insn<big_endian>(p, mflr_12),			p += 4;
-      write_insn<big_endian>(p, bcl_20_31),			p += 4;
-      write_insn<big_endian>(p, mflr_11),			p += 4;
-      write_insn<big_endian>(p, ld_2_11 + l(-16)),		p += 4;
-      write_insn<big_endian>(p, mtlr_12),			p += 4;
-      write_insn<big_endian>(p, add_12_2_11),			p += 4;
-      write_insn<big_endian>(p, ld_11_12 + 0),			p += 4;
-      write_insn<big_endian>(p, ld_2_12 + 8),			p += 4;
-      write_insn<big_endian>(p, mtctr_11),			p += 4;
-      write_insn<big_endian>(p, ld_11_12 + 16),			p += 4;
+      if (this->targ_->abiversion() < 2)
+	{
+	  write_insn<big_endian>(p, mflr_12),			p += 4;
+	  write_insn<big_endian>(p, bcl_20_31),			p += 4;
+	  write_insn<big_endian>(p, mflr_11),			p += 4;
+	  write_insn<big_endian>(p, ld_2_11 + l(-16)),		p += 4;
+	  write_insn<big_endian>(p, mtlr_12),			p += 4;
+	  write_insn<big_endian>(p, add_11_2_11),		p += 4;
+	  write_insn<big_endian>(p, ld_12_11 + 0),		p += 4;
+	  write_insn<big_endian>(p, ld_2_11 + 8),		p += 4;
+	  write_insn<big_endian>(p, mtctr_12),			p += 4;
+	  write_insn<big_endian>(p, ld_11_11 + 16),		p += 4;
+	}
+      else
+	{
+	  write_insn<big_endian>(p, mflr_0),			p += 4;
+	  write_insn<big_endian>(p, bcl_20_31),			p += 4;
+	  write_insn<big_endian>(p, mflr_11),			p += 4;
+	  write_insn<big_endian>(p, ld_2_11 + l(-16)),		p += 4;
+	  write_insn<big_endian>(p, mtlr_0),			p += 4;
+	  write_insn<big_endian>(p, sub_12_12_11),		p += 4;
+	  write_insn<big_endian>(p, add_11_2_11),		p += 4;
+	  write_insn<big_endian>(p, addi_0_12 + l(-48)),	p += 4;
+	  write_insn<big_endian>(p, ld_12_11 + 0),		p += 4;
+	  write_insn<big_endian>(p, srdi_0_0_2),		p += 4;
+	  write_insn<big_endian>(p, mtctr_12),			p += 4;
+	  write_insn<big_endian>(p, ld_11_11 + 8),		p += 4;
+	}
       write_insn<big_endian>(p, bctr),				p += 4;
       while (p < oview + this->pltresolve_size)
 	write_insn<big_endian>(p, nop), p += 4;
@@ -3650,14 +3743,17 @@ Output_data_glink<size, big_endian>::do_write(Output_file* of)
       uint32_t indx = 0;
       while (p < oview + oview_size)
 	{
-	  if (indx < 0x8000)
-	    {
-	      write_insn<big_endian>(p, li_0_0 + indx),			p += 4;
-	    }
-	  else
+	  if (this->targ_->abiversion() < 2)
 	    {
-	      write_insn<big_endian>(p, lis_0_0 + hi(indx)),		p += 4;
-	      write_insn<big_endian>(p, ori_0_0_0 + l(indx)),		p += 4;
+	      if (indx < 0x8000)
+		{
+		  write_insn<big_endian>(p, li_0_0 + indx),		p += 4;
+		}
+	      else
+		{
+		  write_insn<big_endian>(p, lis_0_0 + hi(indx)),	p += 4;
+		  write_insn<big_endian>(p, ori_0_0_0 + l(indx)),	p += 4;
+		}
 	    }
 	  uint32_t branch_off = 8 - (p - oview);
 	  write_insn<big_endian>(p, b + (branch_off & 0x3fffffc)),	p += 4;
@@ -4144,24 +4240,6 @@ Target_powerpc<size, big_endian>::plt_entry_count() const
   return count;
 }
 
-// Return the offset of the first non-reserved PLT entry.
-
-template<int size, bool big_endian>
-unsigned int
-Target_powerpc<size, big_endian>::first_plt_entry_offset() const
-{
-  return this->plt_->first_plt_entry_offset();
-}
-
-// Return the size of each PLT entry.
-
-template<int size, bool big_endian>
-unsigned int
-Target_powerpc<size, big_endian>::plt_entry_size() const
-{
-  return Output_data_plt_powerpc<size, big_endian>::get_plt_entry_size();
-}
-
 // Create a GOT entry for local dynamic __tls_get_addr calls.
 
 template<int size, bool big_endian>
@@ -4189,8 +4267,12 @@ Target_powerpc<size, big_endian>::tlsld_got_offset(
 
 template<int size, bool big_endian>
 int
-Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
+Target_powerpc<size, big_endian>::Scan::get_reference_flags(
+    unsigned int r_type,
+    const Target_powerpc* target)
 {
+  int ref = 0;
+
   switch (r_type)
     {
     case elfcpp::R_POWERPC_NONE:
@@ -4198,7 +4280,7 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC64_TOC:
       // No symbol reference.
-      return 0;
+      break;
 
     case elfcpp::R_PPC64_ADDR64:
     case elfcpp::R_PPC64_UADDR64:
@@ -4209,13 +4291,15 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
     case elfcpp::R_POWERPC_ADDR16_LO:
     case elfcpp::R_POWERPC_ADDR16_HI:
     case elfcpp::R_POWERPC_ADDR16_HA:
-      return Symbol::ABSOLUTE_REF;
+      ref = Symbol::ABSOLUTE_REF;
+      break;
 
     case elfcpp::R_POWERPC_ADDR24:
     case elfcpp::R_POWERPC_ADDR14:
     case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
     case elfcpp::R_POWERPC_ADDR14_BRNTAKEN:
-      return Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
+      ref = Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
+      break;
 
     case elfcpp::R_PPC64_REL64:
     case elfcpp::R_POWERPC_REL32:
@@ -4224,14 +4308,16 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
     case elfcpp::R_POWERPC_REL16_LO:
     case elfcpp::R_POWERPC_REL16_HI:
     case elfcpp::R_POWERPC_REL16_HA:
-      return Symbol::RELATIVE_REF;
+      ref = Symbol::RELATIVE_REF;
+      break;
 
     case elfcpp::R_POWERPC_REL24:
     case elfcpp::R_PPC_PLTREL24:
     case elfcpp::R_POWERPC_REL14:
     case elfcpp::R_POWERPC_REL14_BRTAKEN:
     case elfcpp::R_POWERPC_REL14_BRNTAKEN:
-      return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+      ref = Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+      break;
 
     case elfcpp::R_POWERPC_GOT16:
     case elfcpp::R_POWERPC_GOT16_LO:
@@ -4246,11 +4332,13 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
     case elfcpp::R_PPC64_TOC16_DS:
     case elfcpp::R_PPC64_TOC16_LO_DS:
       // Absolute in GOT.
-      return Symbol::ABSOLUTE_REF;
+      ref = Symbol::ABSOLUTE_REF;
+      break;
 
     case elfcpp::R_POWERPC_GOT_TPREL16:
     case elfcpp::R_POWERPC_TLS:
-      return Symbol::TLS_REF;
+      ref = Symbol::TLS_REF;
+      break;
 
     case elfcpp::R_POWERPC_COPY:
     case elfcpp::R_POWERPC_GLOB_DAT:
@@ -4259,8 +4347,12 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
     case elfcpp::R_POWERPC_DTPMOD:
     default:
       // Not expected.  We will give an error later.
-      return 0;
+      break;
     }
+
+  if (size == 64 && target->abiversion() < 2)
+    ref |= Symbol::FUNC_DESC_ABI;
+  return ref;
 }
 
 // Report an unsupported relocation against a local symbol.
@@ -4331,6 +4423,8 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object,
 	case elfcpp::R_PPC64_JMP_IREL:
 	case elfcpp::R_PPC64_ADDR16_DS:
 	case elfcpp::R_PPC64_ADDR16_LO_DS:
+	case elfcpp::R_PPC64_ADDR16_HIGH:
+	case elfcpp::R_PPC64_ADDR16_HIGHA:
 	case elfcpp::R_PPC64_ADDR16_HIGHER:
 	case elfcpp::R_PPC64_ADDR16_HIGHEST:
 	case elfcpp::R_PPC64_ADDR16_HIGHERA:
@@ -4339,6 +4433,8 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object,
 	case elfcpp::R_POWERPC_ADDR30:
 	case elfcpp::R_PPC64_TPREL16_DS:
 	case elfcpp::R_PPC64_TPREL16_LO_DS:
+	case elfcpp::R_PPC64_TPREL16_HIGH:
+	case elfcpp::R_PPC64_TPREL16_HIGHA:
 	case elfcpp::R_PPC64_TPREL16_HIGHER:
 	case elfcpp::R_PPC64_TPREL16_HIGHEST:
 	case elfcpp::R_PPC64_TPREL16_HIGHERA:
@@ -4509,7 +4605,6 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_POWERPC_GNU_VTINHERIT:
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC64_TOCSAVE:
-    case elfcpp::R_PPC_EMB_MRKREF:
     case elfcpp::R_POWERPC_TLS:
       break;
 
@@ -4546,6 +4641,8 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_POWERPC_ADDR16_HI:
     case elfcpp::R_POWERPC_ADDR16_HA:
     case elfcpp::R_POWERPC_UADDR16:
+    case elfcpp::R_PPC64_ADDR16_HIGH:
+    case elfcpp::R_PPC64_ADDR16_HIGHA:
     case elfcpp::R_PPC64_ADDR16_HIGHER:
     case elfcpp::R_PPC64_ADDR16_HIGHERA:
     case elfcpp::R_PPC64_ADDR16_HIGHEST:
@@ -4612,31 +4709,35 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_POWERPC_REL16_HI:
     case elfcpp::R_POWERPC_REL16_HA:
     case elfcpp::R_POWERPC_SECTOFF:
-    case elfcpp::R_POWERPC_TPREL16:
-    case elfcpp::R_POWERPC_DTPREL16:
     case elfcpp::R_POWERPC_SECTOFF_LO:
-    case elfcpp::R_POWERPC_TPREL16_LO:
-    case elfcpp::R_POWERPC_DTPREL16_LO:
     case elfcpp::R_POWERPC_SECTOFF_HI:
-    case elfcpp::R_POWERPC_TPREL16_HI:
-    case elfcpp::R_POWERPC_DTPREL16_HI:
     case elfcpp::R_POWERPC_SECTOFF_HA:
+    case elfcpp::R_PPC64_SECTOFF_DS:
+    case elfcpp::R_PPC64_SECTOFF_LO_DS:
+    case elfcpp::R_POWERPC_TPREL16:
+    case elfcpp::R_POWERPC_TPREL16_LO:
+    case elfcpp::R_POWERPC_TPREL16_HI:
     case elfcpp::R_POWERPC_TPREL16_HA:
-    case elfcpp::R_POWERPC_DTPREL16_HA:
-    case elfcpp::R_PPC64_DTPREL16_HIGHER:
+    case elfcpp::R_PPC64_TPREL16_DS:
+    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
     case elfcpp::R_PPC64_TPREL16_HIGHER:
-    case elfcpp::R_PPC64_DTPREL16_HIGHERA:
     case elfcpp::R_PPC64_TPREL16_HIGHERA:
-    case elfcpp::R_PPC64_DTPREL16_HIGHEST:
     case elfcpp::R_PPC64_TPREL16_HIGHEST:
-    case elfcpp::R_PPC64_DTPREL16_HIGHESTA:
     case elfcpp::R_PPC64_TPREL16_HIGHESTA:
-    case elfcpp::R_PPC64_TPREL16_DS:
-    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_POWERPC_DTPREL16:
+    case elfcpp::R_POWERPC_DTPREL16_LO:
+    case elfcpp::R_POWERPC_DTPREL16_HI:
+    case elfcpp::R_POWERPC_DTPREL16_HA:
     case elfcpp::R_PPC64_DTPREL16_DS:
     case elfcpp::R_PPC64_DTPREL16_LO_DS:
-    case elfcpp::R_PPC64_SECTOFF_DS:
-    case elfcpp::R_PPC64_SECTOFF_LO_DS:
+    case elfcpp::R_PPC64_DTPREL16_HIGH:
+    case elfcpp::R_PPC64_DTPREL16_HIGHA:
+    case elfcpp::R_PPC64_DTPREL16_HIGHER:
+    case elfcpp::R_PPC64_DTPREL16_HIGHERA:
+    case elfcpp::R_PPC64_DTPREL16_HIGHEST:
+    case elfcpp::R_PPC64_DTPREL16_HIGHESTA:
     case elfcpp::R_PPC64_TLSGD:
     case elfcpp::R_PPC64_TLSLD:
       break;
@@ -4870,7 +4971,6 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_POWERPC_GNU_VTINHERIT:
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC_LOCAL24PC:
-    case elfcpp::R_PPC_EMB_MRKREF:
     case elfcpp::R_POWERPC_TLS:
       break;
 
@@ -4919,6 +5019,8 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_POWERPC_ADDR16_HI:
     case elfcpp::R_POWERPC_ADDR16_HA:
     case elfcpp::R_POWERPC_UADDR16:
+    case elfcpp::R_PPC64_ADDR16_HIGH:
+    case elfcpp::R_PPC64_ADDR16_HIGHA:
     case elfcpp::R_PPC64_ADDR16_HIGHER:
     case elfcpp::R_PPC64_ADDR16_HIGHERA:
     case elfcpp::R_PPC64_ADDR16_HIGHEST:
@@ -5005,7 +5107,7 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_PPC64_REL64:
     case elfcpp::R_POWERPC_REL32:
       // Make a dynamic relocation if necessary.
-      if (needs_dynamic_reloc<size>(gsym, Scan::get_reference_flags(r_type)))
+      if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type, target)))
 	{
 	  if (gsym->may_need_copy_reloc())
 	    {
@@ -5037,31 +5139,35 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_POWERPC_REL16_HI:
     case elfcpp::R_POWERPC_REL16_HA:
     case elfcpp::R_POWERPC_SECTOFF:
-    case elfcpp::R_POWERPC_TPREL16:
-    case elfcpp::R_POWERPC_DTPREL16:
     case elfcpp::R_POWERPC_SECTOFF_LO:
-    case elfcpp::R_POWERPC_TPREL16_LO:
-    case elfcpp::R_POWERPC_DTPREL16_LO:
     case elfcpp::R_POWERPC_SECTOFF_HI:
-    case elfcpp::R_POWERPC_TPREL16_HI:
-    case elfcpp::R_POWERPC_DTPREL16_HI:
     case elfcpp::R_POWERPC_SECTOFF_HA:
+    case elfcpp::R_PPC64_SECTOFF_DS:
+    case elfcpp::R_PPC64_SECTOFF_LO_DS:
+    case elfcpp::R_POWERPC_TPREL16:
+    case elfcpp::R_POWERPC_TPREL16_LO:
+    case elfcpp::R_POWERPC_TPREL16_HI:
     case elfcpp::R_POWERPC_TPREL16_HA:
-    case elfcpp::R_POWERPC_DTPREL16_HA:
-    case elfcpp::R_PPC64_DTPREL16_HIGHER:
+    case elfcpp::R_PPC64_TPREL16_DS:
+    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
     case elfcpp::R_PPC64_TPREL16_HIGHER:
-    case elfcpp::R_PPC64_DTPREL16_HIGHERA:
     case elfcpp::R_PPC64_TPREL16_HIGHERA:
-    case elfcpp::R_PPC64_DTPREL16_HIGHEST:
     case elfcpp::R_PPC64_TPREL16_HIGHEST:
-    case elfcpp::R_PPC64_DTPREL16_HIGHESTA:
     case elfcpp::R_PPC64_TPREL16_HIGHESTA:
-    case elfcpp::R_PPC64_TPREL16_DS:
-    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_POWERPC_DTPREL16:
+    case elfcpp::R_POWERPC_DTPREL16_LO:
+    case elfcpp::R_POWERPC_DTPREL16_HI:
+    case elfcpp::R_POWERPC_DTPREL16_HA:
     case elfcpp::R_PPC64_DTPREL16_DS:
     case elfcpp::R_PPC64_DTPREL16_LO_DS:
-    case elfcpp::R_PPC64_SECTOFF_DS:
-    case elfcpp::R_PPC64_SECTOFF_LO_DS:
+    case elfcpp::R_PPC64_DTPREL16_HIGH:
+    case elfcpp::R_PPC64_DTPREL16_HIGHA:
+    case elfcpp::R_PPC64_DTPREL16_HIGHER:
+    case elfcpp::R_PPC64_DTPREL16_HIGHERA:
+    case elfcpp::R_PPC64_DTPREL16_HIGHEST:
+    case elfcpp::R_PPC64_DTPREL16_HIGHESTA:
     case elfcpp::R_PPC64_TLSGD:
     case elfcpp::R_PPC64_TLSLD:
       break;
@@ -5794,7 +5900,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 		  && (insn2 == nop
 		      || insn2 == cror_15_15_15 || insn2 == cror_31_31_31))
 		{
-		  elfcpp::Swap<32, big_endian>::writeval(wv + 1, ld_2_1 + 40);
+		  elfcpp::Swap<32, big_endian>::
+		    writeval(wv + 1, ld_2_1 + target->stk_toc());
 		  can_plt_call = true;
 		}
 	    }
@@ -6083,6 +6190,10 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       if (r_type != elfcpp::R_PPC_PLTREL24)
 	addend = rela.get_r_addend();
       value = psymval->value(object, addend);
+      if (gsym != NULL)
+	value += object->ppc64_local_entry_offset(gsym);
+      else
+	value += object->ppc64_local_entry_offset(r_sym);
       if (size == 64 && is_branch_reloc(r_type))
 	value = target->symval_for_branch(value, gsym, object, &dest_shndx);
       unsigned int max_branch_offset = 0;
@@ -6146,8 +6257,10 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
 
     case elfcpp::R_PPC64_TPREL16_DS:
     case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
       if (size != 64)
-	// R_PPC_TLSGD and R_PPC_TLSLD
+	// R_PPC_TLSGD, R_PPC_TLSLD, R_PPC_EMB_RELST_LO, R_PPC_EMB_RELST_HI
 	break;
     case elfcpp::R_POWERPC_TPREL16:
     case elfcpp::R_POWERPC_TPREL16_LO:
@@ -6177,6 +6290,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_POWERPC_DTPREL16_HI:
     case elfcpp::R_POWERPC_DTPREL16_HA:
     case elfcpp::R_POWERPC_DTPREL:
+    case elfcpp::R_PPC64_DTPREL16_HIGH:
+    case elfcpp::R_PPC64_DTPREL16_HIGHA:
       // tls symbol values are relative to tls_segment()->vaddr()
       value -= dtp_offset;
       break;
@@ -6317,6 +6432,34 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       overflow = Reloc::CHECK_BITFIELD;
       break;
 
+    case elfcpp::R_POWERPC_ADDR16_HI:
+    case elfcpp::R_POWERPC_ADDR16_HA:
+    case elfcpp::R_POWERPC_GOT16_HI:
+    case elfcpp::R_POWERPC_GOT16_HA:
+    case elfcpp::R_POWERPC_PLT16_HI:
+    case elfcpp::R_POWERPC_PLT16_HA:
+    case elfcpp::R_POWERPC_SECTOFF_HI:
+    case elfcpp::R_POWERPC_SECTOFF_HA:
+    case elfcpp::R_PPC64_TOC16_HI:
+    case elfcpp::R_PPC64_TOC16_HA:
+    case elfcpp::R_PPC64_PLTGOT16_HI:
+    case elfcpp::R_PPC64_PLTGOT16_HA:
+    case elfcpp::R_POWERPC_TPREL16_HI:
+    case elfcpp::R_POWERPC_TPREL16_HA:
+    case elfcpp::R_POWERPC_DTPREL16_HI:
+    case elfcpp::R_POWERPC_DTPREL16_HA:
+    case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
+    case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
+    case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
+    case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
+    case elfcpp::R_POWERPC_GOT_TPREL16_HI:
+    case elfcpp::R_POWERPC_GOT_TPREL16_HA:
+    case elfcpp::R_POWERPC_GOT_DTPREL16_HI:
+    case elfcpp::R_POWERPC_GOT_DTPREL16_HA:
+    case elfcpp::R_POWERPC_REL16_HI:
+    case elfcpp::R_POWERPC_REL16_HA:
+      if (size == 32)
+	break;
     case elfcpp::R_POWERPC_REL24:
     case elfcpp::R_PPC_PLTREL24:
     case elfcpp::R_PPC_LOCAL24PC:
@@ -6350,7 +6493,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_POWERPC_TLS:
     case elfcpp::R_POWERPC_GNU_VTINHERIT:
     case elfcpp::R_POWERPC_GNU_VTENTRY:
-    case elfcpp::R_PPC_EMB_MRKREF:
       break;
 
     case elfcpp::R_PPC64_ADDR64:
@@ -6421,6 +6563,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       status = Reloc::addr16_u(view, value, overflow);
       break;
 
+    case elfcpp::R_PPC64_ADDR16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_DTPREL16_HIGH:
+      if (size == 32)
+	// R_PPC_EMB_MRKREF, R_PPC_EMB_RELST_LO, R_PPC_EMB_RELST_HA
+	goto unsupp;
     case elfcpp::R_POWERPC_ADDR16_HI:
     case elfcpp::R_POWERPC_REL16_HI:
     case elfcpp::R_PPC64_TOC16_HI:
@@ -6435,6 +6583,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       Reloc::addr16_hi(view, value);
       break;
 
+    case elfcpp::R_PPC64_ADDR16_HIGHA:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
+    case elfcpp::R_PPC64_DTPREL16_HIGHA:
+      if (size == 32)
+	// R_PPC_EMB_RELSEC16, R_PPC_EMB_RELST_HI, R_PPC_EMB_BIT_FLD
+	goto unsupp;
     case elfcpp::R_POWERPC_ADDR16_HA:
     case elfcpp::R_POWERPC_REL16_HA:
     case elfcpp::R_PPC64_TOC16_HA:
@@ -6559,11 +6713,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_PLT16_LO_DS:
     case elfcpp::R_PPC64_PLTGOT16_DS:
     case elfcpp::R_PPC64_PLTGOT16_LO_DS:
-    case elfcpp::R_PPC_EMB_RELSEC16:
-    case elfcpp::R_PPC_EMB_RELST_LO:
-    case elfcpp::R_PPC_EMB_RELST_HI:
-    case elfcpp::R_PPC_EMB_RELST_HA:
-    case elfcpp::R_PPC_EMB_BIT_FLD:
     case elfcpp::R_PPC_EMB_RELSDA:
     case elfcpp::R_PPC_TOC16:
     default:
diff --git a/gold/symtab.h b/gold/symtab.h
index f26d4b9..457b8bd 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -634,7 +634,10 @@ class Symbol
     // A TLS-related reference.
     TLS_REF = 4,
     // A reference that can always be treated as a function call.
-    FUNCTION_CALL = 8
+    FUNCTION_CALL = 8,
+    // When set, says that dynamic relocations are needed even if a
+    // symbol has a plt entry.
+    FUNC_DESC_ABI = 16,
   };
 
   // Given a direct absolute or pc-relative static relocation against
@@ -671,7 +674,8 @@ class Symbol
 
     // A reference to any PLT entry in a non-position-independent executable
     // does not need a dynamic relocation.
-    if (!parameters->options().output_is_position_independent()
+    if (!(flags & FUNC_DESC_ABI)
+	&& !parameters->options().output_is_position_independent()
         && this->has_plt_offset())
       return false;
 
diff --git a/include/elf/ppc.h b/include/elf/ppc.h
index f80a1e8..da00df8 100644
--- a/include/elf/ppc.h
+++ b/include/elf/ppc.h
@@ -176,7 +176,8 @@ END_RELOC_NUMBERS (R_PPC_max)
 #define DT_PPC_GOT		(DT_LOPROC)
 
 /* Specify that tls descriptors should be optimized.  */
-#define DT_PPC_TLSOPT		(DT_LOPROC + 1)
+#define DT_PPC_OPT		(DT_LOPROC + 1)
+#define PPC_OPT_TLS		1
 
 /* Processor specific flags for the ELF header e_flags field.  */
 
diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h
index f1c80f1..78d947b 100644
--- a/include/elf/ppc64.h
+++ b/include/elf/ppc64.h
@@ -141,6 +141,14 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
   RELOC_NUMBER (R_PPC64_TLSLD,		   108)
   RELOC_NUMBER (R_PPC64_TOCSAVE,	   109)
 
+/* Added when HA and HI relocs were changed to report overflows.  */
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGH,	   110)
+  RELOC_NUMBER (R_PPC64_ADDR16_HIGHA,	   111)
+  RELOC_NUMBER (R_PPC64_TPREL16_HIGH,	   112)
+  RELOC_NUMBER (R_PPC64_TPREL16_HIGHA,	   113)
+  RELOC_NUMBER (R_PPC64_DTPREL16_HIGH,	   114)
+  RELOC_NUMBER (R_PPC64_DTPREL16_HIGHA,	   115)
+
 #ifndef RELOC_MACROS_GEN_FUNC
 /* Fake relocation only used internally by ld.  */
   RELOC_NUMBER (R_PPC64_LO_DS_OPT,	   128)
@@ -161,8 +169,63 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type)
 
 END_RELOC_NUMBERS (R_PPC64_max)
 
-#define IS_PPC64_TLS_RELOC(R) \
-  ((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA)
+#define IS_PPC64_TLS_RELOC(R)						\
+  (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA)		\
+   || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
+
+
+/* e_flags bits specifying ABI.
+   1 for original function descriptor using ABI,
+   2 for revised ABI without function descriptors,
+   0 for unspecified or not using any features affected by the differences.  */
+#define EF_PPC64_ABI	3
+
+/* The ELFv2 ABI uses three bits in the symbol st_other field of a
+   function definition to specify the number of instructions between a
+   function's global entry point and local entry point.
+   The global entry point is used when it is necessary to set up the
+   toc pointer (r2) for the function.  Callers must enter the global
+   entry point with r12 set to the global entry point address.  On
+   return from the function, r2 may have a different value to that
+   which it had on entry.
+   The local entry point is used when r2 is known to already be valid
+   for the function.  There is no requirement on r12 when using the
+   local entry point, and on return r2 will contain the same value as
+   at entry.
+   A value of zero in these bits means that the function has a single
+   entry point with no requirement on r12 or r2, and that on return r2
+   will contain the same value as at entry.
+   Values of one and seven are reserved.  */
+#define STO_PPC64_LOCAL_BIT		5
+#define STO_PPC64_LOCAL_MASK		(7 << STO_PPC64_LOCAL_BIT)
+
+// 3 bit other field to bytes.
+static inline unsigned int
+ppc64_decode_local_entry(unsigned int other)
+{
+  return ((1 << other) >> 2) << 2;
+}
+
+// bytes to field value.
+static inline unsigned int
+ppc64_encode_local_entry(unsigned int val)
+{
+  return (val >= 4 * 4
+	  ? (val >= 8 * 4
+	     ? (val >= 16 * 4 ? 6 : 5)
+	     : 4)
+	  : (val >= 2 * 4
+	     ? 3
+	     : (val >= 1 * 4 ? 2 : 0)));
+}
+
+/* st_other to number of bytes.  */
+#define PPC64_LOCAL_ENTRY_OFFSET(other)				\
+  ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK)	\
+			    >> STO_PPC64_LOCAL_BIT)
+/* number of bytes to st_other.  */
+#define PPC64_SET_LOCAL_ENTRY_OFFSET(val)		\
+  ppc64_encode_local_entry (val) << STO_PPC64_LOCAL_BIT
 
 /* Specify the start of the .glink section.  */
 #define DT_PPC64_GLINK		DT_LOPROC
@@ -171,7 +234,9 @@ END_RELOC_NUMBERS (R_PPC64_max)
 #define DT_PPC64_OPD		(DT_LOPROC + 1)
 #define DT_PPC64_OPDSZ		(DT_LOPROC + 2)
 
-/* Specify that tls descriptors should be optimized.  */
-#define DT_PPC64_TLSOPT		(DT_LOPROC + 3)
+/* Specify whether various optimisations are possible.  */
+#define DT_PPC64_OPT		(DT_LOPROC + 3)
+#define PPC64_OPT_TLS		1
+#define PPC64_OPT_MULTI_TOC	2
 
 #endif /* _ELF_PPC64_H */
diff --git a/ld/testsuite/ld-elfvers/vers24.rd b/ld/testsuite/ld-elfvers/vers24.rd
index 42e81e4..fb464f9 100644
--- a/ld/testsuite/ld-elfvers/vers24.rd
+++ b/ld/testsuite/ld-elfvers/vers24.rd
@@ -7,9 +7,9 @@ Symbol table '.dynsym' contains [0-9]+ entries:
 # And ensure the dynamic symbol table contains at least x@VERS.0
 # and foo@@VERS.0 symbols
 #...
- +[0-9]+: [0-9a-f]+ +(4 +OBJECT +GLOBAL +DEFAULT +[0-9]+ _?x|[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ _?foo@)@VERS\.0
+ +[0-9]+: [0-9a-f]+ +(4 +OBJECT +GLOBAL +DEFAULT +[0-9]+ _?x|[0-9]+ +FUNC +GLOBAL +DEFAULT .* [0-9]+ _?foo@)@VERS\.0
 #...
- +[0-9]+: [0-9a-f]+ +(4 +OBJECT +GLOBAL +DEFAULT +[0-9]+ _?x|[0-9]+ +FUNC +GLOBAL +DEFAULT +[0-9]+ _?foo@)@VERS\.0
+ +[0-9]+: [0-9a-f]+ +(4 +OBJECT +GLOBAL +DEFAULT +[0-9]+ _?x|[0-9]+ +FUNC +GLOBAL +DEFAULT .* [0-9]+ _?foo@)@VERS\.0
 #...
 Symbol table '.symtab' contains [0-9]+ entries:
 #pass
diff --git a/ld/testsuite/ld-ifunc/ifunc.exp b/ld/testsuite/ld-ifunc/ifunc.exp
index df913d8..d4c4035 100644
--- a/ld/testsuite/ld-ifunc/ifunc.exp
+++ b/ld/testsuite/ld-ifunc/ifunc.exp
@@ -97,8 +97,9 @@ proc contains_ifunc_symbol { binary_file } {
 
     # Look for a line like this:
     #    58: 0000000000400600    30 IFUNC   GLOBAL DEFAULT   12 library_func2
+    # with perhaps some other info between the visibility and section
 
-    if { ![regexp ".*\[ \]*IFUNC\[ \]+GLOBAL\[ \]+DEFAULT\[ \]+\[UND0-9\]+\[ \]+library_func2\n" [file_contents readelf.out]] } {
+    if { ![regexp ".*\[ \]*IFUNC\[ \]+GLOBAL\[ \]+DEFAULT .* \[UND0-9\]+\[ \]+library_func2\n" [file_contents readelf.out]] } {
 	return 0
     }
 
diff --git a/ld/testsuite/ld-powerpc/elfv2.s b/ld/testsuite/ld-powerpc/elfv2.s
new file mode 100644
index 0000000..c2a4c3b
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/elfv2.s
@@ -0,0 +1,32 @@
+ .section .toc,"aw",@progbits
+.L0:
+ .quad x
+
+ .data
+x:
+ .quad f1
+
+ .globl f1
+ .type f1,@function
+ .text
+f1:
+ addis 2,12,.TOC.-f1@ha
+ addi 2,2,.TOC.-f1@l
+ .localentry f1,.-f1
+ mflr 0
+ stdu 1,-32(1)
+ std 0,48(1)
+ bl f1
+ ld 3,.L0@toc(2)
+ bl f2
+ nop
+ ld 3,x@got(2)
+ bl f3
+ nop
+ bl f4
+ nop
+ ld 0,48(1)
+ addi 1,1,32
+ mtlr 0
+ blr
+ .size f1,.-f1
diff --git a/ld/testsuite/ld-powerpc/elfv2exe.d b/ld/testsuite/ld-powerpc/elfv2exe.d
new file mode 100644
index 0000000..7ff9d38
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/elfv2exe.d
@@ -0,0 +1,40 @@
+#source: elfv2.s
+#as: -a64
+#ld: -melf64ppc --defsym f2=0x1234 --defsym f3=0x10008888 --defsym f4=0x1200000 --defsym _start=f1
+#objdump: -dr
+
+.*
+
+Disassembly of section \.text:
+
+0+100000c0 <.*\.plt_branch\.f2>:
+.*:	(ff ff 62 3d|3d 62 ff ff) 	addis   r11,r2,-1
+.*:	(f0 7f 8b e9|e9 8b 7f f0) 	ld      r12,32752\(r11\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+100000d0 <.*\.plt_branch\.f4>:
+.*:	(ff ff 62 3d|3d 62 ff ff) 	addis   r11,r2,-1
+.*:	(f8 7f 8b e9|e9 8b 7f f8) 	ld      r12,32760\(r11\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+100000e0 <_start>:
+.*:	(02 10 40 3c|3c 40 10 02) 	lis     r2,4098
+.*:	(40 81 42 38|38 42 81 40) 	addi    r2,r2,-32448
+.*:	(a6 02 08 7c|7c 08 02 a6) 	mflr    r0
+.*:	(e1 ff 21 f8|f8 21 ff e1) 	stdu    r1,-32\(r1\)
+.*:	(30 00 01 f8|f8 01 00 30) 	std     r0,48\(r1\)
+.*:	(f5 ff ff 4b|4b ff ff f5) 	bl      .* <_start\+0x8>
+.*:	(08 80 62 e8|e8 62 80 08) 	ld      r3,-32760\(r2\)
+.*:	(c5 ff ff 4b|4b ff ff c5) 	bl      .*\.plt_branch\.f2>
+.*:	(00 00 00 60|60 00 00 00) 	nop
+.*:	(10 80 62 e8|e8 62 80 10) 	ld      r3,-32752\(r2\)
+.*:	(81 87 00 48|48 00 87 81) 	bl      10008888 <f3>
+.*:	(00 00 00 60|60 00 00 00) 	nop
+.*:	(c1 ff ff 4b|4b ff ff c1) 	bl      .*\.plt_branch\.f4>
+.*:	(00 00 00 60|60 00 00 00) 	nop
+.*:	(30 00 01 e8|e8 01 00 30) 	ld      r0,48\(r1\)
+.*:	(20 00 21 38|38 21 00 20) 	addi    r1,r1,32
+.*:	(a6 03 08 7c|7c 08 03 a6) 	mtlr    r0
+.*:	(20 00 80 4e|4e 80 00 20) 	blr
diff --git a/ld/testsuite/ld-powerpc/elfv2so.d b/ld/testsuite/ld-powerpc/elfv2so.d
new file mode 100644
index 0000000..963dbb6
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/elfv2so.d
@@ -0,0 +1,82 @@
+#source: elfv2.s
+#as: -a64
+#ld: -melf64ppc -shared
+#objdump: -dr
+
+.*
+
+Disassembly of section \.text:
+
+0+300 <.*\.plt_call\.f4>:
+.*:	(18 00 41 f8|f8 41 00 18) 	std     r2,24\(r1\)
+.*:	(38 80 82 e9|e9 82 80 38) 	ld      r12,-32712\(r2\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+310 <.*\.plt_call\.f3>:
+.*:	(18 00 41 f8|f8 41 00 18) 	std     r2,24\(r1\)
+.*:	(28 80 82 e9|e9 82 80 28) 	ld      r12,-32728\(r2\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+320 <.*\.plt_call\.f2>:
+.*:	(18 00 41 f8|f8 41 00 18) 	std     r2,24\(r1\)
+.*:	(30 80 82 e9|e9 82 80 30) 	ld      r12,-32720\(r2\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+330 <.*\.plt_call\.f1>:
+.*:	(18 00 41 f8|f8 41 00 18) 	std     r2,24\(r1\)
+.*:	(40 80 82 e9|e9 82 80 40) 	ld      r12,-32704\(r2\)
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+
+0+340 <f1>:
+.*:	(02 00 4c 3c|3c 4c 00 02) 	addis   r2,r12,2
+.*:	(e0 81 42 38|38 42 81 e0) 	addi    r2,r2,-32288
+.*:	(a6 02 08 7c|7c 08 02 a6) 	mflr    r0
+.*:	(e1 ff 21 f8|f8 21 ff e1) 	stdu    r1,-32\(r1\)
+.*:	(30 00 01 f8|f8 01 00 30) 	std     r0,48\(r1\)
+.*:	(dd ff ff 4b|4b ff ff dd) 	bl      .*\.plt_call\.f1>
+.*:	(08 80 62 e8|e8 62 80 08) 	ld      r3,-32760\(r2\)
+.*:	(c5 ff ff 4b|4b ff ff c5) 	bl      .*\.plt_call\.f2>
+.*:	(18 00 41 e8|e8 41 00 18) 	ld      r2,24\(r1\)
+.*:	(10 80 62 e8|e8 62 80 10) 	ld      r3,-32752\(r2\)
+.*:	(a9 ff ff 4b|4b ff ff a9) 	bl      .*\.plt_call\.f3>
+.*:	(18 00 41 e8|e8 41 00 18) 	ld      r2,24\(r1\)
+.*:	(91 ff ff 4b|4b ff ff 91) 	bl      .*\.plt_call\.f4>
+.*:	(18 00 41 e8|e8 41 00 18) 	ld      r2,24\(r1\)
+.*:	(30 00 01 e8|e8 01 00 30) 	ld      r0,48\(r1\)
+.*:	(20 00 21 38|38 21 00 20) 	addi    r1,r1,32
+.*:	(a6 03 08 7c|7c 08 03 a6) 	mtlr    r0
+.*:	(20 00 80 4e|4e 80 00 20) 	blr
+.*:	(a0 01 01 00|00 00 00 00) 	.*
+.*:	(00 00 00 00|00 01 01 a0) 	.*
+
+0+390 <__glink_PLTresolve>:
+.*:	(a6 02 08 7c|7c 08 02 a6) 	mflr    r0
+.*:	(05 00 9f 42|42 9f 00 05) 	bcl     .*
+.*:	(a6 02 68 7d|7d 68 02 a6) 	mflr    r11
+.*:	(f0 ff 4b e8|e8 4b ff f0) 	ld      r2,-16\(r11\)
+.*:	(a6 03 08 7c|7c 08 03 a6) 	mtlr    r0
+.*:	(50 60 8b 7d|7d 8b 60 50) 	subf    r12,r11,r12
+.*:	(14 5a 62 7d|7d 62 5a 14) 	add     r11,r2,r11
+.*:	(d0 ff 0c 38|38 0c ff d0) 	addi    r0,r12,-48
+.*:	(00 00 8b e9|e9 8b 00 00) 	ld      r12,0\(r11\)
+.*:	(82 f0 00 78|78 00 f0 82) 	rldicl  r0,r0,62,2
+.*:	(a6 03 89 7d|7d 89 03 a6) 	mtctr   r12
+.*:	(08 00 6b e9|e9 6b 00 08) 	ld      r11,8\(r11\)
+.*:	(20 04 80 4e|4e 80 04 20) 	bctr
+.*:	(00 00 00 60|60 00 00 00) 	nop
+
+.* <f3@plt>:
+.*:	(c8 ff ff 4b|4b ff ff c8) 	b       .* <__glink_PLTresolve>
+
+.* <f2@plt>:
+.*:	(c4 ff ff 4b|4b ff ff c4) 	b       .* <__glink_PLTresolve>
+
+.* <f4@plt>:
+.*:	(c0 ff ff 4b|4b ff ff c0) 	b       .* <__glink_PLTresolve>
+
+.* <f1@plt>:
+.*:	(bc ff ff 4b|4b ff ff bc) 	b       .* <__glink_PLTresolve>
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index f022b95..837ad64 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -269,6 +269,8 @@ run_ld_link_tests $ppcelftests
 if [ supports_ppc64 ] then {
     run_ld_link_tests $ppc64elftests
     run_dump_test "relbrlt"
+    run_dump_test "elfv2so"
+    run_dump_test "elfv2exe"
 }
 
 if { [istarget "powerpc*-eabi*"] } {
diff --git a/ld/testsuite/ld-powerpc/tls.d b/ld/testsuite/ld-powerpc/tls.d
index 3c32980..eb4be24 100644
--- a/ld/testsuite/ld-powerpc/tls.d
+++ b/ld/testsuite/ld-powerpc/tls.d
@@ -9,7 +9,7 @@
 
 Disassembly of section \.text:
 
-0+100000e8 <_start>:
+0+100000e8 <\._start>:
 .*:	(3c 6d 00 00|00 00 6d 3c) 	addis   r3,r13,0
 .*:	(60 00 00 00|00 00 00 60) 	nop
 .*:	(38 63 90 78|78 90 63 38) 	addi    r3,r3,-28552
diff --git a/ld/testsuite/ld-powerpc/tls.g b/ld/testsuite/ld-powerpc/tls.g
index 83f8e06..2de9e3b 100644
--- a/ld/testsuite/ld-powerpc/tls.g
+++ b/ld/testsuite/ld-powerpc/tls.g
@@ -8,5 +8,5 @@
 .*
 
 Contents of section \.got:
- 100101e0 (00000000|e0810110) (100181e0|00000000) (ffffffff|1880ffff) (ffff8018|ffffffff)  .*
- 100101f0 (ffffffff|5880ffff) (ffff8058|ffffffff)                    .*
+ 100101f8 (00000000|f8810110) (100181f8|00000000) (ffffffff|1880ffff) (ffff8018|ffffffff)  .*
+ 10010208 (ffffffff|5880ffff) (ffff8058|ffffffff)                    .*
diff --git a/ld/testsuite/ld-powerpc/tls.s b/ld/testsuite/ld-powerpc/tls.s
index 5ad9f3d..49828d0 100644
--- a/ld/testsuite/ld-powerpc/tls.s
+++ b/ld/testsuite/ld-powerpc/tls.s
@@ -19,8 +19,13 @@ ie4:	.quad 0x56789abcdef01234
 le4:	.quad 0x6789abcdef012345
 le5:	.quad 0x789abcdef0123456
 
-	.text
+	.section ".opd","aw",@progbits
+	.p2align 3
 _start:
+	.quad	.L_start,.TOC.@tocbase,0
+
+	.text
+.L_start:
 #extern syms
 #GD
  addi 3,2,gd@got@tlsgd		#R_PPC64_GOT_TLSGD16	gd
diff --git a/ld/testsuite/ld-powerpc/tlsexe.d b/ld/testsuite/ld-powerpc/tlsexe.d
index 8390551..0d5ee40 100644
--- a/ld/testsuite/ld-powerpc/tlsexe.d
+++ b/ld/testsuite/ld-powerpc/tlsexe.d
@@ -19,8 +19,8 @@ Disassembly of section \.text:
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(f9 61 00 20|20 00 61 f9) 	std     r11,32\(r1\)
 .*	(f8 41 00 28|28 00 41 f8) 	std     r2,40\(r1\)
-.*	(e9 62 80 48|48 80 62 e9) 	ld      r11,-32696\(r2\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
+.*	(e9 82 80 48|48 80 82 e9) 	ld      r12,-32696\(r2\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
 .*	(e8 42 80 50|50 80 42 e8) 	ld      r2,-32688\(r2\)
 .*	(4e 80 04 21|21 04 80 4e) 	bctrl
 .*	(e9 61 00 20|20 00 61 e9) 	ld      r11,32\(r1\)
@@ -28,7 +28,7 @@ Disassembly of section \.text:
 .*	(7d 68 03 a6|a6 03 68 7d) 	mtlr    r11
 .*	(4e 80 00 20|20 00 80 4e) 	blr
 
-.* <_start>:
+.* <._start>:
 .*	(e8 62 80 10|10 80 62 e8) 	ld      r3,-32752\(r2\)
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(7c 63 6a 14|14 6a 63 7c) 	add     r3,r3,r13
@@ -67,22 +67,23 @@ Disassembly of section \.text:
 .*	(e9 4d 90 2a|2a 90 4d e9) 	lwa     r10,-28632\(r13\)
 .*	(3d 2d 00 00|00 00 2d 3d) 	addis   r9,r13,0
 .*	(a9 49 90 30|30 90 49 a9) 	lha     r10,-28624\(r9\)
-.*	(00 00 00 00|00 02 01 00) .*
-.*	(00 01 02 00|00 00 00 00) .*
+.*	(00 00 00 00|18 02 01 00) .*
+.*	(00 01 02 18|00 00 00 00) .*
 .* <__glink_PLTresolve>:
 .*	(7d 88 02 a6|a6 02 88 7d) 	mflr    r12
 .*	(42 9f 00 05|05 00 9f 42) 	bcl     20,4\*cr7\+so,.*
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(e8 4b ff f0|f0 ff 4b e8) 	ld      r2,-16\(r11\)
 .*	(7d 88 03 a6|a6 03 88 7d) 	mtlr    r12
-.*	(7d 82 5a 14|14 5a 82 7d) 	add     r12,r2,r11
-.*	(e9 6c 00 00|00 00 6c e9) 	ld      r11,0\(r12\)
-.*	(e8 4c 00 08|08 00 4c e8) 	ld      r2,8\(r12\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
-.*	(e9 6c 00 10|10 00 6c e9) 	ld      r11,16\(r12\)
+.*	(7d 62 5a 14|14 5a 62 7d) 	add     r11,r2,r11
+.*	(e9 8b 00 00|00 00 8b e9) 	ld      r12,0\(r11\)
+.*	(e8 4b 00 08|08 00 4b e8) 	ld      r2,8\(r11\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+.*	(e9 6b 00 10|10 00 6b e9) 	ld      r11,16\(r11\)
 .*	(4e 80 04 20|20 04 80 4e) 	bctr
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
+.* <__tls_get_addr_opt@plt>:
 .*	(38 00 00 00|00 00 00 38) 	li      r0,0
 .*	(4b ff ff c4|c4 ff ff 4b) 	b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsexe.g b/ld/testsuite/ld-powerpc/tlsexe.g
index 3420d20..fb8dbb3 100644
--- a/ld/testsuite/ld-powerpc/tlsexe.g
+++ b/ld/testsuite/ld-powerpc/tlsexe.g
@@ -7,6 +7,6 @@
 .*
 
 Contents of section \.got:
-.* (00000000|20860110) (10018620|00000000) (ffffffff|1880ffff) (ffff8018|ffffffff)  .*
+.* (00000000|38860110) (10018638|00000000) (ffffffff|1880ffff) (ffff8018|ffffffff)  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
diff --git a/ld/testsuite/ld-powerpc/tlsexe.r b/ld/testsuite/ld-powerpc/tlsexe.r
index 8d6ff30..72ef3f4 100644
--- a/ld/testsuite/ld-powerpc/tlsexe.r
+++ b/ld/testsuite/ld-powerpc/tlsexe.r
@@ -20,6 +20,7 @@ Section Headers:
  +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.opd .*
  +\[[ 0-9]+\] \.got +PROGBITS .* 0+30 08 +WA +0 +0 +8
  +\[[ 0-9]+\] \.plt +.*
  +\[[ 0-9]+\] \.shstrtab +.*
@@ -46,7 +47,7 @@ Program Headers:
  +0+ +
  +01 +\.interp 
  +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text 
- +03 +\.tdata \.dynamic \.got \.plt 
+ +03 +\.tdata \.dynamic \.opd \.got \.plt 
  +04 +\.dynamic 
  +05 +\.tdata \.tbss 
 
@@ -66,10 +67,10 @@ Symbol table '\.dynsym' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +UND gd
 .* TLS +GLOBAL +DEFAULT +UND ld
 .* TLS +GLOBAL +DEFAULT +9 ld2
-.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
 .* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
-.* NOTYPE +GLOBAL +DEFAULT +12 _edata
-.* NOTYPE +GLOBAL +DEFAULT +12 _end
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
 
 Symbol table '\.symtab' contains [0-9]+ entries:
  +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
@@ -86,6 +87,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* SECTION +LOCAL +DEFAULT +10 
 .* SECTION +LOCAL +DEFAULT +11 
 .* SECTION +LOCAL +DEFAULT +12 
+.* SECTION +LOCAL +DEFAULT +13 
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* TLS +LOCAL +DEFAULT +8 gd4
 .* TLS +LOCAL +DEFAULT +8 ld4
@@ -104,12 +106,12 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* GLOBAL +DEFAULT +9 ld0
 .* GLOBAL +DEFAULT +9 le1
 .* GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +7 _start
+.* FUNC +GLOBAL +DEFAULT +11 _start
 .* TLS +GLOBAL +DEFAULT +9 ld2
 .* TLS +GLOBAL +DEFAULT +9 ld1
-.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
 .* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
-.* NOTYPE +GLOBAL +DEFAULT +12 _edata
-.* NOTYPE +GLOBAL +DEFAULT +12 _end
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
 .* TLS +GLOBAL +DEFAULT +9 gd0
 .* TLS +GLOBAL +DEFAULT +9 ie0
diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.d b/ld/testsuite/ld-powerpc/tlsexetoc.d
index fc20992..ee0f3b2 100644
--- a/ld/testsuite/ld-powerpc/tlsexetoc.d
+++ b/ld/testsuite/ld-powerpc/tlsexetoc.d
@@ -19,8 +19,8 @@ Disassembly of section \.text:
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(f9 61 00 20|20 00 61 f9) 	std     r11,32\(r1\)
 .*	(f8 41 00 28|28 00 41 f8) 	std     r2,40\(r1\)
-.*	(e9 62 80 70|70 80 62 e9) 	ld      r11,-32656\(r2\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
+.*	(e9 82 80 70|70 80 82 e9) 	ld      r12,-32656\(r2\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
 .*	(e8 42 80 78|78 80 42 e8) 	ld      r2,-32648\(r2\)
 .*	(4e 80 04 21|21 04 80 4e) 	bctrl
 .*	(e9 61 00 20|20 00 61 e9) 	ld      r11,32\(r1\)
@@ -28,7 +28,7 @@ Disassembly of section \.text:
 .*	(7d 68 03 a6|a6 03 68 7d) 	mtlr    r11
 .*	(4e 80 00 20|20 00 80 4e) 	blr
 
-.* <_start>:
+.* <\._start>:
 .*	(38 62 80 08|08 80 62 38) 	addi    r3,r2,-32760
 .*	(4b ff ff b5|b5 ff ff 4b) 	bl      .*
 .*	(60 00 00 00|00 00 00 60) 	nop
@@ -51,22 +51,23 @@ Disassembly of section \.text:
 .*	(89 4d 90 60|60 90 4d 89) 	lbz     r10,-28576\(r13\)
 .*	(3d 2d 00 00|00 00 2d 3d) 	addis   r9,r13,0
 .*	(99 49 90 68|68 90 49 99) 	stb     r10,-28568\(r9\)
-.*	(00 00 00 00|28 02 01 00) .*
-.*	(00 01 02 28|00 00 00 00) .*
+.*	(00 00 00 00|40 02 01 00) .*
+.*	(00 01 02 40|00 00 00 00) .*
 .* <__glink_PLTresolve>:
 .*	(7d 88 02 a6|a6 02 88 7d) 	mflr    r12
 .*	(42 9f 00 05|05 00 9f 42) 	bcl     20,4\*cr7\+so,.*
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(e8 4b ff f0|f0 ff 4b e8) 	ld      r2,-16\(r11\)
 .*	(7d 88 03 a6|a6 03 88 7d) 	mtlr    r12
-.*	(7d 82 5a 14|14 5a 82 7d) 	add     r12,r2,r11
-.*	(e9 6c 00 00|00 00 6c e9) 	ld      r11,0\(r12\)
-.*	(e8 4c 00 08|08 00 4c e8) 	ld      r2,8\(r12\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
-.*	(e9 6c 00 10|10 00 6c e9) 	ld      r11,16\(r12\)
+.*	(7d 62 5a 14|14 5a 62 7d) 	add     r11,r2,r11
+.*	(e9 8b 00 00|00 00 8b e9) 	ld      r12,0\(r11\)
+.*	(e8 4b 00 08|08 00 4b e8) 	ld      r2,8\(r11\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+.*	(e9 6b 00 10|10 00 6b e9) 	ld      r11,16\(r11\)
 .*	(4e 80 04 20|20 04 80 4e) 	bctr
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
+.* <__tls_get_addr_opt@plt>:
 .*	(38 00 00 00|00 00 00 38) 	li      r0,0
 .*	(4b ff ff c4|c4 ff ff 4b) 	b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.g b/ld/testsuite/ld-powerpc/tlsexetoc.g
index e219f0e..dc563ad 100644
--- a/ld/testsuite/ld-powerpc/tlsexetoc.g
+++ b/ld/testsuite/ld-powerpc/tlsexetoc.g
@@ -7,7 +7,7 @@
 .*: +file format elf64-powerpc
 
 Contents of section \.got:
-.* (00000000|c0850110) (100185c0|00000000) 00000000 00000000  .*
+.* (00000000|d8850110) (100185d8|00000000) 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 (00000000|01000000) (00000001|00000000)  .*
 .* 00000000 00000000 (00000000|01000000) (00000001|00000000)  .*
diff --git a/ld/testsuite/ld-powerpc/tlsexetoc.r b/ld/testsuite/ld-powerpc/tlsexetoc.r
index 71d6c9e..e6f606b 100644
--- a/ld/testsuite/ld-powerpc/tlsexetoc.r
+++ b/ld/testsuite/ld-powerpc/tlsexetoc.r
@@ -20,6 +20,7 @@ Section Headers:
  +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.dynamic +DYNAMIC .* 0+160 10 +WA +4 +0 +8
+ +\[[ 0-9]+\] \.opd .*
  +\[[ 0-9]+\] \.got +PROGBITS .* 0+58 08 +WA +0 +0 +8
  +\[[ 0-9]+\] \.plt +.*
  +\[[ 0-9]+\] \.shstrtab +.*
@@ -46,7 +47,7 @@ Program Headers:
  +0+ +
  +01 +\.interp 
  +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text 
- +03 +\.tdata \.dynamic \.got \.plt 
+ +03 +\.tdata \.dynamic \.opd \.got \.plt 
  +04 +\.dynamic 
  +05 +\.tdata \.tbss 
 
@@ -65,10 +66,10 @@ Symbol table '\.dynsym' contains [0-9]+ entries:
 .* NOTYPE +LOCAL +DEFAULT +UND 
 .* TLS +GLOBAL +DEFAULT +UND gd
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
 .* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
-.* NOTYPE +GLOBAL +DEFAULT +12 _edata
-.* NOTYPE +GLOBAL +DEFAULT +12 _end
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
 
 Symbol table '\.symtab' contains [0-9]+ entries:
  +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
@@ -85,6 +86,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* SECTION +LOCAL +DEFAULT +10 
 .* SECTION +LOCAL +DEFAULT +11 
 .* SECTION +LOCAL +DEFAULT +12 
+.* SECTION +LOCAL +DEFAULT +13 
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* TLS +LOCAL +DEFAULT +8 gd4
 .* TLS +LOCAL +DEFAULT +8 ld4
@@ -93,7 +95,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +LOCAL +DEFAULT +8 ie4
 .* TLS +LOCAL +DEFAULT +8 le4
 .* TLS +LOCAL +DEFAULT +8 le5
-.* NOTYPE +LOCAL +DEFAULT +11 \.Lie0
+.* NOTYPE +LOCAL +DEFAULT +12 \.Lie0
 .* (FUNC|NOTYPE) +LOCAL +DEFAULT +UND \.__tls_get_addr(|_opt)
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* NOTYPE +LOCAL +DEFAULT +7 00000010\.plt_call\.__tls_get_addr(|_opt)
@@ -104,12 +106,12 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +9 ld0
 .* TLS +GLOBAL +DEFAULT +9 le1
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +7 _start
+.* FUNC +GLOBAL +DEFAULT +11 _start
 .* TLS +GLOBAL +DEFAULT +9 ld2
 .* TLS +GLOBAL +DEFAULT +9 ld1
-.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +13 __bss_start
 .* FUNC +GLOBAL +DEFAULT +UND __tls_get_addr_opt
-.* NOTYPE +GLOBAL +DEFAULT +12 _edata
-.* NOTYPE +GLOBAL +DEFAULT +12 _end
+.* NOTYPE +GLOBAL +DEFAULT +13 _edata
+.* NOTYPE +GLOBAL +DEFAULT +13 _end
 .* TLS +GLOBAL +DEFAULT +9 gd0
 .* TLS +GLOBAL +DEFAULT +9 ie0
diff --git a/ld/testsuite/ld-powerpc/tlsso.d b/ld/testsuite/ld-powerpc/tlsso.d
index 00b00a0..e64184d 100644
--- a/ld/testsuite/ld-powerpc/tlsso.d
+++ b/ld/testsuite/ld-powerpc/tlsso.d
@@ -10,14 +10,14 @@ Disassembly of section \.text:
 
 .* <00000010\.plt_call\.__tls_get_addr(|_opt)>:
 .*	(f8 41 00 28|28 00 41 f8) 	std     r2,40\(r1\)
-.*	(e9 62 80 78|78 80 62 e9) 	ld      r11,-32648\(r2\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
+.*	(e9 82 80 78|78 80 82 e9) 	ld      r12,-32648\(r2\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
 .*	(e8 42 80 80|80 80 42 e8) 	ld      r2,-32640\(r2\)
 .*	(28 22 00 00|00 00 22 28) 	cmpldi  r2,0
 .*	(4c e2 04 20|20 04 e2 4c) 	bnectr\+ 
-.*	(48 00 00 ..|.. 00 00 48) 	b       .* <__glink_PLTresolve\+0x38>
+.*	(48 00 00 ..|.. 00 00 48) 	b       .* <__tls_get_addr@plt>
 
-.* <_start>:
+.* <\._start>:
 .*	(38 62 80 20|20 80 62 38) 	addi    r3,r2,-32736
 .*	(4b ff ff ..|.. ff ff 4b) 	bl      .*plt_call.__tls_get_addr.*
 .*	(e8 41 00 28|28 00 41 e8) 	ld      r2,40\(r1\)
@@ -57,22 +57,23 @@ Disassembly of section \.text:
 .*	(3d 2d 00 00|00 00 2d 3d) 	addis   r9,r13,0
 .*	(a9 49 00 00|00 00 49 a9) 	lha     r10,0\(r9\)
 .*	(60 00 00 00|00 00 00 60) 	nop
-.*	(00 00 00 00|20 02 01 00) .*
-.*	(00 01 02 20|00 00 00 00) .*
+.*	(00 00 00 00|38 02 01 00) .*
+.*	(00 01 02 38|00 00 00 00) .*
 .* <__glink_PLTresolve>:
 .*	(7d 88 02 a6|a6 02 88 7d) 	mflr    r12
 .*	(42 9f 00 05|05 00 9f 42) 	bcl     20,4\*cr7\+so,.*
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(e8 4b ff f0|f0 ff 4b e8) 	ld      r2,-16\(r11\)
 .*	(7d 88 03 a6|a6 03 88 7d) 	mtlr    r12
-.*	(7d 82 5a 14|14 5a 82 7d) 	add     r12,r2,r11
-.*	(e9 6c 00 00|00 00 6c e9) 	ld      r11,0\(r12\)
-.*	(e8 4c 00 08|08 00 4c e8) 	ld      r2,8\(r12\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
-.*	(e9 6c 00 10|10 00 6c e9) 	ld      r11,16\(r12\)
+.*	(7d 62 5a 14|14 5a 62 7d) 	add     r11,r2,r11
+.*	(e9 8b 00 00|00 00 8b e9) 	ld      r12,0\(r11\)
+.*	(e8 4b 00 08|08 00 4b e8) 	ld      r2,8\(r11\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+.*	(e9 6b 00 10|10 00 6b e9) 	ld      r11,16\(r11\)
 .*	(4e 80 04 20|20 04 80 4e) 	bctr
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
+.* <__tls_get_addr@plt>:
 .*	(38 00 00 00|00 00 00 38) 	li      r0,0
 .*	(4b ff ff c4|c4 ff ff 4b) 	b       .*
diff --git a/ld/testsuite/ld-powerpc/tlsso.g b/ld/testsuite/ld-powerpc/tlsso.g
index 8536803..8fd3ce0 100644
--- a/ld/testsuite/ld-powerpc/tlsso.g
+++ b/ld/testsuite/ld-powerpc/tlsso.g
@@ -7,7 +7,7 @@
 .*: +file format elf64-powerpc
 
 Contents of section \.got:
- 10788 (00000000|88870100) (00018788|00000000) 00000000 00000000  .*
+ 107e0 (00000000|e0870100) (000187e0|00000000) 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
 .* 00000000 00000000 00000000 00000000  .*
diff --git a/ld/testsuite/ld-powerpc/tlsso.r b/ld/testsuite/ld-powerpc/tlsso.r
index fab50e0..6464be0 100644
--- a/ld/testsuite/ld-powerpc/tlsso.r
+++ b/ld/testsuite/ld-powerpc/tlsso.r
@@ -18,6 +18,7 @@ Section Headers:
  +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.dynamic .*
+ +\[[ 0-9]+\] \.opd .*
  +\[[ 0-9]+\] \.got .*
  +\[[ 0-9]+\] \.plt .*
  +\[[ 0-9]+\] \.shstrtab .*
@@ -39,12 +40,14 @@ Program Headers:
  Section to Segment mapping:
  +Segment Sections\.\.\.
  +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text 
- +01 +\.tdata \.dynamic .got \.plt 
+ +01 +\.tdata \.dynamic \.opd \.got \.plt 
  +02 +\.dynamic 
  +03 +\.tdata \.tbss 
 
-Relocation section '\.rela\.dyn' at offset .* contains 16 entries:
+Relocation section '\.rela\.dyn' at offset .* contains 18 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_RELATIVE +55c
+[0-9a-f ]+R_PPC64_RELATIVE +187e0
 [0-9a-f ]+R_PPC64_TPREL16 +0+60 le0 \+ 0
 [0-9a-f ]+R_PPC64_TPREL16_HA +0+68 le1 \+ 0
 [0-9a-f ]+R_PPC64_TPREL16_LO +0+68 le1 \+ 0
@@ -77,12 +80,12 @@ Symbol table '\.dynsym' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +8 ld0
 .* TLS +GLOBAL +DEFAULT +8 le1
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +6 _start
+.* FUNC +GLOBAL +DEFAULT +10 _start
 .* TLS +GLOBAL +DEFAULT +8 ld2
 .* TLS +GLOBAL +DEFAULT +8 ld1
-.* NOTYPE +GLOBAL +DEFAULT +11 __bss_start
-.* NOTYPE +GLOBAL +DEFAULT +11 _edata
-.* NOTYPE +GLOBAL +DEFAULT +11 _end
+.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +12 _edata
+.* NOTYPE +GLOBAL +DEFAULT +12 _end
 .* TLS +GLOBAL +DEFAULT +8 gd0
 .* TLS +GLOBAL +DEFAULT +8 ie0
 
@@ -100,6 +103,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* SECTION +LOCAL +DEFAULT +9 
 .* SECTION +LOCAL +DEFAULT +10 
 .* SECTION +LOCAL +DEFAULT +11 
+.* SECTION +LOCAL +DEFAULT +12 
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* TLS +LOCAL +DEFAULT +7 gd4
 .* TLS +LOCAL +DEFAULT +7 ld4
@@ -119,11 +123,11 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +8 ld0
 .* TLS +GLOBAL +DEFAULT +8 le1
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +6 _start
+.* FUNC +GLOBAL +DEFAULT +10 _start
 .* TLS +GLOBAL +DEFAULT +8 ld2
 .* TLS +GLOBAL +DEFAULT +8 ld1
-.* NOTYPE +GLOBAL +DEFAULT +11 __bss_start
-.* NOTYPE +GLOBAL +DEFAULT +11 _edata
-.* NOTYPE +GLOBAL +DEFAULT +11 _end
+.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +12 _edata
+.* NOTYPE +GLOBAL +DEFAULT +12 _end
 .* TLS +GLOBAL +DEFAULT +8 gd0
 .* TLS +GLOBAL +DEFAULT +8 ie0
diff --git a/ld/testsuite/ld-powerpc/tlstoc.d b/ld/testsuite/ld-powerpc/tlstoc.d
index faea1c4..05f61af 100644
--- a/ld/testsuite/ld-powerpc/tlstoc.d
+++ b/ld/testsuite/ld-powerpc/tlstoc.d
@@ -12,7 +12,7 @@ Disassembly of section \.text:
 .* <\.__tls_get_addr>:
 .*	(4e 80 00 20|20 00 80 4e) 	blr
 
-.* <_start>:
+.* <\._start>:
 .*	(3c 6d 00 00|00 00 6d 3c) 	addis   r3,r13,0
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(38 63 90 40|40 90 63 38) 	addi    r3,r3,-28608
diff --git a/ld/testsuite/ld-powerpc/tlstoc.g b/ld/testsuite/ld-powerpc/tlstoc.g
index 9ca4302..e3fe1d3 100644
--- a/ld/testsuite/ld-powerpc/tlstoc.g
+++ b/ld/testsuite/ld-powerpc/tlstoc.g
@@ -8,8 +8,8 @@
 .*
 
 Contents of section \.got:
- 100101a0 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
- 100101b0 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
- 100101c0 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
- 100101d0 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
- 100101e0 (ffffffff|6080ffff) (ffff8060|ffffffff) 00000000 00000000  .*
+ 100101b8 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
+ 100101c8 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
+ 100101d8 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
+ 100101e8 (00000000|01000000) (00000001|00000000) 00000000 00000000  .*
+ 100101f8 (ffffffff|6080ffff) (ffff8060|ffffffff) 00000000 00000000  .*
diff --git a/ld/testsuite/ld-powerpc/tlstoc.s b/ld/testsuite/ld-powerpc/tlstoc.s
index 5008d89..f5dbfdd 100644
--- a/ld/testsuite/ld-powerpc/tlstoc.s
+++ b/ld/testsuite/ld-powerpc/tlstoc.s
@@ -19,8 +19,13 @@ ie4:	.quad 0x56789abcdef01234
 le4:	.quad 0x6789abcdef012345
 le5:	.quad 0x789abcdef0123456
 
-	.text
+	.section ".opd","aw",@progbits
+	.p2align 3
 _start:
+	.quad	.L_start,.TOC.@tocbase,0
+
+	.text
+.L_start:
 #extern syms
 #GD
  addi 3,2,.Lgd@toc
diff --git a/ld/testsuite/ld-powerpc/tlstocso.d b/ld/testsuite/ld-powerpc/tlstocso.d
index a0cd08f..fa3b77a 100644
--- a/ld/testsuite/ld-powerpc/tlstocso.d
+++ b/ld/testsuite/ld-powerpc/tlstocso.d
@@ -10,14 +10,14 @@ Disassembly of section \.text:
 
 .* <00000010\.plt_call\.__tls_get_addr(|_opt)>:
 .*	(f8 41 00 28|28 00 41 f8) 	std     r2,40\(r1\)
-.*	(e9 62 80 70|70 80 62 e9) 	ld      r11,-32656\(r2\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
+.*	(e9 82 80 70|70 80 82 e9) 	ld      r12,-32656\(r2\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
 .*	(e8 42 80 78|78 80 42 e8) 	ld      r2,-32648\(r2\)
 .*	(28 22 00 00|00 00 22 28) 	cmpldi  r2,0
 .*	(4c e2 04 20|20 04 e2 4c) 	bnectr\+ 
-.*	(48 00 00 ..|.. 00 00 48) 	b       .* <__glink_PLTresolve\+0x38>
+.*	(48 00 00 ..|.. 00 00 48) 	b       .* <__tls_get_addr@plt>
 
-.* <_start>:
+.* <\._start>:
 .*	(38 62 80 08|08 80 62 38) 	addi    r3,r2,-32760
 .*	(4b ff ff ..|.. ff ff 4b) 	bl      .*plt_call.__tls_get_addr.*
 .*	(e8 41 00 28|28 00 41 e8) 	ld      r2,40\(r1\)
@@ -41,22 +41,23 @@ Disassembly of section \.text:
 .*	(3d 2d 00 00|00 00 2d 3d) 	addis   r9,r13,0
 .*	(99 49 00 00|00 00 49 99) 	stb     r10,0\(r9\)
 .*	(60 00 00 00|00 00 00 60) 	nop
-.*	(00 00 00 00|18 02 01 00) .*
-.*	(00 01 02 18|00 00 00 00) .*
+.*	(00 00 00 00|30 02 01 00) .*
+.*	(00 01 02 30|00 00 00 00) .*
 .* <__glink_PLTresolve>:
 .*	(7d 88 02 a6|a6 02 88 7d) 	mflr    r12
 .*	(42 9f 00 05|05 00 9f 42) 	bcl     20,4\*cr7\+so,.*
 .*	(7d 68 02 a6|a6 02 68 7d) 	mflr    r11
 .*	(e8 4b ff f0|f0 ff 4b e8) 	ld      r2,-16\(r11\)
 .*	(7d 88 03 a6|a6 03 88 7d) 	mtlr    r12
-.*	(7d 82 5a 14|14 5a 82 7d) 	add     r12,r2,r11
-.*	(e9 6c 00 00|00 00 6c e9) 	ld      r11,0\(r12\)
-.*	(e8 4c 00 08|08 00 4c e8) 	ld      r2,8\(r12\)
-.*	(7d 69 03 a6|a6 03 69 7d) 	mtctr   r11
-.*	(e9 6c 00 10|10 00 6c e9) 	ld      r11,16\(r12\)
+.*	(7d 62 5a 14|14 5a 62 7d) 	add     r11,r2,r11
+.*	(e9 8b 00 00|00 00 8b e9) 	ld      r12,0\(r11\)
+.*	(e8 4b 00 08|08 00 4b e8) 	ld      r2,8\(r11\)
+.*	(7d 89 03 a6|a6 03 89 7d) 	mtctr   r12
+.*	(e9 6b 00 10|10 00 6b e9) 	ld      r11,16\(r11\)
 .*	(4e 80 04 20|20 04 80 4e) 	bctr
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
 .*	(60 00 00 00|00 00 00 60) 	nop
+.* <__tls_get_addr@plt>:
 .*	(38 00 00 00|00 00 00 38) 	li      r0,0
 .*	(4b ff ff c4|c4 ff ff 4b) 	b       .*
diff --git a/ld/testsuite/ld-powerpc/tlstocso.r b/ld/testsuite/ld-powerpc/tlstocso.r
index 1ec8b63..f397915 100644
--- a/ld/testsuite/ld-powerpc/tlstocso.r
+++ b/ld/testsuite/ld-powerpc/tlstocso.r
@@ -18,6 +18,7 @@ Section Headers:
  +\[[ 0-9]+\] \.tdata +PROGBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.tbss +NOBITS .* 0+38 0+ WAT +0 +0 +8
  +\[[ 0-9]+\] \.dynamic .*
+ +\[[ 0-9]+\] \.opd .*
  +\[[ 0-9]+\] \.got .*
  +\[[ 0-9]+\] \.plt .*
  +\[[ 0-9]+\] \.shstrtab .*
@@ -39,12 +40,14 @@ Program Headers:
  Section to Segment mapping:
  +Segment Sections\.\.\.
  +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text 
- +01 +\.tdata \.dynamic \.got \.plt 
+ +01 +\.tdata \.dynamic \.opd \.got \.plt 
  +02 +\.dynamic 
  +03 +\.tdata \.tbss 
 
-Relocation section '\.rela\.dyn' at offset .* contains 11 entries:
+Relocation section '\.rela\.dyn' at offset .* contains 13 entries:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+[0-9a-f ]+R_PPC64_RELATIVE +4dc
+[0-9a-f ]+R_PPC64_RELATIVE +18720
 [0-9a-f ]+R_PPC64_TPREL16 +0+60 le0 \+ 0
 [0-9a-f ]+R_PPC64_TPREL16_HA +0+68 le1 \+ 0
 [0-9a-f ]+R_PPC64_TPREL16_LO +0+68 le1 \+ 0
@@ -72,12 +75,12 @@ Symbol table '\.dynsym' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +8 ld0
 .* TLS +GLOBAL +DEFAULT +8 le1
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +6 _start
+.* FUNC +GLOBAL +DEFAULT +10 _start
 .* TLS +GLOBAL +DEFAULT +8 ld2
 .* TLS +GLOBAL +DEFAULT +8 ld1
-.* NOTYPE +GLOBAL +DEFAULT +11 __bss_start
-.* NOTYPE +GLOBAL +DEFAULT +11 _edata
-.* NOTYPE +GLOBAL +DEFAULT +11 _end
+.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +12 _edata
+.* NOTYPE +GLOBAL +DEFAULT +12 _end
 .* TLS +GLOBAL +DEFAULT +8 gd0
 .* TLS +GLOBAL +DEFAULT +8 ie0
 
@@ -95,6 +98,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* SECTION +LOCAL +DEFAULT +9 
 .* SECTION +LOCAL +DEFAULT +10 
 .* SECTION +LOCAL +DEFAULT +11 
+.* SECTION +LOCAL +DEFAULT +12 
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* TLS +LOCAL +DEFAULT +7 gd4
 .* TLS +LOCAL +DEFAULT +7 ld4
@@ -103,7 +107,7 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +LOCAL +DEFAULT +7 ie4
 .* TLS +LOCAL +DEFAULT +7 le4
 .* TLS +LOCAL +DEFAULT +7 le5
-.* NOTYPE +LOCAL +DEFAULT +10 \.Lie0
+.* NOTYPE +LOCAL +DEFAULT +11 \.Lie0
 .* NOTYPE +LOCAL +DEFAULT +UND \.__tls_get_addr
 .* FILE +LOCAL +DEFAULT +ABS .*
 .* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
@@ -115,11 +119,11 @@ Symbol table '\.symtab' contains [0-9]+ entries:
 .* TLS +GLOBAL +DEFAULT +8 ld0
 .* TLS +GLOBAL +DEFAULT +8 le1
 .* TLS +GLOBAL +DEFAULT +UND ld
-.* NOTYPE +GLOBAL +DEFAULT +6 _start
+.* FUNC +GLOBAL +DEFAULT +10 _start
 .* TLS +GLOBAL +DEFAULT +8 ld2
 .* TLS +GLOBAL +DEFAULT +8 ld1
-.* NOTYPE +GLOBAL +DEFAULT +11 __bss_start
-.* NOTYPE +GLOBAL +DEFAULT +11 _edata
-.* NOTYPE +GLOBAL +DEFAULT +11 _end
+.* NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+.* NOTYPE +GLOBAL +DEFAULT +12 _edata
+.* NOTYPE +GLOBAL +DEFAULT +12 _end
 .* TLS +GLOBAL +DEFAULT +8 gd0
 .* TLS +GLOBAL +DEFAULT +8 ie0
diff --git a/ld/testsuite/ld-scripts/crossref.exp b/ld/testsuite/ld-scripts/crossref.exp
index 061b5aa..01fdeb4 100644
--- a/ld/testsuite/ld-scripts/crossref.exp
+++ b/ld/testsuite/ld-scripts/crossref.exp
@@ -31,9 +31,11 @@ if { ![is_remote host] && [which $CC] == 0 } {
     return
 }
 
+global CFLAGS
+set old_CFLAGS "$CFLAGS"
+
 # Xtensa targets currently default to putting literal values in a separate
 # section and that requires linker script support, so put literals in text.
-global CFLAGS
 if [istarget xtensa*-*-*] {
     set CFLAGS "$CFLAGS -mtext-section-literals"
 }
@@ -41,7 +43,7 @@ if [istarget xtensa*-*-*] {
 # If we have a compiler that doesn't use/reference dot-symbols, then
 # calls to functions reference the .opd section function descriptor.
 # This makes NOCROSSREFS rather useless on powerpc64.
-if [istarget powerpc64*-*-*] {
+if [istarget powerpc64-*-*] {
     set CFLAGS "$CFLAGS -mcall-aixdesc"
 }
 
@@ -61,6 +63,7 @@ if { ![ld_compile $CC "$srcdir/$subdir/cross1.c" tmpdir/cross1.o] \
      || ![ld_compile $CC "$srcdir/$subdir/cross2.c" tmpdir/cross2.o] } {
     unresolved $test1
     unresolved $test2
+    set CFLAGS "$old_CFLAGS"
     return
 }
 
@@ -95,6 +98,7 @@ if [string match "" $exec_output] then {
 
 if { ![ld_compile $CC "$srcdir/$subdir/cross3.c" tmpdir/cross3.o] } {
     unresolved $test2
+    set CFLAGS "$old_CFLAGS"
     return
 }
 
@@ -118,11 +122,13 @@ if [string match "" $exec_output] then {
 
 if { ![ld_compile $CC "$srcdir/$subdir/cross4.c" tmpdir/cross4.o] } {
     unresolved $test3
+    set CFLAGS "$old_CFLAGS"
     return
 }
 
 if ![ld_relocate $ld tmpdir/cross3-partial.o "tmpdir/cross1.o tmpdir/cross4.o"] {
     unresolved $test3
+    set CFLAGS "$old_CFLAGS"
     return
 }
 
@@ -138,3 +144,5 @@ if [string match "" $exec_output] then {
     verbose -log "$exec_output"
     fail $test3
 }
+
+set CFLAGS "$old_CFLAGS"