nameless LOAD_DLL_DEBUG_EVENT causes ntdll.dll to be missing
[binutils-gdb.git] / bfd / elf64-ppc.c
index a4f3064a4f7702210a929e632f2082e3e63a7bed..f30c009b5c3a512c250c36f7d6e321fee1a0f055 100644 (file)
@@ -1,6 +1,6 @@
 /* PowerPC64-specific support for 64-bit ELF.
    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-   2009, 2010 Free Software Foundation, Inc.
+   2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Written by Linus Nordberg, Swox AB <info@swox.com>,
    based on elf32-ppc.c by Ian Lance Taylor.
    Largely rewritten by Alan Modra.
@@ -34,6 +34,7 @@
 #include "elf-bfd.h"
 #include "elf/ppc64.h"
 #include "elf64-ppc.h"
+#include "dwarf2.h"
 
 static bfd_reloc_status_type ppc64_elf_ha_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
@@ -54,7 +55,7 @@ static bfd_reloc_status_type ppc64_elf_toc64_reloc
 static bfd_reloc_status_type ppc64_elf_unhandled_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_vma opd_entry_value
-  (asection *, bfd_vma, asection **, bfd_vma *);
+  (asection *, bfd_vma, asection **, bfd_vma *, bfd_boolean);
 
 #define TARGET_LITTLE_SYM      bfd_elf64_powerpcle_vec
 #define TARGET_LITTLE_NAME     "elf64-powerpcle"
@@ -79,12 +80,14 @@ 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_reloc_name_lookup              ppc64_elf_reloc_name_lookup
 #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
 #define bfd_elf64_get_synthetic_symtab       ppc64_elf_get_synthetic_symtab
+#define bfd_elf64_bfd_link_just_syms         ppc64_elf_link_just_syms
 
 #define elf_backend_object_p                 ppc64_elf_object_p
 #define elf_backend_grok_prstatus            ppc64_elf_grok_prstatus
@@ -94,7 +97,7 @@ static bfd_vma opd_entry_value
 #define elf_backend_copy_indirect_symbol      ppc64_elf_copy_indirect_symbol
 #define elf_backend_add_symbol_hook          ppc64_elf_add_symbol_hook
 #define elf_backend_check_directives         ppc64_elf_process_dot_syms
-#define elf_backend_as_needed_cleanup        ppc64_elf_as_needed_cleanup
+#define elf_backend_notice_as_needed         ppc64_elf_notice_as_needed
 #define elf_backend_archive_symbol_lookup     ppc64_elf_archive_symbol_lookup
 #define elf_backend_check_relocs             ppc64_elf_check_relocs
 #define elf_backend_gc_keep                  ppc64_elf_gc_keep
@@ -103,8 +106,10 @@ static bfd_vma opd_entry_value
 #define elf_backend_gc_sweep_hook            ppc64_elf_gc_sweep_hook
 #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
 #define elf_backend_hide_symbol                      ppc64_elf_hide_symbol
+#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
@@ -114,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
@@ -134,26 +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_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)
@@ -164,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
@@ -299,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 */
@@ -315,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 */
@@ -477,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 */
@@ -493,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 */
@@ -670,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 */
@@ -686,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 */
@@ -731,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 */
@@ -746,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 */
@@ -953,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 */
@@ -972,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 */
@@ -1044,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 */
@@ -1062,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 */
@@ -1280,6 +1308,20 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
         0,                     /* dst_mask */
         FALSE),                /* pcrel_offset */
 
+  HOWTO (R_PPC64_TOCSAVE,
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        "R_PPC64_TOCSAVE",     /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
   /* Computes the load module index of the load module that contains the
      definition of its TLS sym.  */
   HOWTO (R_PPC64_DTPMOD64,
@@ -1350,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 */
@@ -1365,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 */
@@ -1516,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 */
@@ -1531,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 */
@@ -1668,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 */
@@ -1683,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 */
@@ -1730,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 */
@@ -1745,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 */
@@ -1791,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 */
@@ -1806,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 */
@@ -1852,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 */
@@ -1867,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 */
@@ -1940,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 */
@@ -1956,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 */
@@ -1964,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 */
@@ -2042,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;
@@ -2162,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;
@@ -2172,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;
@@ -2323,7 +2467,7 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
     {
       bfd_vma dest = opd_entry_value (symbol->section,
                                      symbol->value + reloc_entry->addend,
-                                     NULL, NULL);
+                                     NULL, NULL, FALSE);
       if (dest != (bfd_vma) -1)
        reloc_entry->addend = dest - (symbol->value
                                      + symbol->section->output_section->vma
@@ -2340,8 +2484,8 @@ ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   long insn;
   enum elf_ppc64_reloc_type r_type;
   bfd_size_type octets;
-  /* Disabled until we sort out how ld should choose 'y' vs 'at'.  */
-  bfd_boolean is_power4 = FALSE;
+  /* Assume 'at' branch hints.  */
+  bfd_boolean is_isa_v2 = TRUE;
 
   /* If this is a relocatable link (output_bfd test tells us), just
      call the generic function.  Any adjustment will be done at final
@@ -2358,7 +2502,7 @@ ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
       || r_type == R_PPC64_REL14_BRTAKEN)
     insn |= 0x01 << 21; /* 'y' or 't' bit, lowest bit of BO field.  */
 
-  if (is_power4)
+  if (is_isa_v2)
     {
       /* Set 'a' bit.  This is 0b00010 in BO field for branch
         on CR(BI) insns (BO == 001at or 011at), and 0b01000
@@ -2448,7 +2592,7 @@ ppc64_elf_toc_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
   TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
   if (TOCstart == 0)
-    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
+    TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner);
 
   /* Subtract the TOC base address.  */
   reloc_entry->addend -= TOCstart + TOC_BASE_OFF;
@@ -2471,7 +2615,7 @@ ppc64_elf_toc_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
   TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
   if (TOCstart == 0)
-    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
+    TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner);
 
   /* Subtract the TOC base address.  */
   reloc_entry->addend -= TOCstart + TOC_BASE_OFF;
@@ -2498,7 +2642,7 @@ ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 
   TOCstart = _bfd_get_gp_value (input_section->output_section->owner);
   if (TOCstart == 0)
-    TOCstart = ppc64_elf_toc (input_section->output_section->owner);
+    TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner);
 
   octets = reloc_entry->address * bfd_octets_per_byte (abfd);
   bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets);
@@ -2591,12 +2735,21 @@ struct ppc64_elf_obj_tdata
      sections means we potentially need one of these for each input bfd.  */
   struct got_entry tlsld_got;
 
-  /* A copy of relocs before they are modified for --emit-relocs.  */
-  Elf_Internal_Rela *opd_relocs;
+  union {
+    /* A copy of relocs before they are modified for --emit-relocs.  */
+    Elf_Internal_Rela *relocs;
+
+    /* Section contents.  */
+    bfd_byte *contents;
+  } opd;
 
   /* Nonzero if this bfd has small toc/got relocs, ie. that expect
      the reloc to be in the range -32768 to 32767.  */
-  unsigned int has_small_toc_reloc;
+  unsigned int has_small_toc_reloc : 1;
+
+  /* Set if toc/got ha relocs detected not using r2, or lo reloc
+     instruction not one we handle.  */
+  unsigned int unexpected_toc_insn : 1;
 };
 
 #define ppc64_elf_tdata(bfd) \
@@ -2649,10 +2802,10 @@ ppc64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
     return FALSE;
 
   /* pr_cursig */
-  elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+  elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
 
   /* pr_pid */
-  elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 32);
+  elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32);
 
   /* pr_reg */
   offset = 112;
@@ -2669,9 +2822,11 @@ ppc64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
   if (note->descsz != 136)
     return FALSE;
 
-  elf_tdata (abfd)->core_program
+  elf_tdata (abfd)->core->pid
+    = bfd_get_32 (abfd, note->descdata + 24);
+  elf_tdata (abfd)->core->program
     = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
-  elf_tdata (abfd)->core_command
+  elf_tdata (abfd)->core->command
     = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
 
   return TRUE;
@@ -2692,7 +2847,7 @@ ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
        va_list ap;
 
        va_start (ap, note_type);
-       memset (data, 0, 40);
+       memset (data, 0, sizeof (data));
        strncpy (data + 40, va_arg (ap, const char *), 16);
        strncpy (data + 56, va_arg (ap, const char *), 80);
        va_end (ap);
@@ -2724,35 +2879,6 @@ ppc64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
     }
 }
 
-/* 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)
-{
-  /* Check if we have the same endianess.  */
-  if (ibfd->xvec->byteorder != obfd->xvec->byteorder
-      && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
-      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
-    {
-      const char *msg;
-
-      if (bfd_big_endian (ibfd))
-       msg = _("%B: compiled for a big endian system "
-               "and target is little endian");
-      else
-       msg = _("%B: compiled for a little endian system "
-               "and target is big endian");
-
-      (*_bfd_error_handler) (msg, ibfd);
-
-      bfd_set_error (bfd_error_wrong_format);
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
 /* Add extra PPC sections.  */
 
 static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
@@ -2835,6 +2961,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;
+}
 \f
 /* Parameters for the qsort hook.  */
 static bfd_boolean synthetic_relocatable;
@@ -2981,15 +3120,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)
@@ -3158,20 +3301,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;
        }
@@ -3220,9 +3361,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.  */
@@ -3240,13 +3381,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)
@@ -3258,7 +3407,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
              slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
              if (! (*slurp_relocs) (abfd, relplt, dyn_syms, TRUE))
                goto free_contents_and_exit;
-       
+
              plt_count = relplt->size / sizeof (Elf64_External_Rela);
              size += plt_count * sizeof (asymbol);
 
@@ -3316,8 +3465,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
                {
                  if (sec->vma > ent)
                    break;
-                 if ((sec->flags & SEC_ALLOC) == 0
-                     || (sec->flags & SEC_LOAD) == 0)
+                 /* SEC_LOAD may not be set if SEC is from a separate debug
+                    info file.  */
+                 if ((sec->flags & SEC_ALLOC) == 0)
                    break;
                  if ((sec->flags & SEC_CODE) != 0)
                    s->section = sec;
@@ -3398,8 +3548,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;
@@ -3450,13 +3605,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
@@ -3483,26 +3638,6 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
    calls may use the function descriptor symbol, ie. "bl foo".  This
    behaves exactly as "bl .foo".  */
 
-/* The linker needs to keep track of the number of relocs that it
-   decides to copy as dynamic relocs in check_relocs for each symbol.
-   This is so that it can later discard them if they are found to be
-   unnecessary.  We store the information in a field extending the
-   regular ELF linker hash table.  */
-
-struct ppc_dyn_relocs
-{
-  struct ppc_dyn_relocs *next;
-
-  /* The input section of the reloc.  */
-  asection *sec;
-
-  /* Total number of relocs copied for the input section.  */
-  bfd_size_type count;
-
-  /* Number of pc-relative relocs copied for the input section.  */
-  bfd_size_type pc_count;
-};
-
 /* Of those relocs that might be copied as dynamic relocs, this function
    selects those that must be copied when linking a shared library,
    even when the symbol is local.  */
@@ -3527,6 +3662,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:
@@ -3566,21 +3703,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
@@ -3593,11 +3730,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
@@ -3610,7 +3747,8 @@ enum ppc_stub_type {
   ppc_stub_long_branch_r2off,
   ppc_stub_plt_branch,
   ppc_stub_plt_branch_r2off,
-  ppc_stub_plt_call
+  ppc_stub_plt_call,
+  ppc_stub_plt_call_r2save
 };
 
 struct ppc_stub_hash_entry {
@@ -3635,12 +3773,12 @@ struct ppc_stub_hash_entry {
   struct ppc_link_hash_entry *h;
   struct plt_entry *plt_ent;
 
-  /* And the reloc addend that this was derived from.  */
-  bfd_vma addend;
-
   /* 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 {
@@ -3655,6 +3793,21 @@ struct ppc_branch_hash_entry {
   unsigned int iter;
 };
 
+/* Used to track dynamic relocations for local symbols.  */
+struct ppc_dyn_relocs
+{
+  struct ppc_dyn_relocs *next;
+
+  /* The input section of the reloc.  */
+  asection *sec;
+
+  /* Total number of relocs copied for the input section.  */
+  unsigned int count : 31;
+
+  /* Whether this entry is for STT_GNU_IFUNC symbols.  */
+  unsigned int ifunc : 1;
+};
+
 struct ppc_link_hash_entry
 {
   struct elf_link_hash_entry elf;
@@ -3669,7 +3822,7 @@ struct ppc_link_hash_entry
   } u;
 
   /* Track dynamic relocs copied for this symbol.  */
-  struct ppc_dyn_relocs *dyn_relocs;
+  struct elf_dyn_relocs *dyn_relocs;
 
   /* Link between function code and descriptor symbols.  */
   struct ppc_link_hash_entry *oh;
@@ -3718,6 +3871,9 @@ struct ppc_link_hash_table
   /* Another hash table for plt_branch stubs.  */
   struct bfd_hash_table branch_hash_table;
 
+  /* Hash table for function prologue tocsave.  */
+  htab_t tocsave_htab;
+
   /* Linker stub bfd.  */
   bfd *stub_bfd;
 
@@ -3753,18 +3909,14 @@ struct ppc_link_hash_table
   /* List of input sections for each output section.  */
   asection **input_list;
 
-  /* Short-cuts to get to dynamic linker sections.  */
-  asection *got;
-  asection *plt;
-  asection *relplt;
-  asection *iplt;
-  asection *reliplt;
+  /* Shortcuts to get to dynamic linker sections.  */
   asection *dynbss;
   asection *relbss;
   asection *glink;
   asection *sfpr;
   asection *brlt;
   asection *relbrlt;
+  asection *glink_eh_frame;
 
   /* Shortcut to .__tls_get_addr and __tls_get_addr.  */
   struct ppc_link_hash_entry *tls_get_addr;
@@ -3774,11 +3926,23 @@ struct ppc_link_hash_table
   bfd_size_type got_reli_size;
 
   /* Statistics.  */
-  unsigned long stub_count[ppc_stub_plt_call];
+  unsigned long stub_count[ppc_stub_plt_call_r2save];
 
   /* Number of stubs against global syms.  */
   unsigned long stub_globals;
 
+  /* 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;
+
+  /* Set if PLT call stubs need a read-read barrier.  */
+  unsigned int plt_thread_safe:1;
+
   /* Set if we should emit symbols for stubs.  */
   unsigned int emit_stub_syms:1;
 
@@ -3868,7 +4032,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;
@@ -3960,6 +4126,26 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
   return entry;
 }
 
+struct tocsave_entry {
+  asection *sec;
+  bfd_vma offset;
+};
+
+static hashval_t
+tocsave_htab_hash (const void *p)
+{
+  const struct tocsave_entry *e = (const struct tocsave_entry *) p;
+  return ((bfd_vma)(intptr_t) e->sec ^ e->offset) >> 3;
+}
+
+static int
+tocsave_htab_eq (const void *p1, const void *p2)
+{
+  const struct tocsave_entry *e1 = (const struct tocsave_entry *) p1;
+  const struct tocsave_entry *e2 = (const struct tocsave_entry *) p2;
+  return e1->sec == e2->sec && e1->offset == e2->offset;
+}
+
 /* Create a ppc64 ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
@@ -3990,6 +4176,13 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
                            sizeof (struct ppc_branch_hash_entry)))
     return NULL;
 
+  htab->tocsave_htab = htab_try_create (1024,
+                                       tocsave_htab_hash,
+                                       tocsave_htab_eq,
+                                       NULL);
+  if (htab->tocsave_htab == NULL)
+    return NULL;
+
   /* Initializing two fields of the union is just cosmetic.  We really
      only care about glist, but when compiled on a 32-bit host the
      bfd_vma fields are larger.  Setting the bfd_vma to zero makes
@@ -4011,42 +4204,125 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
 static void
 ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
 {
-  struct ppc_link_hash_table *ret = (struct ppc_link_hash_table *) hash;
+  struct ppc_link_hash_table *htab = (struct ppc_link_hash_table *) hash;
 
-  bfd_hash_table_free (&ret->stub_hash_table);
-  bfd_hash_table_free (&ret->branch_hash_table);
-  _bfd_generic_link_hash_table_free (hash);
+  bfd_hash_table_free (&htab->stub_hash_table);
+  bfd_hash_table_free (&htab->branch_hash_table);
+  if (htab->tocsave_htab)
+    htab_delete (htab->tocsave_htab);
+  _bfd_elf_link_hash_table_free (hash);
 }
 
-/* Satisfy the ELF linker by filling in some fields in our fake bfd.  */
+/* Create sections for linker generated code.  */
 
-void
-ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
+static bfd_boolean
+create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
+  flagword flags;
 
-  elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64;
-
-/* Always hook our dynamic sections into the first bfd, which is the
-   linker created stub bfd.  This ensures that the GOT header is at
-   the start of the output TOC section.  */
   htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return;
-  htab->stub_bfd = abfd;
-  htab->elf.dynobj = abfd;
-}
 
-/* Build a name for an entry in the stub hash table.  */
+  /* Create .sfpr for code to save and restore fp regs.  */
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
+          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+  htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
+                                                  flags);
+  if (htab->sfpr == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
+    return FALSE;
 
-static char *
+  /* Create .glink for lazy dynamic linking support.  */
+  htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
+                                                   flags);
+  if (htab->glink == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->glink, 3))
+    return FALSE;
+
+  if (!info->no_ld_generated_unwind_info)
+    {
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
+              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      htab->glink_eh_frame = bfd_make_section_anyway_with_flags (dynobj,
+                                                                ".eh_frame",
+                                                                flags);
+      if (htab->glink_eh_frame == NULL
+         || !bfd_set_section_alignment (dynobj, htab->glink_eh_frame, 2))
+       return FALSE;
+    }
+
+  flags = SEC_ALLOC | SEC_LINKER_CREATED;
+  htab->elf.iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
+  if (htab->elf.iplt == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->elf.iplt, 3))
+    return FALSE;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+  htab->elf.irelplt
+    = bfd_make_section_anyway_with_flags (dynobj, ".rela.iplt", flags);
+  if (htab->elf.irelplt == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->elf.irelplt, 3))
+    return FALSE;
+
+  /* Create branch lookup table for plt_branch stubs.  */
+  flags = (SEC_ALLOC | SEC_LOAD
+          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+  htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
+                                                  flags);
+  if (htab->brlt == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
+    return FALSE;
+
+  if (!info->shared)
+    return TRUE;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+  htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
+                                                     ".rela.branch_lt",
+                                                     flags);
+  if (htab->relbrlt == NULL
+      || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Satisfy the ELF linker by filling in some fields in our fake bfd.  */
+
+bfd_boolean
+ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
+{
+  struct ppc_link_hash_table *htab;
+
+  elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64;
+
+/* Always hook our dynamic sections into the first bfd, which is the
+   linker created stub bfd.  This ensures that the GOT header is at
+   the start of the output TOC section.  */
+  htab = ppc_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+  htab->stub_bfd = abfd;
+  htab->elf.dynobj = abfd;
+
+  if (info->relocatable)
+    return TRUE;
+
+  return create_linkage_sections (htab->elf.dynobj, info);
+}
+
+/* Build a name for an entry in the stub hash table.  */
+
+static char *
 ppc_stub_name (const asection *input_section,
               const asection *sym_sec,
               const struct ppc_link_hash_entry *h,
               const Elf_Internal_Rela *rel)
 {
   char *stub_name;
-  bfd_size_type len;
+  ssize_t len;
 
   /* rel->r_addend is actually 64 bit, but who uses more than +/- 2^31
      offsets from a sym as a branch target?  In fact, we could
@@ -4060,10 +4336,10 @@ ppc_stub_name (const asection *input_section,
       if (stub_name == NULL)
        return stub_name;
 
-      sprintf (stub_name, "%08x.%s+%x",
-              input_section->id & 0xffffffff,
-              h->elf.root.root.string,
-              (int) rel->r_addend & 0xffffffff);
+      len = sprintf (stub_name, "%08x.%s+%x",
+                    input_section->id & 0xffffffff,
+                    h->elf.root.root.string,
+                    (int) rel->r_addend & 0xffffffff);
     }
   else
     {
@@ -4072,13 +4348,13 @@ ppc_stub_name (const asection *input_section,
       if (stub_name == NULL)
        return stub_name;
 
-      sprintf (stub_name, "%08x.%x:%x+%x",
-              input_section->id & 0xffffffff,
-              sym_sec->id & 0xffffffff,
-              (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
-              (int) rel->r_addend & 0xffffffff);
+      len = sprintf (stub_name, "%08x.%x:%x+%x",
+                    input_section->id & 0xffffffff,
+                    sym_sec->id & 0xffffffff,
+                    (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
+                    (int) rel->r_addend & 0xffffffff);
     }
-  if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
+  if (len > 2 && stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
     stub_name[len - 2] = 0;
   return stub_name;
 }
@@ -4134,8 +4410,9 @@ ppc_get_stub_entry (const asection *input_section,
 static struct ppc_stub_hash_entry *
 ppc_add_stub (const char *stub_name,
              asection *section,
-             struct ppc_link_hash_table *htab)
+             struct bfd_link_info *info)
 {
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
   asection *link_sec;
   asection *stub_sec;
   struct ppc_stub_hash_entry *stub_entry;
@@ -4172,8 +4449,8 @@ ppc_add_stub (const char *stub_name,
                                     TRUE, FALSE);
   if (stub_entry == NULL)
     {
-      (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
-                            section->owner, stub_name);
+      info->callbacks->einfo (_("%P: %B: cannot create stub entry %s\n"),
+                             section->owner, stub_name);
       return NULL;
     }
 
@@ -4183,73 +4460,6 @@ ppc_add_stub (const char *stub_name,
   return stub_entry;
 }
 
-/* Create sections for linker generated code.  */
-
-static bfd_boolean
-create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
-{
-  struct ppc_link_hash_table *htab;
-  flagword flags;
-
-  htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
-
-  /* Create .sfpr for code to save and restore fp regs.  */
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
-          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
-                                                  flags);
-  if (htab->sfpr == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
-    return FALSE;
-
-  /* Create .glink for lazy dynamic linking support.  */
-  htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
-                                                   flags);
-  if (htab->glink == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->glink, 3))
-    return FALSE;
-
-  flags = SEC_ALLOC | SEC_LINKER_CREATED;
-  htab->iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
-  if (htab->iplt == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->iplt, 3))
-    return FALSE;
-
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
-          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->reliplt = bfd_make_section_anyway_with_flags (dynobj,
-                                                     ".rela.iplt",
-                                                     flags);
-  if (htab->reliplt == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->reliplt, 3))
-    return FALSE;
-
-  /* Create branch lookup table for plt_branch stubs.  */
-  flags = (SEC_ALLOC | SEC_LOAD
-          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
-                                                  flags);
-  if (htab->brlt == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
-    return FALSE;
-
-  if (!info->shared)
-    return TRUE;
-
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
-          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
-                                                     ".rela.branch_lt",
-                                                     flags);
-  if (htab->relbrlt == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
-    return FALSE;
-
-  return TRUE;
-}
-
 /* Create .got and .rela.got sections in ABFD, and .got in dynobj if
    not already done.  */
 
@@ -4265,15 +4475,9 @@ create_got_section (bfd *abfd, struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
-  if (!htab->got)
-    {
-      if (! _bfd_elf_create_got_section (htab->elf.dynobj, info))
-       return FALSE;
-
-      htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got");
-      if (!htab->got)
-       abort ();
-    }
+  if (!htab->elf.sgot
+      && !_bfd_elf_create_got_section (htab->elf.dynobj, info))
+    return FALSE;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED);
@@ -4308,15 +4512,11 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
-  if (!htab->got)
-    htab->got = bfd_get_section_by_name (dynobj, ".got");
-  htab->plt = bfd_get_section_by_name (dynobj, ".plt");
-  htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt");
-  htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+  htab->dynbss = bfd_get_linker_section (dynobj, ".dynbss");
   if (!info->shared)
-    htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+    htab->relbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
-  if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss
+  if (!htab->elf.sgot || !htab->elf.splt || !htab->elf.srelplt || !htab->dynbss
       || (!info->shared && !htab->relbss))
     abort ();
 
@@ -4393,19 +4593,39 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct ppc_link_hash_entry *) dir;
   eind = (struct ppc_link_hash_entry *) ind;
 
+  edir->is_func |= eind->is_func;
+  edir->is_func_descriptor |= eind->is_func_descriptor;
+  edir->tls_mask |= eind->tls_mask;
+  if (eind->oh != NULL)
+    edir->oh = ppc_follow_link (eind->oh);
+
+  /* If called to transfer flags for a weakdef during processing
+     of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
+     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
+  if (!(ELIMINATE_COPY_RELOCS
+       && eind->elf.root.type != bfd_link_hash_indirect
+       && edir->elf.dynamic_adjusted))
+    edir->elf.non_got_ref |= eind->elf.non_got_ref;
+
+  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
+  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)
     {
       if (edir->dyn_relocs != NULL)
        {
-         struct ppc_dyn_relocs **pp;
-         struct ppc_dyn_relocs *p;
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
 
          /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
            {
-             struct ppc_dyn_relocs *q;
+             struct elf_dyn_relocs *q;
 
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
                if (q->sec == p->sec)
@@ -4425,26 +4645,13 @@ ppc64_elf_copy_indirect_symbol (struct bfd_link_info *info,
       eind->dyn_relocs = NULL;
     }
 
-  edir->is_func |= eind->is_func;
-  edir->is_func_descriptor |= eind->is_func_descriptor;
-  edir->tls_mask |= eind->tls_mask;
-  if (eind->oh != NULL)
-    edir->oh = ppc_follow_link (eind->oh);
-
-  /* If called to transfer flags for a weakdef during processing
-     of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
-     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-  if (!(ELIMINATE_COPY_RELOCS
-       && eind->elf.root.type != bfd_link_hash_indirect
-       && edir->elf.dynamic_adjusted))
-    edir->elf.non_got_ref |= eind->elf.non_got_ref;
-
-  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
-  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;
-
-  /* If we were called to copy over info for a weak sym, that's all.  */
+  /* If we were called to copy over info for a weak sym, that's all.
+     You might think dyn_relocs need not be copied over;  After all,
+     both syms will be dynamic or both non-dynamic so we're just
+     moving reloc accounting around.  However, ELIMINATE_COPY_RELOCS
+     code in ppc64_elf_adjust_dynamic_symbol needs to check for
+     dyn_relocs in read-only sections, and it does so on what is the
+     DIR sym here.  */
   if (eind->elf.root.type != bfd_link_hash_indirect)
     return;
 
@@ -4563,15 +4770,19 @@ 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)
 {
+  if ((ibfd->flags & DYNAMIC) == 0
+      && ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
+    elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
+
   if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
     {
       if ((ibfd->flags & DYNAMIC) == 0)
-       elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+       elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
     }
   else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
     ;
@@ -4579,9 +4790,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
@@ -4705,7 +4942,12 @@ ppc64_elf_process_dot_syms (bfd *ibfd, struct bfd_link_info *info)
       while ((eh = *p) != NULL)
        {
          *p = NULL;
-         if (!add_symbol_adjust (eh, info))
+         if (&eh->elf == htab->elf.hgot)
+           ;
+         else if (htab->elf.hgot == NULL
+                  && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
+           htab->elf.hgot = &eh->elf;
+         else if (!add_symbol_adjust (eh, info))
            return FALSE;
          p = &eh->u.next_dot_sym;
        }
@@ -4733,16 +4975,37 @@ ppc64_elf_process_dot_syms (bfd *ibfd, struct bfd_link_info *info)
    not to be needed.  */
 
 static bfd_boolean
-ppc64_elf_as_needed_cleanup (bfd *ibfd ATTRIBUTE_UNUSED,
-                            struct bfd_link_info *info)
+ppc64_elf_notice_as_needed (bfd *ibfd,
+                           struct bfd_link_info *info,
+                           enum notice_asneeded_action act)
 {
-  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  if (act == notice_not_needed)
+    {
+      struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
-  if (htab == NULL)
-    return FALSE;
+      if (htab == NULL)
+       return FALSE;
 
-  htab->dot_syms = NULL;
-  return TRUE;
+      htab->dot_syms = NULL;
+    }
+  return _bfd_elf_notice_as_needed (ibfd, info, act);
+}
+
+/* If --just-symbols against a final linked binary, then assume we need
+   toc adjusting stubs when calling functions defined there.  */
+
+static void
+ppc64_elf_link_just_syms (asection *sec, struct bfd_link_info *info)
+{
+  if ((sec->flags & SEC_CODE) != 0
+      && (sec->owner->flags & (EXEC_P | DYNAMIC)) != 0
+      && is_ppc64_elf (sec->owner))
+    {
+      if (abiversion (sec->owner) >= 2
+         || bfd_get_section_by_name (sec->owner, ".opd") != NULL)
+       sec->has_toc_reloc = 1;
+    }
+  _bfd_elf_link_just_syms (sec, info);
 }
 
 static struct plt_entry **
@@ -4889,6 +5152,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)
@@ -4898,10 +5170,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       ppc64_elf_section_data (sec)->sec_type = sec_opd;
     }
 
-  if (htab->sfpr == NULL
-      && !create_linkage_sections (htab->elf.dynobj, info))
-    return FALSE;
-
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -4919,6 +5187,13 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = elf_follow_link (h);
+
+         /* PR15323, ref flags aren't set for references in the same
+            object.  */
+         h->root.non_ir_ref = 1;
+
+         if (h == htab->elf.hgot)
+           sec->has_toc_reloc = 1;
        }
 
       tls_type = 0;
@@ -5064,6 +5339,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:
@@ -5109,6 +5392,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:
@@ -5269,6 +5554,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:
@@ -5312,22 +5599,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:
@@ -5367,7 +5667,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          if ((info->shared
               && (must_be_dyn_reloc (info, r_type)
                   || (h != NULL
-                      && (! info->symbolic
+                      && (!SYMBOLIC_BIND (info, h)
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
@@ -5378,9 +5678,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              || (!info->shared
                  && ifunc != NULL))
            {
-             struct ppc_dyn_relocs *p;
-             struct ppc_dyn_relocs **head;
-
              /* We must copy these reloc types into the output file.
                 Create a reloc section in dynobj and make room for
                 this reloc.  */
@@ -5397,13 +5694,34 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                 relocations we need for this symbol.  */
              if (h != NULL)
                {
+                 struct elf_dyn_relocs *p;
+                 struct elf_dyn_relocs **head;
+
                  head = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
+                 p = *head;
+                 if (p == NULL || p->sec != sec)
+                   {
+                     p = bfd_alloc (htab->elf.dynobj, sizeof *p);
+                     if (p == NULL)
+                       return FALSE;
+                     p->next = *head;
+                     *head = p;
+                     p->sec = sec;
+                     p->count = 0;
+                     p->pc_count = 0;
+                   }
+                 p->count += 1;
+                 if (!must_be_dyn_reloc (info, r_type))
+                   p->pc_count += 1;
                }
              else
                {
                  /* Track dynamic relocs needed for local syms too.
                     We really need local syms available to do this
                     easily.  Oh well.  */
+                 struct ppc_dyn_relocs *p;
+                 struct ppc_dyn_relocs **head;
+                 bfd_boolean is_ifunc;
                  asection *s;
                  void *vpp;
                  Elf_Internal_Sym *isym;
@@ -5419,24 +5737,23 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
                  vpp = &elf_section_data (s)->local_dynrel;
                  head = (struct ppc_dyn_relocs **) vpp;
+                 is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
+                 p = *head;
+                 if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
+                   p = p->next;
+                 if (p == NULL || p->sec != sec || p->ifunc != is_ifunc)
+                   {
+                     p = bfd_alloc (htab->elf.dynobj, sizeof *p);
+                     if (p == NULL)
+                       return FALSE;
+                     p->next = *head;
+                     *head = p;
+                     p->sec = sec;
+                     p->ifunc = is_ifunc;
+                     p->count = 0;
+                   }
+                 p->count += 1;
                }
-
-             p = *head;
-             if (p == NULL || p->sec != sec)
-               {
-                 p = bfd_alloc (htab->elf.dynobj, sizeof *p);
-                 if (p == NULL)
-                   return FALSE;
-                 p->next = *head;
-                 *head = p;
-                 p->sec = sec;
-                 p->count = 0;
-                 p->pc_count = 0;
-               }
-
-             p->count += 1;
-             if (!must_be_dyn_reloc (info, r_type))
-               p->pc_count += 1;
            }
          break;
 
@@ -5448,6 +5765,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.  */
 
@@ -5455,27 +5844,47 @@ static bfd_vma
 opd_entry_value (asection *opd_sec,
                 bfd_vma offset,
                 asection **code_sec,
-                bfd_vma *code_off)
+                bfd_vma *code_off,
+                bfd_boolean in_code_sec)
 {
   bfd *opd_bfd = opd_sec->owner;
   Elf_Internal_Rela *relocs;
   Elf_Internal_Rela *lo, *hi, *look;
   bfd_vma val;
 
-  /* No relocs implies we are linking a --just-symbols object.  */
+  /* No relocs implies we are linking a --just-symbols object, or looking
+     at a final linked executable with addr2line or somesuch.  */
   if (opd_sec->reloc_count == 0)
     {
-      if (!bfd_get_section_contents (opd_bfd, opd_sec, &val, offset, 8))
-       return (bfd_vma) -1;
+      bfd_byte *contents = ppc64_elf_tdata (opd_bfd)->opd.contents;
+
+      if (contents == NULL)
+       {
+         if (!bfd_malloc_and_get_section (opd_bfd, opd_sec, &contents))
+           return (bfd_vma) -1;
+         ppc64_elf_tdata (opd_bfd)->opd.contents = contents;
+       }
 
+      val = bfd_get_64 (opd_bfd, contents + offset);
       if (code_sec != NULL)
        {
          asection *sec, *likely = NULL;
-         for (sec = opd_bfd->sections; sec != NULL; sec = sec->next)
-           if (sec->vma <= val
-               && (sec->flags & SEC_LOAD) != 0
-               && (sec->flags & SEC_ALLOC) != 0)
-             likely = sec;
+
+         if (in_code_sec)
+           {
+             sec = *code_sec;
+             if (sec->vma <= val
+                 && val < sec->vma + sec->size)
+               likely = sec;
+             else
+               val = -1;
+           }
+         else
+           for (sec = opd_bfd->sections; sec != NULL; sec = sec->next)
+             if (sec->vma <= val
+                 && (sec->flags & SEC_LOAD) != 0
+                 && (sec->flags & SEC_ALLOC) != 0)
+               likely = sec;
          if (likely != NULL)
            {
              *code_sec = likely;
@@ -5488,7 +5897,7 @@ opd_entry_value (asection *opd_sec,
 
   BFD_ASSERT (is_ppc64_elf (opd_bfd));
 
-  relocs = ppc64_elf_tdata (opd_bfd)->opd_relocs;
+  relocs = ppc64_elf_tdata (opd_bfd)->opd.relocs;
   if (relocs == NULL)
     relocs = _bfd_elf_link_read_relocs (opd_bfd, opd_sec, NULL, NULL, TRUE);
 
@@ -5514,15 +5923,18 @@ opd_entry_value (asection *opd_sec,
              unsigned long symndx = ELF64_R_SYM (look->r_info);
              asection *sec;
 
-             if (symndx < symtab_hdr->sh_info)
+             if (symndx < symtab_hdr->sh_info
+                 || elf_sym_hashes (opd_bfd) == NULL)
                {
                  Elf_Internal_Sym *sym;
 
                  sym = (Elf_Internal_Sym *) symtab_hdr->contents;
                  if (sym == NULL)
                    {
-                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
-                                                 symtab_hdr->sh_info,
+                     size_t symcnt = symtab_hdr->sh_info;
+                     if (elf_sym_hashes (opd_bfd) == NULL)
+                       symcnt = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
+                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, symcnt,
                                                  0, NULL, NULL, NULL);
                      if (sym == NULL)
                        break;
@@ -5541,17 +5953,41 @@ opd_entry_value (asection *opd_sec,
 
                  sym_hashes = elf_sym_hashes (opd_bfd);
                  rh = sym_hashes[symndx - symtab_hdr->sh_info];
-                 rh = elf_follow_link (rh);
-                 BFD_ASSERT (rh->root.type == bfd_link_hash_defined
-                             || rh->root.type == bfd_link_hash_defweak);
-                 val = rh->root.u.def.value;
-                 sec = rh->root.u.def.section;
+                 if (rh != NULL)
+                   {
+                     rh = elf_follow_link (rh);
+                     BFD_ASSERT (rh->root.type == bfd_link_hash_defined
+                                 || rh->root.type == bfd_link_hash_defweak);
+                     val = rh->root.u.def.value;
+                     sec = rh->root.u.def.section;
+                   }
+                 else
+                   {
+                     /* Handle the odd case where we can be called
+                        during bfd_elf_link_add_symbols before the
+                        symbol hashes have been fully populated.  */
+                     Elf_Internal_Sym *sym;
+
+                     sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, 1,
+                                                 symndx, NULL, NULL, NULL);
+                     if (sym == NULL)
+                       break;
+
+                     val = sym->st_value;
+                     sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
+                     free (sym);
+                   }
                }
              val += look->r_addend;
              if (code_off != NULL)
                *code_off = val;
              if (code_sec != NULL)
-               *code_sec = sec;
+               {
+                 if (in_code_sec && *code_sec != sec)
+                   return -1;
+                 else
+                   *code_sec = sec;
+               }
              if (sec != NULL && sec->output_section != NULL)
                val += sec->output_section->vma + sec->output_offset;
            }
@@ -5562,6 +5998,55 @@ opd_entry_value (asection *opd_sec,
   return val;
 }
 
+/* If the ELF symbol SYM might be a function in SEC, return the
+   function size and set *CODE_OFF to the function's entry point,
+   otherwise return zero.  */
+
+static bfd_size_type
+ppc64_elf_maybe_function_sym (const asymbol *sym, asection *sec,
+                             bfd_vma *code_off)
+{
+  bfd_size_type size;
+
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+                    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0)
+    return 0;
+
+  size = 0;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+
+  if (strcmp (sym->section->name, ".opd") == 0)
+    {
+      if (opd_entry_value (sym->section, sym->value,
+                          &sec, code_off, TRUE) == (bfd_vma) -1)
+       return 0;
+      /* An old ABI binary with dot-syms has a size of 24 on the .opd
+        symbol.  This size has nothing to do with the code size of the
+        function, which is what we're supposed to return, but the
+        code size isn't available without looking up the dot-sym.
+        However, doing that would be a waste of time particularly
+        since elf_find_function will look at the dot-sym anyway.
+        Now, elf_find_function will keep the largest size of any
+        function sym found at the code address of interest, so return
+        1 here to avoid it incorrectly caching a larger function size
+        for a small function.  This does mean we return the wrong
+        size for a new-ABI function of size 24, but all that does is
+        disable caching for such functions.  */
+      if (size == 24)
+       size = 1;
+    }
+  else
+    {
+      if (sym->section != sec)
+       return 0;
+      *code_off = sym->value;
+    }
+  if (size == 0)
+    size = 1;
+  return size;
+}
+
 /* Return true if symbol is defined in a regular object file.  */
 
 static bfd_boolean
@@ -5639,7 +6124,7 @@ ppc64_elf_gc_keep (struct bfd_link_info *info)
       else if (get_opd_info (eh->elf.root.u.def.section) != NULL
               && opd_entry_value (eh->elf.root.u.def.section,
                                   eh->elf.root.u.def.value,
-                                  &sec, NULL) != (bfd_vma) -1)
+                                  &sec, NULL, FALSE) != (bfd_vma) -1)
        sec->flags |= SEC_KEEP;
 
       sec = eh->elf.root.u.def.section;
@@ -5658,9 +6143,6 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
   struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) h;
   struct ppc_link_hash_entry *fdh;
 
-  if (eh->elf.root.type == bfd_link_hash_warning)
-    eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
-
   /* Dynamic linking info is on the func descriptor sym.  */
   fdh = defined_func_desc (eh);
   if (fdh != NULL)
@@ -5672,7 +6154,10 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
          || (!info->executable
              && eh->elf.def_regular
              && ELF_ST_VISIBILITY (eh->elf.other) != STV_INTERNAL
-             && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN)))
+             && ELF_ST_VISIBILITY (eh->elf.other) != STV_HIDDEN
+             && (strchr (eh->elf.root.root.string, ELF_VER_CHR) != NULL
+                 || !bfd_hide_sym_by_version (info->version_info,
+                                              eh->elf.root.root.string)))))
     {
       asection *code_sec;
       struct ppc_link_hash_entry *fh;
@@ -5690,7 +6175,7 @@ ppc64_elf_gc_mark_dynamic_ref (struct elf_link_hash_entry *h, void *inf)
       else if (get_opd_info (eh->elf.root.u.def.section) != NULL
               && opd_entry_value (eh->elf.root.u.def.section,
                                   eh->elf.root.u.def.value,
-                                  &code_sec, NULL) != (bfd_vma) -1)
+                                  &code_sec, NULL, FALSE) != (bfd_vma) -1)
        code_sec->flags |= SEC_KEEP;
     }
 
@@ -5750,7 +6235,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
              else if (get_opd_info (eh->elf.root.u.def.section) != NULL
                       && opd_entry_value (eh->elf.root.u.def.section,
                                           eh->elf.root.u.def.value,
-                                          &rsec, NULL) != (bfd_vma) -1)
+                                          &rsec, NULL, FALSE) != (bfd_vma) -1)
                eh->elf.root.u.def.section->gc_mark = 1;
              else
                rsec = h->root.u.def.section;
@@ -5824,8 +6309,8 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       if (r_symndx >= symtab_hdr->sh_info)
        {
          struct ppc_link_hash_entry *eh;
-         struct ppc_dyn_relocs **pp;
-         struct ppc_dyn_relocs *p;
+         struct elf_dyn_relocs **pp;
+         struct elf_dyn_relocs *p;
 
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = elf_follow_link (h);
@@ -6034,7 +6519,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;
@@ -6050,7 +6535,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);
@@ -6105,7 +6590,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;
@@ -6121,7 +6606,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);
@@ -6203,9 +6688,6 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
   if (fh->elf.root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (fh->elf.root.type == bfd_link_hash_warning)
-    fh = (struct ppc_link_hash_entry *) fh->elf.root.u.i.link;
-
   info = inf;
   htab = ppc_hash_table (info);
   if (htab == NULL)
@@ -6222,7 +6704,7 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
       && opd_entry_value (fdh->elf.root.u.def.section,
                          fdh->elf.root.u.def.value,
                          &fh->elf.root.u.def.section,
-                         &fh->elf.root.u.def.value) != (bfd_vma) -1)
+                         &fh->elf.root.u.def.value, FALSE) != (bfd_vma) -1)
     {
       fh->elf.root.type = fdh->elf.root.type;
       fh->elf.forced_local = 1;
@@ -6331,7 +6813,7 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
 {
   struct ppc_link_hash_table *htab;
   unsigned int i;
-  const struct sfpr_def_parms funcs[] =
+  static const struct sfpr_def_parms funcs[] =
     {
       { "_savegpr0_", 14, 31, savegpr0, savegpr0_tail },
       { "_restgpr0_", 14, 29, restgpr0, restgpr0_tail },
@@ -6351,15 +6833,31 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
   if (htab == NULL)
     return FALSE;
 
+  if (!info->relocatable
+      && htab->elf.hgot != NULL)
+    {
+      _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
+      /* Make .TOC. defined so as to prevent it being made dynamic.
+        The wrong value here is fixed later in ppc64_elf_set_toc.  */
+      htab->elf.hgot->type = STT_OBJECT;
+      htab->elf.hgot->root.type = bfd_link_hash_defined;
+      htab->elf.hgot->root.u.def.value = 0;
+      htab->elf.hgot->root.u.def.section = bfd_abs_section_ptr;
+      htab->elf.hgot->def_regular = 1;
+      htab->elf.hgot->other = ((htab->elf.hgot->other & ~ELF_ST_VISIBILITY (-1))
+                              | STV_HIDDEN);
+    }
+
   if (htab->sfpr == NULL)
     /* We don't have any relocs.  */
     return TRUE;
 
   /* Provide any missing _save* and _rest* functions.  */
   htab->sfpr->size = 0;
-  for (i = 0; i < sizeof (funcs) / sizeof (funcs[0]); i++)
-    if (!sfpr_define (info, &funcs[i]))
-      return FALSE;
+  if (!info->relocatable)
+    for (i = 0; i < sizeof (funcs) / sizeof (funcs[0]); i++)
+      if (!sfpr_define (info, &funcs[i]))
+       return FALSE;
 
   elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
 
@@ -6369,6 +6867,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
@@ -6406,6 +6923,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;
@@ -6440,26 +6977,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 ppc_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)
@@ -6469,21 +6992,14 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
         function pointers, vtable refs and suchlike in read-only
         sections.  Allow them to proceed, but warn that this might
         break at runtime.  */
-      (*_bfd_error_handler)
-       (_("copy reloc against `%s' requires lazy plt linking; "
-          "avoid setting LD_BIND_NOW=1 or upgrade gcc"),
+      info->callbacks->einfo
+       (_("%P: copy reloc against `%T' requires lazy plt linking; "
+          "avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
         h->root.root.string);
     }
 
   /* This is a reference to a symbol defined by a dynamic object which
-     is not a function.  */
-
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
-      return TRUE;
-    }
+     is not a function.  */
 
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
@@ -6499,7 +7015,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      to copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rela.bss section we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       htab->relbss->size += sizeof (Elf64_External_Rela);
       h->needs_copy = 1;
@@ -6718,6 +7234,55 @@ get_tls_mask (unsigned char **tls_maskp,
   return 1;
 }
 
+/* Find (or create) an entry in the tocsave hash table.  */
+
+static struct tocsave_entry *
+tocsave_find (struct ppc_link_hash_table *htab,
+             enum insert_option insert,
+             Elf_Internal_Sym **local_syms,
+             const Elf_Internal_Rela *irela,
+             bfd *ibfd)
+{
+  unsigned long r_indx;
+  struct elf_link_hash_entry *h;
+  Elf_Internal_Sym *sym;
+  struct tocsave_entry ent, *p;
+  hashval_t hash;
+  struct tocsave_entry **slot;
+
+  r_indx = ELF64_R_SYM (irela->r_info);
+  if (!get_sym_h (&h, &sym, &ent.sec, NULL, local_syms, r_indx, ibfd))
+    return NULL;
+  if (ent.sec == NULL || ent.sec->output_section == NULL)
+    {
+      (*_bfd_error_handler)
+       (_("%B: undefined symbol on R_PPC64_TOCSAVE relocation"));
+      return NULL;
+    }
+
+  if (h != NULL)
+    ent.offset = h->root.u.def.value;
+  else
+    ent.offset = sym->st_value;
+  ent.offset += irela->r_addend;
+
+  hash = tocsave_htab_hash (&ent);
+  slot = ((struct tocsave_entry **)
+         htab_find_slot_with_hash (htab->tocsave_htab, &ent, hash, insert));
+  if (slot == NULL)
+    return NULL;
+
+  if (*slot == NULL)
+    {
+      p = (struct tocsave_entry *) bfd_alloc (ibfd, sizeof (*p));
+      if (p == NULL)
+       return NULL;
+      *p = ent;
+      *slot = p;
+    }
+  return *slot;
+}
+
 /* Adjust all global syms defined in opd sections.  In gcc generated
    code for the old ABI, these will already have been done.  */
 
@@ -6731,9 +7296,6 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   if (h->root.type != bfd_link_hash_defined
       && h->root.type != bfd_link_hash_defweak)
     return TRUE;
@@ -6754,7 +7316,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
          if (dsec == NULL)
            {
              for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
-               if (elf_discarded_section (dsec))
+               if (discarded_section (dsec))
                  {
                    ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec;
                    break;
@@ -6771,7 +7333,7 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
 }
 
 /* Handles decrementing dynamic reloc counts for the reloc specified by
-   R_INFO in section SEC.  If LOCAL_SYMS is NULL, then H and SYM_SEC
+   R_INFO in section SEC.  If LOCAL_SYMS is NULL, then H and SYM
    have already been determined.  */
 
 static bfd_boolean
@@ -6780,11 +7342,10 @@ dec_dynrel_count (bfd_vma r_info,
                  struct bfd_link_info *info,
                  Elf_Internal_Sym **local_syms,
                  struct elf_link_hash_entry *h,
-                 asection *sym_sec)
+                 Elf_Internal_Sym *sym)
 {
   enum elf_ppc64_reloc_type r_type;
-  struct ppc_dyn_relocs *p;
-  struct ppc_dyn_relocs **pp;
+  asection *sym_sec = NULL;
 
   /* Can this reloc be dynamic?  This switch, and later tests here
      should be kept in sync with the code in check_relocs.  */
@@ -6800,6 +7361,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:
@@ -6821,6 +7384,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:
@@ -6839,7 +7404,6 @@ dec_dynrel_count (bfd_vma r_info,
   if (local_syms != NULL)
     {
       unsigned long r_symndx;
-      Elf_Internal_Sym *sym;
       bfd *ibfd = sec->owner;
 
       r_symndx = ELF64_R_SYM (r_info);
@@ -6850,7 +7414,7 @@ dec_dynrel_count (bfd_vma r_info,
   if ((info->shared
        && (must_be_dyn_reloc (info, r_type)
           || (h != NULL
-              && (!info->symbolic
+              && (!SYMBOLIC_BIND (info, h)
                   || h->root.type == bfd_link_hash_defweak
                   || !h->def_regular))))
       || (ELIMINATE_COPY_RELOCS
@@ -6863,43 +7427,66 @@ dec_dynrel_count (bfd_vma r_info,
     return TRUE;
 
   if (h != NULL)
-    pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
-  else
     {
-      if (sym_sec != NULL)
-       {
-         void *vpp = &elf_section_data (sym_sec)->local_dynrel;
-         pp = (struct ppc_dyn_relocs **) vpp;
-       }
-      else
-       {
-         void *vpp = &elf_section_data (sec)->local_dynrel;
-         pp = (struct ppc_dyn_relocs **) vpp;
-       }
+      struct elf_dyn_relocs *p;
+      struct elf_dyn_relocs **pp;
+      pp = &((struct ppc_link_hash_entry *) h)->dyn_relocs;
 
       /* elf_gc_sweep may have already removed all dyn relocs associated
-        with local syms for a given section.  Don't report a dynreloc
-        miscount.  */
-      if (*pp == NULL)
+        with local syms for a given section.  Also, symbol flags are
+        changed by elf_gc_sweep_symbol, confusing the test above.  Don't
+        report a dynreloc miscount.  */
+      if (*pp == NULL && info->gc_sections)
        return TRUE;
-    }
 
-  while ((p = *pp) != NULL)
+      while ((p = *pp) != NULL)
+       {
+         if (p->sec == sec)
+           {
+             if (!must_be_dyn_reloc (info, r_type))
+               p->pc_count -= 1;
+             p->count -= 1;
+             if (p->count == 0)
+               *pp = p->next;
+             return TRUE;
+           }
+         pp = &p->next;
+       }
+    }
+  else
     {
-      if (p->sec == sec)
+      struct ppc_dyn_relocs *p;
+      struct ppc_dyn_relocs **pp;
+      void *vpp;
+      bfd_boolean is_ifunc;
+
+      if (local_syms == NULL)
+       sym_sec = bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+      if (sym_sec == NULL)
+       sym_sec = sec;
+
+      vpp = &elf_section_data (sym_sec)->local_dynrel;
+      pp = (struct ppc_dyn_relocs **) vpp;
+
+      if (*pp == NULL && info->gc_sections)
+       return TRUE;
+
+      is_ifunc = ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC;
+      while ((p = *pp) != NULL)
        {
-         if (!must_be_dyn_reloc (info, r_type))
-           p->pc_count -= 1;
-         p->count -= 1;
-         if (p->count == 0)
-           *pp = p->next;
-         return TRUE;
+         if (p->sec == sec && p->ifunc == is_ifunc)
+           {
+             p->count -= 1;
+             if (p->count == 0)
+               *pp = p->next;
+             return TRUE;
+           }
+         pp = &p->next;
        }
-      pp = &p->next;
     }
 
-  (*_bfd_error_handler) (_("dynreloc miscount for %B, section %A"),
-                          sec->owner, sec);
+  info->callbacks->einfo (_("%P: dynreloc miscount for %B, section %A\n"),
+                         sec->owner, sec);
   bfd_set_error (bfd_error_bad_value);
   return FALSE;
 }
@@ -6935,7 +7522,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping)
       if (sec == NULL || sec->size == 0)
        continue;
 
-      if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+      if (sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
        continue;
 
       if (sec->output_section == bfd_abs_section_ptr)
@@ -7073,6 +7660,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping)
       if (need_edit || add_aux_fields)
        {
          Elf_Internal_Rela *write_rel;
+         Elf_Internal_Shdr *rel_hdr;
          bfd_byte *rptr, *wptr;
          bfd_byte *new_contents;
          bfd_boolean skip;
@@ -7227,7 +7815,7 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping)
                  if (!NO_OPD_RELOCS
                      && !info->relocatable
                      && !dec_dynrel_count (rel->r_info, sec, info,
-                                           NULL, h, sym_sec))
+                                           NULL, h, sym))
                    goto error_ret;
                }
              else
@@ -7252,9 +7840,8 @@ ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping)
 
          /* Fudge the header size too, as this is used later in
             elf_bfd_final_link if we are emitting relocs.  */
-         elf_section_data (sec)->rel_hdr.sh_size
-           = sec->reloc_count * elf_section_data (sec)->rel_hdr.sh_entsize;
-         BFD_ASSERT (elf_section_data (sec)->rel_hdr2 == NULL);
+         rel_hdr = _bfd_elf_single_rel_hdr (sec);
+         rel_hdr->sh_size = sec->reloc_count * rel_hdr->sh_entsize;
          some_edited = TRUE;
        }
       else if (elf_section_data (sec)->relocs != relstart)
@@ -7323,6 +7910,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)
@@ -7450,6 +8040,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
   bfd *ibfd;
   asection *sec;
   struct ppc_link_hash_table *htab;
+  unsigned char *toc_ref;
   int pass;
 
   if (info->relocatable || !info->executable)
@@ -7459,23 +8050,25 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
   if (htab == NULL)
     return FALSE;
 
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
-    {
-      Elf_Internal_Sym *locsyms = NULL;
-      asection *toc = bfd_get_section_by_name (ibfd, ".toc");
-      unsigned char *toc_ref = NULL;
-
-      /* Look at all the sections for this file.  Make two passes over
-        the relocs.  On the first pass, mark toc entries involved
-        with tls relocs, and check that tls relocs involved in
-        setting up a tls_get_addr call are indeed followed by such a
-        call.  If they are not, exclude them from the optimizations
-        done on the second pass.  */
-      for (pass = 0; pass < 2; ++pass)
+  /* Make two passes over the relocs.  On the first pass, mark toc
+     entries involved with tls relocs, and check that tls relocs
+     involved in setting up a tls_get_addr call are indeed followed by
+     such a call.  If they are not, we can't do any tls optimization.
+     On the second pass twiddle tls_mask flags to notify
+     relocate_section that optimization can be done, and adjust got
+     and plt refcounts.  */
+  toc_ref = NULL;
+  for (pass = 0; pass < 2; ++pass)
+    for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+      {
+       Elf_Internal_Sym *locsyms = NULL;
+       asection *toc = bfd_get_section_by_name (ibfd, ".toc");
+
        for (sec = ibfd->sections; sec != NULL; sec = sec->next)
          if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section))
            {
              Elf_Internal_Rela *relstart, *rel, *relend;
+             bfd_boolean found_tls_get_addr_arg = 0;
 
              /* Read the relocations.  */
              relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
@@ -7497,6 +8090,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                  bfd_boolean ok_tprel, is_local;
                  long toc_ref_index = 0;
                  int expecting_tls_get_addr = 0;
+                 bfd_boolean ret = FALSE;
 
                  r_symndx = ELF64_R_SYM (rel->r_info);
                  if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms,
@@ -7511,7 +8105,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                          && (elf_symtab_hdr (ibfd).contents
                              != (unsigned char *) locsyms))
                        free (locsyms);
-                     return FALSE;
+                     return ret;
                    }
 
                  if (h != NULL)
@@ -7522,7 +8116,10 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      else if (h->root.type == bfd_link_hash_undefweak)
                        value = 0;
                      else
-                       continue;
+                       {
+                         found_tls_get_addr_arg = 0;
+                         continue;
+                       }
                    }
                  else
                    /* Symbols referenced by TLS relocs must be of type
@@ -7549,11 +8146,34 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                    }
 
                  r_type = ELF64_R_TYPE (rel->r_info);
+                 /* If this section has old-style __tls_get_addr calls
+                    without marker relocs, then check that each
+                    __tls_get_addr call reloc is preceded by a reloc
+                    that conceivably belongs to the __tls_get_addr arg
+                    setup insn.  If we don't find matching arg setup
+                    relocs, don't do any tls optimization.  */
+                 if (pass == 0
+                     && sec->has_tls_get_addr_call
+                     && h != NULL
+                     && (h == &htab->tls_get_addr->elf
+                         || h == &htab->tls_get_addr_fd->elf)
+                     && !found_tls_get_addr_arg
+                     && is_branch_reloc (r_type))
+                   {
+                     info->callbacks->minfo (_("%H __tls_get_addr lost arg, "
+                                               "TLS optimization disabled\n"),
+                                             ibfd, sec, rel->r_offset);
+                     ret = TRUE;
+                     goto err_free_rel;
+                   }
+
+                 found_tls_get_addr_arg = 0;
                  switch (r_type)
                    {
                    case R_PPC64_GOT_TLSLD16:
                    case R_PPC64_GOT_TLSLD16_LO:
                      expecting_tls_get_addr = 1;
+                     found_tls_get_addr_arg = 1;
                      /* Fall thru */
 
                    case R_PPC64_GOT_TLSLD16_HI:
@@ -7573,6 +8193,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                    case R_PPC64_GOT_TLSGD16:
                    case R_PPC64_GOT_TLSGD16_LO:
                      expecting_tls_get_addr = 1;
+                     found_tls_get_addr_arg = 1;
                      /* Fall thru */
 
                    case R_PPC64_GOT_TLSGD16_HI:
@@ -7601,11 +8222,14 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                        }
                      continue;
 
-                   case R_PPC64_TOC16:
-                   case R_PPC64_TOC16_LO:
-                   case R_PPC64_TLS:
                    case R_PPC64_TLSGD:
                    case R_PPC64_TLSLD:
+                     found_tls_get_addr_arg = 1;
+                     /* Fall thru */
+
+                   case R_PPC64_TLS:
+                   case R_PPC64_TOC16:
+                   case R_PPC64_TOC16_LO:
                      if (sym_sec == NULL || sym_sec != toc)
                        continue;
 
@@ -7614,18 +8238,17 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                         case of R_PPC64_TLS, and after checking for
                         tls_get_addr for the TOC16 relocs.  */
                      if (toc_ref == NULL)
-                       {
-                         toc_ref = bfd_zmalloc (toc->size / 8);
-                         if (toc_ref == NULL)
-                           goto err_free_rel;
-                       }
+                       toc_ref = bfd_zmalloc (toc->output_section->rawsize / 8);
+                     if (toc_ref == NULL)
+                       goto err_free_rel;
+
                      if (h != NULL)
                        value = h->root.u.def.value;
                      else
                        value = sym->st_value;
                      value += rel->r_addend;
                      BFD_ASSERT (value < toc->size && value % 8 == 0);
-                     toc_ref_index = value / 8;
+                     toc_ref_index = (value + toc->output_offset) / 8;
                      if (r_type == R_PPC64_TLS
                          || r_type == R_PPC64_TLSGD
                          || r_type == R_PPC64_TLSLD)
@@ -7646,7 +8269,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      if (pass == 0
                          || sec != toc
                          || toc_ref == NULL
-                         || !toc_ref[rel->r_offset / 8])
+                         || !toc_ref[(rel->r_offset + toc->output_offset) / 8])
                        continue;
                      if (ok_tprel)
                        {
@@ -7661,7 +8284,7 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      if (pass == 0
                          || sec != toc
                          || toc_ref == NULL
-                         || !toc_ref[rel->r_offset / 8])
+                         || !toc_ref[(rel->r_offset + toc->output_offset) / 8])
                        continue;
                      if (rel + 1 < relend
                          && (rel[1].r_info
@@ -7713,8 +8336,13 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                                                     rel, ibfd);
                              if (retval == 0)
                                goto err_free_rel;
-                             if (retval > 1 && toc_tls != NULL)
-                               toc_ref[toc_ref_index] = 1;
+                             if (toc_tls != NULL)
+                               {
+                                 if ((*toc_tls & (TLS_GD | TLS_LD)) != 0)
+                                   found_tls_get_addr_arg = 1;
+                                 if (retval > 1)
+                                   toc_ref[toc_ref_index] = 1;
+                               }
                            }
                          continue;
                        }
@@ -7725,9 +8353,12 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      /* Uh oh, we didn't find the expected call.  We
                         could just mark this symbol to exclude it
                         from tls optimization but it's safer to skip
-                        the entire section.  */
-                     sec->has_tls_reloc = 0;
-                     break;
+                        the entire optimization.  */
+                     info->callbacks->minfo (_("%H arg lost __tls_get_addr, "
+                                               "TLS optimization disabled\n"),
+                                             ibfd, sec, rel->r_offset);
+                     ret = TRUE;
+                     goto err_free_rel;
                    }
 
                  if (expecting_tls_get_addr && htab->tls_get_addr != NULL)
@@ -7794,13 +8425,13 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                      /* If we got rid of a DTPMOD/DTPREL reloc pair then
                         we'll lose one or two dyn relocs.  */
                      if (!dec_dynrel_count (rel->r_info, sec, info,
-                                            NULL, h, sym_sec))
+                                            NULL, h, sym))
                        return FALSE;
 
                      if (tls_set == (TLS_EXPLICIT | TLS_GD))
                        {
                          if (!dec_dynrel_count ((rel + 1)->r_info, sec, info,
-                                                NULL, h, sym_sec))
+                                                NULL, h, sym))
                            return FALSE;
                        }
                    }
@@ -7813,18 +8444,18 @@ ppc64_elf_tls_optimize (struct bfd_link_info *info)
                free (relstart);
            }
 
-      if (toc_ref != NULL)
-       free (toc_ref);
+       if (locsyms != NULL
+           && (elf_symtab_hdr (ibfd).contents != (unsigned char *) locsyms))
+         {
+           if (!info->keep_memory)
+             free (locsyms);
+           else
+             elf_symtab_hdr (ibfd).contents = (unsigned char *) locsyms;
+         }
+      }
 
-      if (locsyms != NULL
-         && (elf_symtab_hdr (ibfd).contents != (unsigned char *) locsyms))
-       {
-         if (!info->keep_memory)
-           free (locsyms);
-         else
-           elf_symtab_hdr (ibfd).contents = (unsigned char *) locsyms;
-       }
-    }
+  if (toc_ref != NULL)
+    free (toc_ref);
   return TRUE;
 }
 
@@ -7850,12 +8481,6 @@ adjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
   struct adjust_toc_info *toc_inf = (struct adjust_toc_info *) inf;
   unsigned long i;
 
-  if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
-
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   if (h->root.type != bfd_link_hash_defined
       && h->root.type != bfd_link_hash_defweak)
     return TRUE;
@@ -7890,6 +8515,32 @@ adjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
   return TRUE;
 }
 
+/* Return TRUE iff INSN is one we expect on a _LO variety toc/got reloc.  */
+
+static bfd_boolean
+ok_lo_toc_insn (unsigned int insn)
+{
+  return ((insn & (0x3f << 26)) == 14u << 26 /* addi */
+         || (insn & (0x3f << 26)) == 32u << 26 /* lwz */
+         || (insn & (0x3f << 26)) == 34u << 26 /* lbz */
+         || (insn & (0x3f << 26)) == 36u << 26 /* stw */
+         || (insn & (0x3f << 26)) == 38u << 26 /* stb */
+         || (insn & (0x3f << 26)) == 40u << 26 /* lhz */
+         || (insn & (0x3f << 26)) == 42u << 26 /* lha */
+         || (insn & (0x3f << 26)) == 44u << 26 /* sth */
+         || (insn & (0x3f << 26)) == 46u << 26 /* lmw */
+         || (insn & (0x3f << 26)) == 47u << 26 /* stmw */
+         || (insn & (0x3f << 26)) == 48u << 26 /* lfs */
+         || (insn & (0x3f << 26)) == 50u << 26 /* lfd */
+         || (insn & (0x3f << 26)) == 52u << 26 /* stfs */
+         || (insn & (0x3f << 26)) == 54u << 26 /* stfd */
+         || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */
+             && (insn & 3) != 1)
+         || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */
+             && ((insn & 3) == 0 || (insn & 3) == 3))
+         || (insn & (0x3f << 26)) == 12u << 26 /* addic */);
+}
+
 /* Examine all relocs referencing .toc sections in order to remove
    unused .toc entries.  */
 
@@ -7907,7 +8558,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
       asection *toc, *sec;
       Elf_Internal_Shdr *symtab_hdr;
       Elf_Internal_Sym *local_syms;
-      Elf_Internal_Rela *relstart, *rel;
+      Elf_Internal_Rela *relstart, *rel, *toc_relocs;
       unsigned long *skip, *drop;
       unsigned char *used;
       unsigned char *keep, last, some_unused;
@@ -7918,10 +8569,11 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
       toc = bfd_get_section_by_name (ibfd, ".toc");
       if (toc == NULL
          || toc->size == 0
-         || toc->sec_info_type == ELF_INFO_TYPE_JUST_SYMS
-         || elf_discarded_section (toc))
+         || toc->sec_info_type == SEC_INFO_TYPE_JUST_SYMS
+         || discarded_section (toc))
        continue;
 
+      toc_relocs = NULL;
       local_syms = NULL;
       symtab_hdr = &elf_symtab_hdr (ibfd);
 
@@ -7931,7 +8583,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        {
          if (sec->reloc_count == 0
-             || !elf_discarded_section (sec)
+             || !discarded_section (sec)
              || get_opd_info (sec)
              || (sec->flags & SEC_ALLOC) == 0
              || (sec->flags & SEC_DEBUGGING) != 0)
@@ -8011,18 +8663,18 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
         .  addi ry,rx,addr@toc@l
         when addr is within 2G of the toc pointer.  This then means
         that the word storing "addr" in the toc is no longer needed.  */
-        
+
       if (!ppc64_elf_tdata (ibfd)->has_small_toc_reloc
          && toc->output_section->rawsize < (bfd_vma) 1 << 31
          && toc->reloc_count != 0)
        {
          /* Read toc relocs.  */
-         relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
-                                               info->keep_memory);
-         if (relstart == NULL)
+         toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
+                                                 info->keep_memory);
+         if (toc_relocs == NULL)
            goto error_ret;
 
-         for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
+         for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
            {
              enum elf_ppc64_reloc_type r_type;
              unsigned long r_symndx;
@@ -8040,7 +8692,11 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                              r_symndx, ibfd))
                goto error_ret;
 
-             if (!SYMBOL_CALLS_LOCAL (info, h))
+             if (sym_sec == NULL
+                 || discarded_section (sym_sec))
+               continue;
+
+             if (!SYMBOL_REFERENCES_LOCAL (info, h))
                continue;
 
              if (h != NULL)
@@ -8078,11 +8734,8 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                }
 
              skip[rel->r_offset >> 3]
-               |= can_optimize | ((rel - relstart) << 2);
+               |= can_optimize | ((rel - toc_relocs) << 2);
            }
-
-         if (elf_section_data (toc)->relocs != relstart)
-           free (relstart);
        }
 
       if (skip == NULL)
@@ -8099,6 +8752,9 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
              && relstart != NULL
              && elf_section_data (sec)->relocs != relstart)
            free (relstart);
+         if (toc_relocs != NULL
+             && elf_section_data (toc)->relocs != toc_relocs)
+           free (toc_relocs);
          if (skip != NULL)
            free (skip);
          return FALSE;
@@ -8117,7 +8773,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
          int repeat;
 
          if (sec->reloc_count == 0
-             || elf_discarded_section (sec)
+             || discarded_section (sec)
              || get_opd_info (sec)
              || (sec->flags & SEC_ALLOC) == 0
              || (sec->flags & SEC_DEBUGGING) != 0)
@@ -8129,91 +8785,156 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
            goto error_ret;
 
          /* Mark toc entries referenced as used.  */
-         repeat = 0;
          do
-           for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
-             {
-               enum elf_ppc64_reloc_type r_type;
-               unsigned long r_symndx;
-               asection *sym_sec;
-               struct elf_link_hash_entry *h;
-               Elf_Internal_Sym *sym;
-               bfd_vma val;
-
-               r_type = ELF64_R_TYPE (rel->r_info);
-               switch (r_type)
-                 {
-                 case R_PPC64_TOC16:
-                 case R_PPC64_TOC16_LO:
-                 case R_PPC64_TOC16_HI:
-                 case R_PPC64_TOC16_HA:
-                 case R_PPC64_TOC16_DS:
-                 case R_PPC64_TOC16_LO_DS:
-                   /* In case we're taking addresses of toc entries.  */
-                 case R_PPC64_ADDR64:
-                   break;
+           {
+             repeat = 0;
+             for (rel = relstart; rel < relstart + sec->reloc_count; ++rel)
+               {
+                 enum elf_ppc64_reloc_type r_type;
+                 unsigned long r_symndx;
+                 asection *sym_sec;
+                 struct elf_link_hash_entry *h;
+                 Elf_Internal_Sym *sym;
+                 bfd_vma val;
+                 enum {no_check, check_lo, check_ha} insn_check;
 
-                 default:
-                   continue;
-                 }
+                 r_type = ELF64_R_TYPE (rel->r_info);
+                 switch (r_type)
+                   {
+                   default:
+                     insn_check = no_check;
+                     break;
 
-               r_symndx = ELF64_R_SYM (rel->r_info);
-               if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
-                               r_symndx, ibfd))
-                 {
-                   free (used);
-                   goto error_ret;
-                 }
+                   case R_PPC64_GOT_TLSLD16_HA:
+                   case R_PPC64_GOT_TLSGD16_HA:
+                   case R_PPC64_GOT_TPREL16_HA:
+                   case R_PPC64_GOT_DTPREL16_HA:
+                   case R_PPC64_GOT16_HA:
+                   case R_PPC64_TOC16_HA:
+                     insn_check = check_ha;
+                     break;
 
-               if (sym_sec != toc)
-                 continue;
+                   case R_PPC64_GOT_TLSLD16_LO:
+                   case R_PPC64_GOT_TLSGD16_LO:
+                   case R_PPC64_GOT_TPREL16_LO_DS:
+                   case R_PPC64_GOT_DTPREL16_LO_DS:
+                   case R_PPC64_GOT16_LO:
+                   case R_PPC64_GOT16_LO_DS:
+                   case R_PPC64_TOC16_LO:
+                   case R_PPC64_TOC16_LO_DS:
+                     insn_check = check_lo;
+                     break;
+                   }
 
-               if (h != NULL)
-                 val = h->root.u.def.value;
-               else
-                 val = sym->st_value;
-               val += rel->r_addend;
+                 if (insn_check != no_check)
+                   {
+                     bfd_vma off = rel->r_offset & ~3;
+                     unsigned char buf[4];
+                     unsigned int insn;
 
-               if (val >= toc->size)
-                 continue;
+                     if (!bfd_get_section_contents (ibfd, sec, buf, off, 4))
+                       {
+                         free (used);
+                         goto error_ret;
+                       }
+                     insn = bfd_get_32 (ibfd, buf);
+                     if (insn_check == check_lo
+                         ? !ok_lo_toc_insn (insn)
+                         : ((insn & ((0x3f << 26) | 0x1f << 16))
+                            != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */))
+                       {
+                         char str[12];
+
+                         ppc64_elf_tdata (ibfd)->unexpected_toc_insn = 1;
+                         sprintf (str, "%#08x", insn);
+                         info->callbacks->einfo
+                           (_("%P: %H: toc optimization is not supported for"
+                              " %s instruction.\n"),
+                            ibfd, sec, rel->r_offset & ~3, str);
+                       }
+                   }
 
-               if ((skip[val >> 3] & can_optimize) != 0)
-                 {
-                   bfd_vma off;
-                   unsigned char opc;
+                 switch (r_type)
+                   {
+                   case R_PPC64_TOC16:
+                   case R_PPC64_TOC16_LO:
+                   case R_PPC64_TOC16_HI:
+                   case R_PPC64_TOC16_HA:
+                   case R_PPC64_TOC16_DS:
+                   case R_PPC64_TOC16_LO_DS:
+                     /* In case we're taking addresses of toc entries.  */
+                   case R_PPC64_ADDR64:
+                     break;
 
-                   switch (r_type)
-                     {
-                     case R_PPC64_TOC16_HA:
-                       break;
+                   default:
+                     continue;
+                   }
 
-                     case R_PPC64_TOC16_LO_DS:
-                       off = rel->r_offset + (bfd_big_endian (ibfd) ? -2 : 3);
-                       if (!bfd_get_section_contents (ibfd, sec, &opc, off, 1))
-                         return FALSE;
-                       if ((opc & (0x3f << 2)) == (58u << 2))
+                 r_symndx = ELF64_R_SYM (rel->r_info);
+                 if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+                                 r_symndx, ibfd))
+                   {
+                     free (used);
+                     goto error_ret;
+                   }
+
+                 if (sym_sec != toc)
+                   continue;
+
+                 if (h != NULL)
+                   val = h->root.u.def.value;
+                 else
+                   val = sym->st_value;
+                 val += rel->r_addend;
+
+                 if (val >= toc->size)
+                   continue;
+
+                 if ((skip[val >> 3] & can_optimize) != 0)
+                   {
+                     bfd_vma off;
+                     unsigned char opc;
+
+                     switch (r_type)
+                       {
+                       case R_PPC64_TOC16_HA:
                          break;
-                       /* Fall thru */
 
-                     default:
-                       /* Wrong sort of reloc, or not a ld.  We may
-                          as well clear ref_from_discarded too.  */
-                       skip[val >> 3] = 0;
-                     }
-                 }
+                       case R_PPC64_TOC16_LO_DS:
+                         off = rel->r_offset;
+                         off += (bfd_big_endian (ibfd) ? -2 : 3);
+                         if (!bfd_get_section_contents (ibfd, sec, &opc,
+                                                        off, 1))
+                           {
+                             free (used);
+                             goto error_ret;
+                           }
+                         if ((opc & (0x3f << 2)) == (58u << 2))
+                           break;
+                         /* Fall thru */
 
-               /* For the toc section, we only mark as used if
-                  this entry itself isn't unused.  */
-               if (sec == toc
-                   && !used[val >> 3]
-                   && (used[rel->r_offset >> 3]
-                       || !(skip[rel->r_offset >> 3] & ref_from_discarded)))
-                 /* Do all the relocs again, to catch reference
-                    chains.  */
-                 repeat = 1;
-
-               used[val >> 3] = 1;
-             }
+                       default:
+                         /* Wrong sort of reloc, or not a ld.  We may
+                            as well clear ref_from_discarded too.  */
+                         skip[val >> 3] = 0;
+                       }
+                   }
+
+                 if (sec != toc)
+                   used[val >> 3] = 1;
+                 /* For the toc section, we only mark as used if this
+                    entry itself isn't unused.  */
+                 else if ((used[rel->r_offset >> 3]
+                           || !(skip[rel->r_offset >> 3] & ref_from_discarded))
+                          && !used[val >> 3])
+                   {
+                     /* Do all the relocs again, to catch reference
+                        chains.  */
+                     repeat = 1;
+                     used[val >> 3] = 1;
+                   }
+               }
+           }
          while (repeat);
 
          if (elf_section_data (sec)->relocs != relstart)
@@ -8234,7 +8955,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                some_unused = 1;
              last = 0;
            }
-         else if (*drop)
+         else if ((*drop & ref_from_discarded) != 0)
            {
              some_unused = 1;
              last = ref_from_discarded;
@@ -8280,7 +9001,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
          for (sec = ibfd->sections; sec != NULL; sec = sec->next)
            {
              if (sec->reloc_count == 0
-                 || elf_discarded_section (sec))
+                 || discarded_section (sec))
                continue;
 
              relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
@@ -8338,7 +9059,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                  else if ((skip[val >> 3] & can_optimize) != 0)
                    {
                      Elf_Internal_Rela *tocrel
-                       = elf_section_data (toc)->relocs + (skip[val >> 3] >> 2);
+                       = toc_relocs + (skip[val >> 3] >> 2);
                      unsigned long tsym = ELF64_R_SYM (tocrel->r_info);
 
                      switch (r_type)
@@ -8352,7 +9073,15 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                          break;
 
                        default:
-                         abort ();
+                         if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
+                           ppc_howto_init ();
+                         info->callbacks->einfo
+                           (_("%P: %H: %s references "
+                              "optimized away TOC entry\n"),
+                            ibfd, sec, rel->r_offset,
+                            ppc64_elf_howto_table[r_type]->name);
+                         bfd_set_error (bfd_error_bad_value);
+                         goto error_ret;
                        }
                      rel->r_addend = tocrel->r_addend;
                      elf_section_data (sec)->relocs = relstart;
@@ -8372,34 +9101,35 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
 
          /* We shouldn't have local or global symbols defined in the TOC,
             but handle them anyway.  */
-         for (sym = local_syms;
-              sym < local_syms + symtab_hdr->sh_info;
-              ++sym)
-           if (sym->st_value != 0
-               && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc)
-             {
-               unsigned long i;
+         if (local_syms != NULL)
+           for (sym = local_syms;
+                sym < local_syms + symtab_hdr->sh_info;
+                ++sym)
+             if (sym->st_value != 0
+                 && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc)
+               {
+                 unsigned long i;
 
-               if (sym->st_value > toc->rawsize)
-                 i = toc->rawsize >> 3;
-               else
-                 i = sym->st_value >> 3;
+                 if (sym->st_value > toc->rawsize)
+                   i = toc->rawsize >> 3;
+                 else
+                   i = sym->st_value >> 3;
 
-               if ((skip[i] & (ref_from_discarded | can_optimize)) != 0)
-                 {
-                   if (local_toc_syms)
-                     (*_bfd_error_handler)
-                       (_("%s defined on removed toc entry"),
-                        bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL));
-                   do
-                     ++i;
-                   while ((skip[i] & (ref_from_discarded | can_optimize)));
-                   sym->st_value = (bfd_vma) i << 3;
-                 }
+                 if ((skip[i] & (ref_from_discarded | can_optimize)) != 0)
+                   {
+                     if (local_toc_syms)
+                       (*_bfd_error_handler)
+                         (_("%s defined on removed toc entry"),
+                          bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL));
+                     do
+                       ++i;
+                     while ((skip[i] & (ref_from_discarded | can_optimize)));
+                     sym->st_value = (bfd_vma) i << 3;
+                   }
 
-               sym->st_value -= skip[i];
-               symtab_hdr->contents = (unsigned char *) local_syms;
-             }
+                 sym->st_value -= skip[i];
+                 symtab_hdr->contents = (unsigned char *) local_syms;
+               }
 
          /* Adjust any global syms defined in this toc input section.  */
          if (toc_inf.global_toc_syms)
@@ -8413,18 +9143,19 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
 
          if (toc->reloc_count != 0)
            {
+             Elf_Internal_Shdr *rel_hdr;
              Elf_Internal_Rela *wrel;
              bfd_size_type sz;
 
-             /* Read toc relocs.  */
-             relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
-                                                   TRUE);
-             if (relstart == NULL)
+             /* Remove unused toc relocs, and adjust those we keep.  */
+             if (toc_relocs == NULL)
+               toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
+                                                       info->keep_memory);
+             if (toc_relocs == NULL)
                goto error_ret;
 
-             /* Remove unused toc relocs, and adjust those we keep.  */
-             wrel = relstart;
-             for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
+             wrel = toc_relocs;
+             for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
                if ((skip[rel->r_offset >> 3]
                     & (ref_from_discarded | can_optimize)) == 0)
                  {
@@ -8437,12 +9168,16 @@ ppc64_elf_edit_toc (struct bfd_link_info *info)
                                            &local_syms, NULL, NULL))
                  goto error_ret;
 
-             toc->reloc_count = wrel - relstart;
-             sz = elf_section_data (toc)->rel_hdr.sh_entsize;
-             elf_section_data (toc)->rel_hdr.sh_size = toc->reloc_count * sz;
-             BFD_ASSERT (elf_section_data (toc)->rel_hdr2 == NULL);
+             elf_section_data (toc)->relocs = toc_relocs;
+             toc->reloc_count = wrel - toc_relocs;
+             rel_hdr = _bfd_elf_single_rel_hdr (toc);
+             sz = rel_hdr->sh_entsize;
+             rel_hdr->sh_size = toc->reloc_count * sz;
            }
        }
+      else if (toc_relocs != NULL
+              && elf_section_data (toc)->relocs != toc_relocs)
+       free (toc_relocs);
 
       if (local_syms != NULL
          && symtab_hdr->contents != (unsigned char *) local_syms)
@@ -8488,19 +9223,18 @@ allocate_got (struct elf_link_hash_entry *h,
   got->size += entsize;
 
   dyn = htab->elf.dynamic_sections_created;
-  if ((info->shared
-       || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
-           && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-               || h->root.type != bfd_link_hash_undefweak))
+  if (h->type == STT_GNU_IFUNC)
     {
-      asection *relgot = ppc64_elf_tdata (gent->owner)->relgot;
-      relgot->size += rentsize;
+      htab->elf.irelplt->size += rentsize;
+      htab->got_reli_size += rentsize;
     }
-  else if (h->type == STT_GNU_IFUNC)
+  else if ((info->shared
+           || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              || h->root.type != bfd_link_hash_undefweak))
     {
-      asection *relgot = htab->reliplt;
+      asection *relgot = ppc64_elf_tdata (gent->owner)->relgot;
       relgot->size += rentsize;
-      htab->got_reli_size += rentsize;
     }
 }
 
@@ -8534,15 +9268,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   struct ppc_link_hash_table *htab;
   asection *s;
   struct ppc_link_hash_entry *eh;
-  struct ppc_dyn_relocs *p;
+  struct elf_dyn_relocs *p;
   struct got_entry **pgent, *gent;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   info = (struct bfd_link_info *) inf;
   htab = ppc_hash_table (info);
   if (htab == NULL)
@@ -8561,35 +9292,40 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            if (!htab->elf.dynamic_sections_created
                || h->dynindx == -1)
              {
-               s = htab->iplt;
+               s = htab->elf.iplt;
                pent->plt.offset = s->size;
-               s->size += PLT_ENTRY_SIZE;
-               s = htab->reliplt;
+               s->size += PLT_ENTRY_SIZE (htab);
+               s = htab->elf.irelplt;
              }
            else
              {
                /* If this is the first .plt entry, make room for the special
                   first entry.  */
-               s = htab->plt;
+               s = htab->elf.splt;
                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;
+               s = htab->elf.srelplt;
              }
            s->size += sizeof (Elf64_External_Rela);
            doneone = TRUE;
@@ -8698,7 +9434,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
         then they should avoid writing weird assembly.  */
       if (SYMBOL_CALLS_LOCAL (info, h))
        {
-         struct ppc_dyn_relocs **pp;
+         struct elf_dyn_relocs **pp;
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
            {
@@ -8767,39 +9503,73 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   for (p = eh->dyn_relocs; p != NULL; p = p->next)
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
-      if (!htab->elf.dynamic_sections_created)
-       sreloc = htab->reliplt;
+      if (eh->elf.type == STT_GNU_IFUNC)
+       sreloc = htab->elf.irelplt;
       sreloc->size += p->count * sizeof (Elf64_External_Rela);
     }
 
   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 ppc_dyn_relocs *p;
+  struct bfd_link_info *info;
+  struct ppc_link_hash_table *htab;
+  struct plt_entry *pent;
+  asection *s;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
 
-  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->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)
+      {
+       /* 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.  */
 
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       {
-         struct bfd_link_info *info = inf;
+static bfd_boolean
+maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
+{
+  if (h->root.type == bfd_link_hash_indirect)
+    return TRUE;
 
-         info->flags |= DF_TEXTREL;
+  if (readonly_dynrelocs (h))
+    {
+      ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
 
-         /* Not an error, just cut short the traversal.  */
-         return FALSE;
-       }
+      /* Not an error, just cut short the traversal.  */
+      return FALSE;
     }
   return TRUE;
 }
@@ -8807,7 +9577,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;
@@ -8830,7 +9600,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
            abort ();
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
@@ -8849,7 +9619,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       unsigned char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
-      asection *srel;
 
       if (!is_ppc64_elf (ibfd))
        continue;
@@ -8870,9 +9639,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                }
              else if (p->count != 0)
                {
-                 srel = elf_section_data (p->sec)->sreloc;
-                 if (!htab->elf.dynamic_sections_created)
-                   srel = htab->reliplt;
+                 asection *srel = elf_section_data (p->sec)->sreloc;
+                 if (p->ifunc)
+                   srel = htab->elf.irelplt;
                  srel->size += p->count * sizeof (Elf64_External_Rela);
                  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
                    info->flags |= DF_TEXTREL;
@@ -8891,7 +9660,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       end_local_plt = local_plt + locsymcount;
       lgot_masks = (unsigned char *) end_local_plt;
       s = ppc64_elf_tdata (ibfd)->got;
-      srel = ppc64_elf_tdata (ibfd)->relgot;
       for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
        {
          struct got_entry **pent, *ent;
@@ -8907,19 +9675,25 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                  }
                else
                  {
-                   unsigned int num = 1;
+                   unsigned int ent_size = 8;
+                   unsigned int rel_size = sizeof (Elf64_External_Rela);
+
                    ent->got.offset = s->size;
                    if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
-                     num = 2;
-                   s->size += num * 8;
-                   if (info->shared)
-                     srel->size += num * sizeof (Elf64_External_Rela);
-                   else if ((*lgot_masks & PLT_IFUNC) != 0)
                      {
-                       htab->reliplt->size
-                         += num * sizeof (Elf64_External_Rela);
-                       htab->got_reli_size
-                         += num * sizeof (Elf64_External_Rela);
+                       ent_size *= 2;
+                       rel_size *= 2;
+                     }
+                   s->size += ent_size;
+                   if ((*lgot_masks & PLT_IFUNC) != 0)
+                     {
+                       htab->elf.irelplt->size += rel_size;
+                       htab->got_reli_size += rel_size;
+                     }
+                   else if (info->shared)
+                     {
+                       asection *srel = ppc64_elf_tdata (ibfd)->relgot;
+                       srel->size += rel_size;
                      }
                    pent = &ent->next;
                  }
@@ -8936,11 +9710,11 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          for (ent = *local_plt; ent != NULL; ent = ent->next)
            if (ent->plt.refcount > 0)
              {
-               s = htab->iplt;
+               s = htab->elf.iplt;
                ent->plt.offset = s->size;
-               s->size += PLT_ENTRY_SIZE;
+               s->size += PLT_ENTRY_SIZE (htab);
 
-               htab->reliplt->size += sizeof (Elf64_External_Rela);
+               htab->elf.irelplt->size += sizeof (Elf64_External_Rela);
              }
            else
              ent->plt.offset = (bfd_vma) -1;
@@ -8950,6 +9724,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)
@@ -8997,20 +9777,26 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (s == htab->brlt || s == htab->relbrlt)
        /* These haven't been allocated yet;  don't strip.  */
        continue;
-      else if (s == htab->got
-              || s == htab->plt
-              || s == htab->iplt
+      else if (s == htab->elf.sgot
+              || s == htab->elf.splt
+              || s == htab->elf.iplt
               || s == htab->glink
               || s == htab->dynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
+      else if (s == htab->glink_eh_frame)
+       {
+         if (!bfd_is_abs_section (s->output_section))
+           /* Not sized yet.  */
+           continue;
+       }
       else if (CONST_STRNEQ (s->name, ".rela"))
        {
          if (s->size != 0)
            {
-             if (s != htab->relplt)
+             if (s != htab->elf.srelplt)
                relocs = TRUE;
 
              /* We use the reloc_count field as a counter if we need
@@ -9060,7 +9846,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        continue;
 
       s = ppc64_elf_tdata (ibfd)->got;
-      if (s != NULL && s != htab->got)
+      if (s != NULL && s != htab->elf.sgot)
        {
          if (s->size == 0)
            s->flags |= SEC_EXCLUDE;
@@ -9089,6 +9875,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
@@ -9103,7 +9891,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
            return FALSE;
        }
 
-      if (htab->plt != NULL && htab->plt->size != 0)
+      if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
        {
          if (!add_dynamic_entry (DT_PLTGOT, 0)
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
@@ -9113,18 +9901,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)
        {
@@ -9136,7 +9927,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)
            {
@@ -9150,6 +9941,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
@@ -9157,7 +9961,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;
@@ -9226,7 +10031,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;
@@ -9234,86 +10039,244 @@ ppc_type_of_stub (asection *input_sec,
   return ppc_stub_none;
 }
 
-/* Build a .plt call stub.  */
+/* With power7 weakly ordered memory model, it is possible for ld.so
+   to update a plt entry in one thread and have another thread see a
+   stale zero toc entry.  To avoid this we need some sort of acquire
+   barrier in the call stub.  One solution is to make the load of the
+   toc word seem to appear to depend on the load of the function entry
+   word.  Another solution is to test for r2 being zero, and branch to
+   the appropriate glink entry if so.
+
+   .   fake dep barrier        compare
+   .   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>
+
+   The solution involving the compare turns out to be faster, so
+   that's what we use unless the branch won't reach.  */
+
+#define ALWAYS_USE_FAKE_DEP 0
+#define ALWAYS_EMIT_R2SAVE 0
 
-static inline bfd_byte *
-build_plt_stub (bfd *obfd, bfd_byte *p, int offset, Elf_Internal_Rela *r)
-{
 #define PPC_LO(v) ((v) & 0xffff)
 #define PPC_HI(v) (((v) >> 16) & 0xffff)
 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
 
+static inline unsigned int
+plt_stub_size (struct ppc_link_hash_table *htab,
+              struct ppc_stub_hash_entry *stub_entry,
+              bfd_vma 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)
+      && !htab->no_tls_get_addr_opt)
+    size += 13 * 4;
+  return size;
+}
+
+/* If this stub would cross fewer 2**plt_stub_align boundaries if we align,
+   then return the padding needed to do so.  */
+static inline unsigned int
+plt_stub_pad (struct ppc_link_hash_table *htab,
+             struct ppc_stub_hash_entry *stub_entry,
+             bfd_vma plt_off)
+{
+  int stub_align = 1 << htab->plt_stub_align;
+  unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
+  bfd_vma stub_off = stub_entry->stub_sec->size;
+
+  if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
+      > (stub_size & -stub_align))
+    return stub_align - (stub_off & (stub_align - 1));
+  return 0;
+}
+
+/* Build a .plt call stub.  */
+
+static inline bfd_byte *
+build_plt_stub (struct ppc_link_hash_table *htab,
+               struct ppc_stub_hash_entry *stub_entry,
+               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
+              || stub_entry->h == htab->tls_get_addr)
+          && !htab->no_tls_get_addr_opt))
+    {
+      bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
+      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;
+
+      if (pltindex > 32768)
+       glinkoff += (pltindex - 32768) * 4;
+      to = (glinkoff
+           + htab->glink->output_offset
+           + htab->glink->output_section->vma);
+      from = (p - stub_entry->stub_sec->contents
+             + 4 * (ALWAYS_EMIT_R2SAVE
+                    || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+             + 4 * (PPC_HA (offset) != 0)
+             + 4 * (PPC_HA (offset + 8 + 8 * plt_static_chain)
+                    != PPC_HA (offset))
+             + 4 * (plt_static_chain != 0)
+             + 20
+             + stub_entry->stub_sec->output_offset
+             + stub_entry->stub_sec->output_section->vma);
+      cmp_branch_off = to - from;
+      use_fake_dep = cmp_branch_off + (1 << 25) >= (1 << 26);
+    }
+
   if (PPC_HA (offset) != 0)
     {
       if (r != NULL)
        {
+         if (ALWAYS_EMIT_R2SAVE
+             || 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_HA);
-         r[1].r_offset = r[0].r_offset + 8;
+         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 + 16) != 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;
-             r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
-             r[2].r_addend = r[0].r_addend + 8;
-             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 (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
+               {
+                 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;
+                   }
+               }
            }
        }
-      bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p),    p += 4;
-      bfd_put_32 (obfd, STD_R2_40R1, p),                       p += 4;
-      bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p),     p += 4;
-      if (PPC_HA (offset + 16) != PPC_HA (offset))
+      if (ALWAYS_EMIT_R2SAVE
+         || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+       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;
-      bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset + 8), p),  p += 4;
-      bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset + 16), p),        p += 4;
-      bfd_put_32 (obfd, BCTR, p),                              p += 4;
+      bfd_put_32 (obfd, MTCTR_R12, p),                         p += 4;
+      if (plt_load_toc)
+       {
+         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;
+       }
     }
   else
     {
       if (r != NULL)
        {
-         r[0].r_offset += 4;
+         if (ALWAYS_EMIT_R2SAVE
+             || 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 + 16) != PPC_HA (offset))
-           {
-             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
+         if (plt_load_toc)
            {
-             r[1].r_offset = r[0].r_offset + 8;
-             r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
-             r[1].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_DS);
-             r[2].r_addend = r[0].r_addend + 8;
+             if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
+               {
+                 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;
+                   }
+               }
            }
        }
-      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 + 16) != PPC_HA (offset))
+      if (ALWAYS_EMIT_R2SAVE
+         || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+       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;
-      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;
-      bfd_put_32 (obfd, BCTR, p),                              p += 4;
+      bfd_put_32 (obfd, MTCTR_R12, p),                         p += 4;
+      if (plt_load_toc)
+       {
+         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_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;
+      bfd_put_32 (obfd, B_DOT | (cmp_branch_off & 0x3fffffc), p), p += 4;
     }
+  else
+    bfd_put_32 (obfd, BCTR, p),                                        p += 4;
   return p;
 }
 
@@ -9326,17 +10289,18 @@ build_plt_stub (bfd *obfd, bfd_byte *p, int offset, Elf_Internal_Rela *r)
 #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 *
-build_tls_get_addr_stub (bfd *obfd, bfd_byte *p, int offset,
-                        Elf_Internal_Rela *r)
+build_tls_get_addr_stub (struct ppc_link_hash_table *htab,
+                        struct ppc_stub_hash_entry *stub_entry,
+                        bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
 {
+  bfd *obfd = htab->stub_bfd;
+
   bfd_put_32 (obfd, LD_R11_0R3 + 0, p),                p += 4;
   bfd_put_32 (obfd, LD_R12_0R3 + 8, p),                p += 4;
   bfd_put_32 (obfd, MR_R0_R3, p),              p += 4;
@@ -9345,15 +10309,15 @@ build_tls_get_addr_stub (bfd *obfd, bfd_byte *p, int offset,
   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 (obfd, p, offset, r);
+  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;
 
@@ -9376,9 +10340,13 @@ get_relocs (asection *sec, int count)
       if (relocs == NULL)
        return NULL;
       elfsec_data->relocs = relocs;
-      elfsec_data->rel_hdr.sh_size = (sec->reloc_count
-                                     * sizeof (Elf64_External_Rela));
-      elfsec_data->rel_hdr.sh_entsize = sizeof (Elf64_External_Rela);
+      elfsec_data->rela.hdr = bfd_zalloc (sec->owner,
+                                         sizeof (Elf_Internal_Shdr));
+      if (elfsec_data->rela.hdr == NULL)
+       return NULL;
+      elfsec_data->rela.hdr->sh_size = (sec->reloc_count
+                                       * sizeof (Elf64_External_Rela));
+      elfsec_data->rela.hdr->sh_entsize = sizeof (Elf64_External_Rela);
       sec->reloc_count = 0;
     }
   relocs += sec->reloc_count;
@@ -9386,6 +10354,40 @@ get_relocs (asection *sec, int count)
   return relocs;
 }
 
+static bfd_vma
+get_r2off (struct bfd_link_info *info,
+          struct ppc_stub_hash_entry *stub_entry)
+{
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+  bfd_vma r2off = htab->stub_group[stub_entry->target_section->id].toc_off;
+
+  if (r2off == 0)
+    {
+      /* 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;
+
+      if (strcmp (opd->name, ".opd") != 0
+         || opd->reloc_count != 0)
+       {
+         info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"),
+                                 stub_entry->h->elf.root.root.string);
+         bfd_set_error (bfd_error_bad_value);
+         return 0;
+       }
+      if (!bfd_get_section_contents (opd->owner, opd, buf, opd_off + 8, 8))
+       return 0;
+      r2off = bfd_get_64 (opd->owner, buf);
+      r2off -= elf_gp (info->output_bfd);
+    }
+  r2off -= htab->stub_group[stub_entry->id_sec->id].toc_off;
+  return r2off;
+}
+
 static bfd_boolean
 ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
@@ -9418,9 +10420,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
@@ -9430,11 +10434,14 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       size = 4;
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
        {
-         bfd_vma r2off;
+         bfd_vma r2off = get_r2off (info, stub_entry);
 
-         r2off = (htab->stub_group[stub_entry->target_section->id].toc_off
-                  - htab->stub_group[stub_entry->id_sec->id].toc_off);
-         bfd_put_32 (htab->stub_bfd, STD_R2_40R1, loc);
+         if (r2off == 0)
+           {
+             htab->stub_error = TRUE;
+             return FALSE;
+           }
+         bfd_put_32 (htab->stub_bfd, STD_R2_0R1 + STK_TOC (htab), loc);
          loc += 4;
          size = 12;
          if (PPC_HA (r2off) != 0)
@@ -9451,8 +10458,9 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (off + (1 << 25) >= (bfd_vma) (1 << 26))
        {
-         (*_bfd_error_handler) (_("long branch stub `%s' offset overflow"),
-                                stub_entry->root.string);
+         info->callbacks->einfo
+           (_("%P: long branch stub `%s' offset overflow\n"),
+            stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
        }
@@ -9510,8 +10518,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                                         FALSE, FALSE);
       if (br_entry == NULL)
        {
-         (*_bfd_error_handler) (_("can't find branch stub `%s'"),
-                                stub_entry->root.string);
+         info->callbacks->einfo (_("%P: can't find branch stub `%s'\n"),
+                                 stub_entry->root.string);
          htab->stub_error = TRUE;
          return FALSE;
        }
@@ -9519,6 +10527,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);
@@ -9571,8 +10581,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
-         (*_bfd_error_handler)
-           (_("linkage table error against `%s'"),
+         info->callbacks->einfo
+           (_("%P: linkage table error against `%T'\n"),
             stub_entry->root.string);
          bfd_set_error (bfd_error_bad_value);
          htab->stub_error = TRUE;
@@ -9605,54 +10615,60 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          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
        {
-         bfd_vma r2off;
+         bfd_vma r2off = get_r2off (info, stub_entry);
+
+         if (r2off == 0 && htab->opd_abi)
+           {
+             htab->stub_error = TRUE;
+             return FALSE;
+           }
 
-         r2off = (htab->stub_group[stub_entry->target_section->id].toc_off
-                  - htab->stub_group[stub_entry->id_sec->id].toc_off);
-         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;
+         size = 16;
          if (PPC_HA (off) != 0)
            {
              size += 4;
-             bfd_put_32 (htab->stub_bfd, ADDIS_R12_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, ADDIS_R11_R2 | PPC_HA (off), loc);
              loc += 4;
+             bfd_put_32 (htab->stub_bfd, LD_R12_0R11 | PPC_LO (off), loc);
            }
          else
-           {
-             bfd_put_32 (htab->stub_bfd, LD_R11_0R2 | PPC_LO (off), loc);
-             loc += 4;
-           }
+           bfd_put_32 (htab->stub_bfd, LD_R12_0R2 | PPC_LO (off), loc);
 
          if (PPC_HA (r2off) != 0)
            {
              size += 4;
+             loc += 4;
              bfd_put_32 (htab->stub_bfd, ADDIS_R2_R2 | PPC_HA (r2off), loc);
+           }
+         if (PPC_LO (r2off) != 0)
+           {
+             size += 4;
              loc += 4;
+             bfd_put_32 (htab->stub_bfd, ADDI_R2_R2 | PPC_LO (r2off), loc);
            }
-         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;
 
     case ppc_stub_plt_call:
+    case ppc_stub_plt_call_r2save:
       if (stub_entry->h != NULL
          && stub_entry->h->is_func_descriptor
          && stub_entry->h->oh != NULL)
@@ -9667,6 +10683,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
             these checks could now disappear.  */
          if (fh->elf.root.type == bfd_link_hash_undefined)
            fh->elf.root.type = bfd_link_hash_undefweak;
+         /* Stop undo_symbol_twiddle changing it back to undefined.  */
+         fh->was_undefined = 0;
        }
 
       /* Now build the stub.  */
@@ -9674,11 +10692,11 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (dest >= (bfd_vma) -2)
        abort ();
 
-      plt = htab->plt;
+      plt = htab->elf.splt;
       if (!htab->elf.dynamic_sections_created
          || stub_entry->h == NULL
          || stub_entry->h->elf.dynindx == -1)
-       plt = htab->iplt;
+       plt = htab->elf.iplt;
 
       dest += plt->output_offset + plt->output_section->vma;
 
@@ -9689,13 +10707,16 @@ 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);
 
-         rl = (htab->reliplt->contents
-               + (htab->reliplt->reloc_count++
+         rl = (htab->elf.irelplt->contents
+               + (htab->elf.irelplt->reloc_count++
                   * sizeof (Elf64_External_Rela)));
          bfd_elf64_swap_reloca_out (info->output_bfd, &rela, rl);
          stub_entry->plt_ent->plt.offset |= 1;
@@ -9707,8 +10728,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
       if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
        {
-         (*_bfd_error_handler)
-           (_("linkage table error against `%s'"),
+         info->callbacks->einfo
+           (_("%P: linkage table error against `%T'\n"),
             stub_entry->h != NULL
             ? stub_entry->h->elf.root.root.string
             : "<local sym>");
@@ -9717,12 +10738,23 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          return FALSE;
        }
 
+      if (htab->plt_stub_align != 0)
+       {
+         unsigned pad = plt_stub_pad (htab, stub_entry, off);
+
+         stub_entry->stub_sec->size += pad;
+         stub_entry->stub_offset = stub_entry->stub_sec->size;
+         loc += pad;
+       }
+
       r = NULL;
       if (info->emitrelocations)
        {
          r = get_relocs (stub_entry->stub_sec,
-                         (2 + (PPC_HA (off) != 0)
-                          + (PPC_HA (off + 16) == PPC_HA (off))));
+                         (2
+                          + (PPC_HA (off) != 0)
+                          + (htab->plt_static_chain
+                             && PPC_HA (off + 16) == PPC_HA (off))));
          if (r == NULL)
            return FALSE;
          r[0].r_offset = loc - stub_entry->stub_sec->contents;
@@ -9734,9 +10766,9 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
          && (stub_entry->h == htab->tls_get_addr_fd
              || stub_entry->h == htab->tls_get_addr)
          && !htab->no_tls_get_addr_opt)
-       p = build_tls_get_addr_stub (htab->stub_bfd, loc, off, r);
+       p = build_tls_get_addr_stub (htab, stub_entry, loc, off, r);
       else
-       p = build_plt_stub (htab->stub_bfd, loc, off, r);
+       p = build_plt_stub (htab, stub_entry, loc, off, r);
       size = p - loc;
       break;
 
@@ -9756,6 +10788,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                                       "long_branch_r2off",
                                       "plt_branch",
                                       "plt_branch_r2off",
+                                      "plt_call",
                                       "plt_call" };
 
       len1 = strlen (stub_str[stub_entry->stub_type - 1]);
@@ -9806,36 +10839,34 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
   if (htab == NULL)
     return FALSE;
 
-  if (stub_entry->stub_type == ppc_stub_plt_call)
+  if (stub_entry->stub_type == ppc_stub_plt_call
+      || stub_entry->stub_type == ppc_stub_plt_call_r2save)
     {
       asection *plt;
       off = stub_entry->plt_ent->plt.offset & ~(bfd_vma) 1;
       if (off >= (bfd_vma) -2)
        abort ();
-      plt = htab->plt;
+      plt = htab->elf.splt;
       if (!htab->elf.dynamic_sections_created
          || stub_entry->h == NULL
          || stub_entry->h->elf.dynindx == -1)
-       plt = htab->iplt;
+       plt = htab->elf.iplt;
       off += (plt->output_offset
              + plt->output_section->vma
              - elf_gp (plt->output_section->owner)
              - htab->stub_group[stub_entry->id_sec->id].toc_off);
 
-      size = PLT_CALL_STUB_SIZE;
-      if (PPC_HA (off) == 0)
-       size -= 4;
-      if (PPC_HA (off + 16) != 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)
-         && !htab->no_tls_get_addr_opt)
-       size += 13 * 4;
+      size = plt_stub_size (htab, stub_entry, off);
+      if (htab->plt_stub_align)
+       size += plt_stub_pad (htab, stub_entry, off);
       if (info->emitrelocations)
        {
          stub_entry->stub_sec->reloc_count
-           += 2 + (PPC_HA (off) != 0) + (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;
        }
     }
@@ -9844,6 +10875,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
@@ -9860,16 +10892,25 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       size = 4;
       if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
        {
-         r2off = (htab->stub_group[stub_entry->target_section->id].toc_off
-                  - htab->stub_group[stub_entry->id_sec->id].toc_off);
+         r2off = get_r2off (info, stub_entry);
+         if (r2off == 0 && htab->opd_abi)
+           {
+             htab->stub_error = TRUE;
+             return FALSE;
+           }
          size = 12;
          if (PPC_HA (r2off) != 0)
            size = 16;
          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;
 
@@ -9878,8 +10919,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
                                             TRUE, FALSE);
          if (br_entry == NULL)
            {
-             (*_bfd_error_handler) (_("can't build branch stub `%s'"),
-                                    stub_entry->root.string);
+             info->callbacks->einfo (_("%P: can't build branch stub `%s'\n"),
+                                     stub_entry->root.string);
              htab->stub_error = TRUE;
              return FALSE;
            }
@@ -9920,12 +10961,14 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
            }
          else
            {
-             size = 20;
+             size = 16;
              if (PPC_HA (off) != 0)
                size += 4;
 
              if (PPC_HA (r2off) != 0)
                size += 4;
+             if (PPC_LO (r2off) != 0)
+               size += 4;
            }
        }
       else if (info->emitrelocations)
@@ -9962,9 +11005,6 @@ ppc64_elf_setup_section_lists
   htab->add_stub_section = add_stub_section;
   htab->layout_sections_again = layout_sections_again;
 
-  if (htab->brlt == NULL)
-    return 0;
-
   /* Find the top input section id.  */
   for (input_bfd = info->input_bfds, top_id = 3;
        input_bfd != NULL;
@@ -10017,8 +11057,7 @@ ppc64_elf_start_multitoc_partition (struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
-  elf_gp (info->output_bfd) = ppc64_elf_toc (info->output_bfd);
-  htab->toc_curr = elf_gp (info->output_bfd);
+  htab->toc_curr = ppc64_elf_set_toc (info, info->output_bfd);
   htab->toc_bfd = NULL;
   htab->toc_first_sec = NULL;
 }
@@ -10039,7 +11078,9 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
   if (!htab->second_toc_pass)
     {
       /* Keep track of the first .toc or .got section for this input bfd.  */
-      if (htab->toc_bfd != isec->owner)
+      bfd_boolean new_bfd = htab->toc_bfd != isec->owner;
+
+      if (new_bfd)
        {
          htab->toc_bfd = isec->owner;
          htab->toc_first_sec = isec;
@@ -10067,7 +11108,8 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
 
       /* Die if someone uses a linker script that doesn't keep input
         file .toc and .got together.  */
-      if (elf_gp (isec->owner) != 0
+      if (new_bfd
+         && elf_gp (isec->owner) != 0
          && elf_gp (isec->owner) != off)
        return FALSE;
 
@@ -10105,9 +11147,6 @@ merge_global_got (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   merge_got_entries (&h->got.glist);
 
   return TRUE;
@@ -10124,9 +11163,6 @@ reallocate_got (struct elf_link_hash_entry *h, void *inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   for (gent = h->got.glist; gent != NULL; gent = gent->next)
     if (!gent->is_indirect)
       allocate_got (h, (struct bfd_link_info *) inf, gent);
@@ -10182,8 +11218,8 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
     }
 
   /* Zap sizes of got sections.  */
-  htab->reliplt->rawsize = htab->reliplt->size;
-  htab->reliplt->size -= htab->got_reli_size;
+  htab->elf.irelplt->rawsize = htab->elf.irelplt->size;
+  htab->elf.irelplt->size -= htab->got_reli_size;
   htab->got_reli_size = 0;
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
@@ -10215,7 +11251,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
       unsigned char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
-      asection *s, *srel;
+      asection *s;
 
       if (!is_ppc64_elf (ibfd))
        continue;
@@ -10231,26 +11267,31 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
       end_local_plt = local_plt + locsymcount;
       lgot_masks = (unsigned char *) end_local_plt;
       s = ppc64_elf_tdata (ibfd)->got;
-      srel = ppc64_elf_tdata (ibfd)->relgot;
       for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
        {
          struct got_entry *ent;
 
          for (ent = *lgot_ents; ent != NULL; ent = ent->next)
            {
-             unsigned int num = 1;
+             unsigned int ent_size = 8;
+             unsigned int rel_size = sizeof (Elf64_External_Rela);
+
              ent->got.offset = s->size;
              if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
-               num = 2;
-             s->size += num * 8;
-             if (info->shared)
-               srel->size += num * sizeof (Elf64_External_Rela);
-             else if ((*lgot_masks & PLT_IFUNC) != 0)
                {
-                 htab->reliplt->size
-                   += num * sizeof (Elf64_External_Rela);
-                 htab->got_reli_size
-                   += num * sizeof (Elf64_External_Rela);
+                 ent_size *= 2;
+                 rel_size *= 2;
+               }
+             s->size += ent_size;
+             if ((*lgot_masks & PLT_IFUNC) != 0)
+               {
+                 htab->elf.irelplt->size += rel_size;
+                 htab->got_reli_size += rel_size;
+               }
+             else if (info->shared)
+               {
+                 asection *srel = ppc64_elf_tdata (ibfd)->relgot;
+                 srel->size += rel_size;
                }
            }
        }
@@ -10280,7 +11321,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
        }
     }
 
-  done_something = htab->reliplt->rawsize != htab->reliplt->size;
+  done_something = htab->elf.irelplt->rawsize != htab->elf.irelplt->size;
   if (!done_something)
     for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
       {
@@ -10442,7 +11483,8 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
                  sym_value += adjust;
                }
 
-             dest = opd_entry_value (sym_sec, sym_value, &sym_sec, NULL);
+             dest = opd_entry_value (sym_sec, sym_value,
+                                     &sym_sec, NULL, FALSE);
              if (dest == (bfd_vma) -1)
                continue;
            }
@@ -10467,7 +11509,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;
@@ -10561,28 +11606,25 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
 
   if (htab->multi_toc_needed)
     {
-      /* If a code section has a function that uses the TOC then we need
-        to use the right TOC (obviously).  Also, make sure that .opd gets
-        the correct TOC value for R_PPC64_TOC relocs that don't have or
-        can't find their function symbol (shouldn't ever happen now).
-        Also specially treat .fixup for the linux kernel.  .fixup
-        contains branches, but only back to the function that hit an
-        exception.  */
-      if (isec->has_toc_reloc
-         || (isec->flags & SEC_CODE) == 0
-         || strcmp (isec->name, ".fixup") == 0)
-       {
-         if (elf_gp (isec->owner) != 0)
-           htab->toc_curr = elf_gp (isec->owner);
-       }
-      else if (!isec->call_check_done
-              && toc_adjusting_stub_needed (info, isec) < 0)
-       return FALSE;
+      /* Analyse sections that aren't already flagged as needing a
+        valid toc pointer.  Exclude .fixup for the linux kernel.
+        .fixup contains branches, but only back to the function that
+        hit an exception.  */
+      if (!(isec->has_toc_reloc
+           || (isec->flags & SEC_CODE) == 0
+           || strcmp (isec->name, ".fixup") == 0
+           || isec->call_check_done))
+       {
+         if (toc_adjusting_stub_needed (info, isec) < 0)
+           return FALSE;
+       }
+      /* Make all sections use the TOC assigned for this object file.
+        This will be wrong for pasted sections;  We fix that in
+        check_pasted_section().  */
+      if (elf_gp (isec->owner) != 0)
+       htab->toc_curr = elf_gp (isec->owner);
     }
 
-  /* Functions that don't use the TOC can belong in any TOC group.
-     Use the last TOC base.  This happens to make _init and _fini
-     pasting work, because the fragments generally don't use the TOC.  */
   htab->stub_group[isec->id].toc_off = htab->toc_curr;
   return TRUE;
 }
@@ -10609,6 +11651,15 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
            else if (toc_off != htab->stub_group[i->id].toc_off)
              return FALSE;
          }
+
+      if (toc_off == 0)
+       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
+         if (i->makes_toc_func_call)
+           {
+             toc_off = htab->stub_group[i->id].toc_off;
+             break;
+           }
+
       /* Make sure the whole pasted function uses the same toc offset.  */
       if (toc_off != 0)
        for (i = o->map_head.s; i != NULL; i = i->map_head.s)
@@ -10734,6 +11785,41 @@ group_sections (struct ppc_link_hash_table *htab,
 #undef PREV_SEC
 }
 
+static const unsigned char glink_eh_frame_cie[] =
+{
+  0, 0, 0, 16,                         /* length.  */
+  0, 0, 0, 0,                          /* id.  */
+  1,                                   /* CIE version.  */
+  'z', 'R', 0,                         /* Augmentation string.  */
+  4,                                   /* Code alignment.  */
+  0x78,                                        /* Data alignment.  */
+  65,                                  /* RA reg.  */
+  1,                                   /* Augmentation size.  */
+  DW_EH_PE_pcrel | DW_EH_PE_sdata4,    /* FDE encoding.  */
+  DW_CFA_def_cfa, 1, 0                 /* def_cfa: r1 offset 0.  */
+};
+
+/* Stripping output sections is normally done before dynamic section
+   symbols have been allocated.  This function is called later, and
+   handles cases like htab->brlt which is mapped to its own output
+   section.  */
+
+static void
+maybe_strip_output (struct bfd_link_info *info, asection *isec)
+{
+  if (isec->size == 0
+      && isec->output_section->size == 0
+      && !(isec->output_section->flags & SEC_KEEP)
+      && !bfd_section_removed_from_list (info->output_bfd,
+                                        isec->output_section)
+      && elf_section_data (isec->output_section)->dynindx == 0)
+    {
+      isec->output_section->flags |= SEC_EXCLUDE;
+      bfd_section_list_remove (info->output_bfd, isec->output_section);
+      info->output_bfd->section_count--;
+    }
+}
+
 /* Determine and set the size of the stub section for a final link.
 
    The basic idea here is to examine all the relocations looking for
@@ -10741,7 +11827,9 @@ group_sections (struct ppc_link_hash_table *htab,
    instruction.  */
 
 bfd_boolean
-ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
+ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
+                     bfd_boolean plt_static_chain, int plt_thread_safe,
+                     int plt_stub_align)
 {
   bfd_size_type stub_group_size;
   bfd_boolean stubs_always_before_branch;
@@ -10750,6 +11838,45 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
   if (htab == NULL)
     return FALSE;
 
+  htab->plt_static_chain = plt_static_chain;
+  htab->plt_stub_align = plt_stub_align;
+  if (plt_thread_safe == -1 && !info->executable)
+    plt_thread_safe = 1;
+  if (!htab->opd_abi)
+    plt_thread_safe = 0;
+  else if (plt_thread_safe == -1)
+    {
+      static const char *const thread_starter[] =
+       {
+         "pthread_create",
+         /* libstdc++ */
+         "_ZNSt6thread15_M_start_threadESt10shared_ptrINS_10_Impl_baseEE",
+         /* librt */
+         "aio_init", "aio_read", "aio_write", "aio_fsync", "lio_listio",
+         "mq_notify", "create_timer",
+         /* libanl */
+         "getaddrinfo_a",
+         /* libgomp */
+         "GOMP_parallel_start",
+         "GOMP_parallel_loop_static_start",
+         "GOMP_parallel_loop_dynamic_start",
+         "GOMP_parallel_loop_guided_start",
+         "GOMP_parallel_loop_runtime_start",
+         "GOMP_parallel_sections_start",
+       };
+      unsigned i;
+
+      for (i = 0; i < sizeof (thread_starter)/ sizeof (thread_starter[0]); i++)
+       {
+         struct elf_link_hash_entry *h;
+         h = elf_link_hash_lookup (&htab->elf, thread_starter[i],
+                                   FALSE, FALSE, TRUE);
+         plt_thread_safe = h != NULL && h->ref_regular;
+         if (plt_thread_safe)
+           break;
+       }
+    }
+  htab->plt_thread_safe = plt_thread_safe;
   stubs_always_before_branch = group_size < 0;
   if (group_size < 0)
     stub_group_size = -group_size;
@@ -10823,6 +11950,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;
@@ -10899,12 +12027,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;
@@ -10923,7 +12055,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                          sym_value += adjust;
                        }
                      dest = opd_entry_value (sym_sec, sym_value,
-                                             &code_sec, &code_value);
+                                             &code_sec, &code_value, FALSE);
                      if (dest != (bfd_vma) -1)
                        {
                          destination = dest;
@@ -10941,7 +12073,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)
                    {
@@ -10981,6 +12114,18 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                        continue;
                    }
 
+                 if (stub_type == ppc_stub_plt_call
+                     && irela + 1 < irelaend
+                     && irela[1].r_offset == irela->r_offset + 4
+                     && ELF64_R_TYPE (irela[1].r_info) == R_PPC64_TOCSAVE)
+                   {
+                     if (!tocsave_find (htab, INSERT,
+                                        &local_syms, irela + 1, input_bfd))
+                       goto error_ret_free_internal;
+                   }
+                 else if (stub_type == ppc_stub_plt_call)
+                   stub_type = ppc_stub_plt_call_r2save;
+
                  /* Support for grouping stub sections.  */
                  id_sec = htab->stub_group[section->id].link_sec;
 
@@ -10995,10 +12140,12 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                    {
                      /* The proper stub has already been created.  */
                      free (stub_name);
+                     if (stub_type == ppc_stub_plt_call_r2save)
+                       stub_entry->stub_type = stub_type;
                      continue;
                    }
 
-                 stub_entry = ppc_add_stub (stub_name, section, htab);
+                 stub_entry = ppc_add_stub (stub_name, section, info);
                  if (stub_entry == NULL)
                    {
                      free (stub_name);
@@ -11014,7 +12161,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                    }
 
                  stub_entry->stub_type = stub_type;
-                 if (stub_type != ppc_stub_plt_call)
+                 if (stub_type != ppc_stub_plt_call
+                     && stub_type != ppc_stub_plt_call_r2save)
                    {
                      stub_entry->target_value = code_value;
                      stub_entry->target_section = code_sec;
@@ -11026,7 +12174,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                    }
                  stub_entry->h = hash;
                  stub_entry->plt_ent = plt_ent;
-                 stub_entry->addend = irela->r_addend;
+                 stub_entry->other = hash ? hash->elf.other : sym->st_other;
 
                  if (stub_entry->h != NULL)
                    htab->stub_globals += 1;
@@ -11075,6 +12223,37 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
          htab->glink->flags |= SEC_RELOC;
        }
 
+      if (htab->glink_eh_frame != NULL
+         && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
+         && htab->glink_eh_frame->output_section->size != 0)
+       {
+         size_t size = 0, align;
+
+         for (stub_sec = htab->stub_bfd->sections;
+              stub_sec != NULL;
+              stub_sec = stub_sec->next)
+           if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+             size += 20;
+         if (htab->glink != NULL && htab->glink->size != 0)
+           size += 24;
+         if (size != 0)
+           size += sizeof (glink_eh_frame_cie);
+         align = 1;
+         align <<= htab->glink_eh_frame->output_section->alignment_power;
+         align -= 1;
+         size = (size + align) & ~align;
+         htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
+         htab->glink_eh_frame->size = size;
+       }
+
+      if (htab->plt_stub_align != 0)
+       for (stub_sec = htab->stub_bfd->sections;
+            stub_sec != NULL;
+            stub_sec = stub_sec->next)
+         if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+           stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1)
+                             & (-1 << htab->plt_stub_align));
+
       for (stub_sec = htab->stub_bfd->sections;
           stub_sec != NULL;
           stub_sec = stub_sec->next)
@@ -11084,17 +12263,18 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
 
       /* Exit from this loop when no stubs have been added, and no stubs
         have changed size.  */
-      if (stub_sec == NULL)
+      if (stub_sec == NULL
+         && (htab->glink_eh_frame == NULL
+             || htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
        break;
 
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
     }
 
-  /* It would be nice to strip htab->brlt from the output if the
-     section is empty, but it's too late.  If we strip sections here,
-     the dynamic symbol table is corrupted since the section symbol
-     for the stripped section isn't written.  */
+  maybe_strip_output (info, htab->brlt);
+  if (htab->glink_eh_frame != NULL)
+    maybe_strip_output (info, htab->glink_eh_frame);
 
   return TRUE;
 }
@@ -11103,7 +12283,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
    move, we'll be called again.  Provide a value for TOCstart.  */
 
 bfd_vma
-ppc64_elf_toc (bfd *obfd)
+ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
 {
   asection *s;
   bfd_vma TOCstart;
@@ -11127,34 +12307,113 @@ ppc64_elf_toc (bfd *obfd)
 
         FIXME: Warn user?  */
 
-      /* Look for a likely section.  We probably won't even be
-        using TOCstart.  */
-      for (s = obfd->sections; s != NULL; s = s->next)
-       if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY
-                        | SEC_EXCLUDE))
-           == (SEC_ALLOC | SEC_SMALL_DATA))
-         break;
-      if (s == NULL)
-       for (s = obfd->sections; s != NULL; s = s->next)
-         if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_EXCLUDE))
-             == (SEC_ALLOC | SEC_SMALL_DATA))
-           break;
-      if (s == NULL)
-       for (s = obfd->sections; s != NULL; s = s->next)
-         if ((s->flags & (SEC_ALLOC | SEC_READONLY | SEC_EXCLUDE))
-             == SEC_ALLOC)
-           break;
-      if (s == NULL)
-       for (s = obfd->sections; s != NULL; s = s->next)
-         if ((s->flags & (SEC_ALLOC | SEC_EXCLUDE)) == SEC_ALLOC)
-           break;
-    }
+      /* Look for a likely section.  We probably won't even be
+        using TOCstart.  */
+      for (s = obfd->sections; s != NULL; s = s->next)
+       if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_READONLY
+                        | SEC_EXCLUDE))
+           == (SEC_ALLOC | SEC_SMALL_DATA))
+         break;
+      if (s == NULL)
+       for (s = obfd->sections; s != NULL; s = s->next)
+         if ((s->flags & (SEC_ALLOC | SEC_SMALL_DATA | SEC_EXCLUDE))
+             == (SEC_ALLOC | SEC_SMALL_DATA))
+           break;
+      if (s == NULL)
+       for (s = obfd->sections; s != NULL; s = s->next)
+         if ((s->flags & (SEC_ALLOC | SEC_READONLY | SEC_EXCLUDE))
+             == SEC_ALLOC)
+           break;
+      if (s == NULL)
+       for (s = obfd->sections; s != NULL; s = s->next)
+         if ((s->flags & (SEC_ALLOC | SEC_EXCLUDE)) == SEC_ALLOC)
+           break;
+    }
+
+  TOCstart = 0;
+  if (s != NULL)
+    TOCstart = s->output_section->vma + s->output_offset;
+
+  _bfd_set_gp_value (obfd, TOCstart);
+
+  if (info != NULL && s != NULL && is_ppc64_elf (obfd))
+    {
+      struct ppc_link_hash_table *htab = ppc_hash_table (info);
+
+      if (htab != NULL
+         && htab->elf.hgot != NULL)
+       {
+         htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
+         htab->elf.hgot->root.u.def.section = s;
+       }
+    }
+  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->elf.splt;
+       if (!htab->elf.dynamic_sections_created
+           || h->dynindx == -1)
+         plt = htab->elf.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;
 
-  TOCstart = 0;
-  if (s != NULL)
-    TOCstart = s->output_section->vma + s->output_offset;
+       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;
+         }
 
-  return TOCstart;
+       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.
@@ -11217,7 +12476,9 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
              h->non_elf = 0;
            }
        }
-      plt0 = htab->plt->output_section->vma + htab->plt->output_offset - 16;
+      plt0 = (htab->elf.splt->output_section->vma
+             + htab->elf.splt->output_offset
+             - 16);
       if (info->emitrelocations)
        {
          Elf_Internal_Rela *r = get_relocs (htab->glink, 1);
@@ -11232,26 +12493,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)
@@ -11262,26 +12553,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)
+         if (htab->opd_abi)
            {
-             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;
+             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)
@@ -11299,12 +12597,131 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
        return FALSE;
     }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *last_fde;
+      size_t last_fde_len, size, align, pad;
+
+      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
+      if (p == NULL)
+       return FALSE;
+      htab->glink_eh_frame->contents = p;
+      last_fde = p;
+
+      htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
+
+      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+      /* CIE length (rewrite in case little-endian).  */
+      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
+      p += sizeof (glink_eh_frame_cie);
+
+      for (stub_sec = htab->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           last_fde = p;
+           last_fde_len = 16;
+           /* FDE length.  */
+           bfd_put_32 (htab->elf.dynobj, 16, p);
+           p += 4;
+           /* CIE pointer.  */
+           val = p - htab->glink_eh_frame->contents;
+           bfd_put_32 (htab->elf.dynobj, val, p);
+           p += 4;
+           /* Offset to stub section.  */
+           val = (stub_sec->output_section->vma
+                  + stub_sec->output_offset);
+           val -= (htab->glink_eh_frame->output_section->vma
+                   + htab->glink_eh_frame->output_offset);
+           val -= p - htab->glink_eh_frame->contents;
+           if (val + 0x80000000 > 0xffffffff)
+             {
+               info->callbacks->einfo
+                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                  stub_sec->name);
+               return FALSE;
+             }
+           bfd_put_32 (htab->elf.dynobj, val, p);
+           p += 4;
+           /* stub section size.  */
+           bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 3;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         last_fde = p;
+         last_fde_len = 20;
+         /* FDE length.  */
+         bfd_put_32 (htab->elf.dynobj, 20, p);
+         p += 4;
+         /* CIE pointer.  */
+         val = p - htab->glink_eh_frame->contents;
+         bfd_put_32 (htab->elf.dynobj, val, p);
+         p += 4;
+         /* Offset to .glink.  */
+         val = (htab->glink->output_section->vma
+                + htab->glink->output_offset
+                + 8);
+         val -= (htab->glink_eh_frame->output_section->vma
+                 + htab->glink_eh_frame->output_offset);
+         val -= p - htab->glink_eh_frame->contents;
+         if (val + 0x80000000 > 0xffffffff)
+           {
+             info->callbacks->einfo
+               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                htab->glink->name);
+             return FALSE;
+           }
+         bfd_put_32 (htab->elf.dynobj, val, p);
+         p += 4;
+         /* .glink size.  */
+         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+
+         *p++ = DW_CFA_advance_loc + 1;
+         *p++ = DW_CFA_register;
+         *p++ = 65;
+         *p++ = 12;
+         *p++ = DW_CFA_advance_loc + 4;
+         *p++ = DW_CFA_restore_extended;
+         *p++ = 65;
+       }
+      /* Subsume any padding into the last FDE if user .eh_frame
+        sections are aligned more than glink_eh_frame.  Otherwise any
+        zero padding will be seen as a terminator.  */
+      size = p - htab->glink_eh_frame->contents;
+      align = 1;
+      align <<= htab->glink_eh_frame->output_section->alignment_power;
+      align -= 1;
+      pad = ((size + align) & ~align) - size;
+      htab->glink_eh_frame->size = size + pad;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
+    }
+
   /* Build the stubs as directed by the stub hash table.  */
   bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
 
   if (htab->relbrlt != NULL)
     htab->relbrlt->reloc_count = 0;
 
+  if (htab->plt_stub_align != 0)
+    for (stub_sec = htab->stub_bfd->sections;
+        stub_sec != NULL;
+        stub_sec = stub_sec->next)
+      if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+       stub_sec->size = ((stub_sec->size + (1 << htab->plt_stub_align) - 1)
+                         & (-1 << htab->plt_stub_align));
+
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
@@ -11316,10 +12733,11 @@ 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))
     {
       htab->stub_error = TRUE;
-      (*_bfd_error_handler) (_("stubs don't match calculated size"));
+      info->callbacks->einfo (_("%P: stubs don't match calculated size\n"));
     }
 
   if (htab->stub_error)
@@ -11336,14 +12754,16 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
                         "  toc adjust   %lu\n"
                         "  long branch  %lu\n"
                         "  long toc adj %lu\n"
-                        "  plt call     %lu"),
+                        "  plt call     %lu\n"
+                        "  plt call toc %lu"),
               stub_sec_count,
               stub_sec_count == 1 ? "" : "s",
               htab->stub_count[ppc_stub_long_branch - 1],
               htab->stub_count[ppc_stub_long_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_branch - 1],
               htab->stub_count[ppc_stub_plt_branch_r2off - 1],
-              htab->stub_count[ppc_stub_plt_call - 1]);
+              htab->stub_count[ppc_stub_plt_call - 1],
+              htab->stub_count[ppc_stub_plt_call_r2save - 1]);
     }
   return TRUE;
 }
@@ -11358,9 +12778,6 @@ undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   eh = (struct ppc_link_hash_entry *) h;
   if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined)
     return TRUE;
@@ -11396,63 +12813,6 @@ ppc64_elf_action_discarded (asection *sec)
   return _bfd_elf_default_action_discarded (sec);
 }
 
-/* REL points to a low-part reloc on a largetoc instruction sequence.
-   Find the matching high-part reloc instruction and verify that it
-   is addis REG,x,imm.  If so, set *REG to x and return a pointer to
-   the high-part reloc.  */
-
-static const Elf_Internal_Rela *
-ha_reloc_match (const Elf_Internal_Rela *relocs,
-               const Elf_Internal_Rela *rel,
-               unsigned int *reg,
-               bfd_boolean match_addend,
-               const bfd *input_bfd,
-               const bfd_byte *contents)
-{
-  enum elf_ppc64_reloc_type r_type, r_type_ha;
-  bfd_vma r_info_ha, r_addend;
-
-  r_type = ELF64_R_TYPE (rel->r_info);
-  switch (r_type)
-    {
-    case R_PPC64_GOT_TLSLD16_LO:
-    case R_PPC64_GOT_TLSGD16_LO:
-    case R_PPC64_GOT_TPREL16_LO_DS:
-    case R_PPC64_GOT_DTPREL16_LO_DS:
-    case R_PPC64_GOT16_LO:
-    case R_PPC64_TOC16_LO:
-      r_type_ha = r_type + 2;
-      break;
-    case R_PPC64_GOT16_LO_DS:
-      r_type_ha = R_PPC64_GOT16_HA;
-      break;
-    case R_PPC64_TOC16_LO_DS:
-      r_type_ha = R_PPC64_TOC16_HA;
-      break;
-    default:
-      abort ();
-    }
-  r_info_ha = ELF64_R_INFO (ELF64_R_SYM (rel->r_info), r_type_ha);
-  r_addend = rel->r_addend;
-
-  while (--rel >= relocs)
-    if (rel->r_info == r_info_ha
-       && (!match_addend
-           || rel->r_addend == r_addend))
-      {
-       const bfd_byte *p = contents + (rel->r_offset & ~3);
-       unsigned int insn = bfd_get_32 (input_bfd, p);
-       if ((insn & (0x3f << 26)) == (15u << 26) /* addis rt,x,imm */
-           && (insn & (0x1f << 21)) == (*reg << 21))
-         {
-           *reg = (insn >> 16) & 0x1f;
-           return rel;
-         }
-       break;
-      }
-  return NULL;
-}
-
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
@@ -11500,13 +12860,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   Elf_Internal_Rela outrel;
   bfd_byte *loc;
   struct got_entry **local_got_ents;
-  unsigned char *ha_opt;
   bfd_vma TOCstart;
-  bfd_boolean no_ha_opt;
   bfd_boolean ret = TRUE;
   bfd_boolean is_opd;
-  /* Disabled until we sort out how ld should choose 'y' vs 'at'.  */
-  bfd_boolean is_power4 = FALSE;
+  /* Assume 'at' branch hints.  */
+  bfd_boolean is_isa_v2 = TRUE;
   bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
 
   /* Initialize howto table if needed.  */
@@ -11528,15 +12886,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
   symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
   is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
-  ha_opt = NULL;
-  no_ha_opt = FALSE;
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
   for (; rel < relend; rel++)
     {
       enum elf_ppc64_reloc_type r_type;
-      bfd_vma addend, orig_addend;
+      bfd_vma addend;
       bfd_reloc_status_type r;
       Elf_Internal_Sym *sym;
       asection *sec;
@@ -11551,11 +12907,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_boolean warned;
+      enum { DEST_NORMAL, DEST_OPD, DEST_STUB } reloc_dest;
       unsigned int insn;
-      bfd_vma mask;
+      unsigned int mask;
       struct ppc_stub_hash_entry *stub_entry;
       bfd_vma max_br_offset;
       bfd_vma from;
+      const Elf_Internal_Rela orig_rel = *rel;
 
       r_type = ELF64_R_TYPE (rel->r_info);
       r_symndx = ELF64_R_SYM (rel->r_info);
@@ -11575,7 +12933,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       sym_name = NULL;
       unresolved_reloc = FALSE;
       warned = FALSE;
-      orig_addend = rel->r_addend;
 
       if (r_symndx < symtab_hdr->sh_info)
        {
@@ -11609,30 +12966,61 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        }
       else
        {
+         bfd_boolean ignored;
+
          RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
                                   r_symndx, symtab_hdr, sym_hashes,
                                   h_elf, sec, relocation,
-                                  unresolved_reloc, warned);
+                                  unresolved_reloc, warned, ignored);
          sym_name = h_elf->root.root.string;
          sym_type = h_elf->type;
+         if (sec != NULL
+             && sec->owner == output_bfd
+             && strcmp (sec->name, ".opd") == 0)
+           {
+             /* This is a symbol defined in a linker script.  All
+                such are defined in output sections, even those
+                defined by simple assignment from a symbol defined in
+                an input section.  Transfer the symbol to an
+                appropriate input .opd section, so that a branch to
+                this symbol will be mapped to the location specified
+                by the opd entry.  */
+             struct bfd_link_order *lo;
+             for (lo = sec->map_head.link_order; lo != NULL; lo = lo->next)
+               if (lo->type == bfd_indirect_link_order)
+                 {
+                   asection *isec = lo->u.indirect.section;
+                   if (h_elf->root.u.def.value >= isec->output_offset
+                       && h_elf->root.u.def.value < (isec->output_offset
+                                                     + isec->size))
+                     {
+                       h_elf->root.u.def.value -= isec->output_offset;
+                       h_elf->root.u.def.section = isec;
+                       sec = isec;
+                       break;
+                     }
+                 }
+           }
        }
       h = (struct ppc_link_hash_entry *) h_elf;
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (ppc64_elf_howto_table[r_type], input_bfd,
-                              contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend,
+                                        ppc64_elf_howto_table[r_type], 0,
+                                        contents);
 
       if (info->relocatable)
        continue;
 
+      if (h != NULL && &h->elf == htab->elf.hgot)
+       {
+         relocation = (TOCstart
+                       + htab->stub_group[input_section->id].toc_off);
+         sec = bfd_abs_section_ptr;
+         unresolved_reloc = FALSE;
+       }
+
       /* TLS optimizations.  Replace instruction sequences and relocs
         based on information we collected in tls_optimize.  We edit
         RELOCS so that --emit-relocs will output something sensible
@@ -11685,13 +13073,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            /* R_PPC64_TLS is OK against a symbol in the TOC.  */
            ;
          else
-           (*_bfd_error_handler)
+           info->callbacks->einfo
              (!IS_PPC64_TLS_RELOC (r_type)
-              ? _("%B(%A+0x%lx): %s used with TLS symbol %s")
-              : _("%B(%A+0x%lx): %s used with non-TLS symbol %s"),
-              input_bfd,
-              input_section,
-              (long) rel->r_offset,
+              ? _("%P: %H: %s used with TLS symbol `%T'\n")
+              : _("%P: %H: %s used with non-TLS symbol `%T'\n"),
+              input_bfd, input_section, rel->r_offset,
               ppc64_elf_howto_table[r_type]->name,
               sym_name);
        }
@@ -12090,17 +13476,67 @@ 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.  */
       insn = 0;
       max_br_offset = 1 << 25;
       addend = rel->r_addend;
+      reloc_dest = DEST_NORMAL;
       switch (r_type)
        {
        default:
          break;
 
+       case R_PPC64_TOCSAVE:
+         if (relocation + addend == (rel->r_offset
+                                     + input_section->output_offset
+                                     + input_section->output_section->vma)
+             && tocsave_find (htab, NO_INSERT,
+                              &local_syms, rel, input_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_0R1 + STK_TOC (htab),
+                           contents + rel->r_offset);
+           }
+         break;
+
          /* Branch taken prediction relocations.  */
        case R_PPC64_ADDR14_BRTAKEN:
        case R_PPC64_REL14_BRTAKEN:
@@ -12130,89 +13566,105 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              && h->oh != NULL
              && h->oh->is_func_descriptor)
            fdh = ppc_follow_link (h->oh);
-         stub_entry = ppc_get_stub_entry (input_section, sec, fdh, rel, htab);
+         stub_entry = ppc_get_stub_entry (input_section, sec, fdh, &orig_rel,
+                                          htab);
          if (stub_entry != NULL
              && (stub_entry->stub_type == ppc_stub_plt_call
+                 || stub_entry->stub_type == ppc_stub_plt_call_r2save
                  || stub_entry->stub_type == ppc_stub_plt_branch_r2off
                  || stub_entry->stub_type == ppc_stub_long_branch_r2off))
            {
              bfd_boolean can_plt_call = FALSE;
 
+             /* All of these stubs will modify r2, so there must be a
+                branch and link followed by a nop.  The nop is
+                replaced by an insn to restore r2.  */
              if (rel->r_offset + 8 <= input_section->size)
                {
-                 unsigned long nop;
-                 nop = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
-                 if (nop == NOP
-                     || nop == CROR_151515 || nop == CROR_313131)
+                 unsigned long br;
+
+                 br = bfd_get_32 (input_bfd,
+                                  contents + rel->r_offset);
+                 if ((br & 1) != 0)
                    {
-                     if (h != NULL
-                         && (h == htab->tls_get_addr_fd
-                             || h == htab->tls_get_addr)
-                         && !htab->no_tls_get_addr_opt)
+                     unsigned long nop;
+
+                     nop = bfd_get_32 (input_bfd,
+                                       contents + rel->r_offset + 4);
+                     if (nop == NOP
+                         || nop == CROR_151515 || nop == CROR_313131)
                        {
-                         /* Special stub used, leave nop alone.  */
+                         if (h != NULL
+                             && (h == htab->tls_get_addr_fd
+                                 || h == htab->tls_get_addr)
+                             && !htab->no_tls_get_addr_opt)
+                           {
+                             /* Special stub used, leave nop alone.  */
+                           }
+                         else
+                           bfd_put_32 (input_bfd,
+                                       LD_R2_0R1 + STK_TOC (htab),
+                                       contents + rel->r_offset + 4);
+                         can_plt_call = TRUE;
                        }
-                     else
-                       bfd_put_32 (input_bfd, LD_R2_40R1,
-                                   contents + rel->r_offset + 4);
-                     can_plt_call = TRUE;
                    }
                }
 
-             if (!can_plt_call)
+             if (!can_plt_call && h != NULL)
                {
-                 if (stub_entry->stub_type == ppc_stub_plt_call)
-                   {
-                     /* If this is a plain branch rather than a branch
-                        and link, don't require a nop.  However, don't
-                        allow tail calls in a shared library as they
-                        will result in r2 being corrupted.  */
-                     unsigned long br;
-                     br = bfd_get_32 (input_bfd, contents + rel->r_offset);
-                     if (info->executable && (br & 1) == 0)
-                       can_plt_call = TRUE;
-                     else
-                       stub_entry = NULL;
-                   }
-                 else if (h != NULL
-                          && strcmp (h->elf.root.root.string,
-                                     ".__libc_start_main") == 0)
+                 const char *name = h->elf.root.root.string;
+
+                 if (*name == '.')
+                   ++name;
+
+                 if (strncmp (name, "__libc_start_main", 17) == 0
+                     && (name[17] == 0 || name[17] == '@'))
                    {
-                     /* Allow crt1 branch to go via a toc adjusting stub.  */
+                     /* Allow crt1 branch to go via a toc adjusting
+                        stub.  Other calls that never return could do
+                        the same, if we could detect such.  */
                      can_plt_call = TRUE;
                    }
-                 else
+               }
+
+             if (!can_plt_call)
+               {
+                 /* g++ as of 20130507 emits self-calls without a
+                    following nop.  This is arguably wrong since we
+                    have conflicting information.  On the one hand a
+                    global symbol and on the other a local call
+                    sequence, but don't error for this special case.
+                    It isn't possible to cheaply verify we have
+                    exactly such a call.  Allow all calls to the same
+                    section.  */
+                 asection *code_sec = sec;
+
+                 if (get_opd_info (sec) != NULL)
                    {
-                     if (strcmp (input_section->output_section->name,
-                                 ".init") == 0
-                         || strcmp (input_section->output_section->name,
-                                    ".fini") == 0)
-                       (*_bfd_error_handler)
-                         (_("%B(%A+0x%lx): automatic multiple TOCs "
-                            "not supported using your crt files; "
-                            "recompile with -mminimal-toc or upgrade gcc"),
-                          input_bfd,
-                          input_section,
-                          (long) rel->r_offset);
-                     else
-                       (*_bfd_error_handler)
-                         (_("%B(%A+0x%lx): sibling call optimization to `%s' "
-                            "does not allow automatic multiple TOCs; "
-                            "recompile with -mminimal-toc or "
-                            "-fno-optimize-sibling-calls, "
-                            "or make `%s' extern"),
-                          input_bfd,
-                          input_section,
-                          (long) rel->r_offset,
-                          sym_name,
-                          sym_name);
-                     bfd_set_error (bfd_error_bad_value);
-                     ret = FALSE;
+                     bfd_vma off = (relocation + addend
+                                    - sec->output_section->vma
+                                    - sec->output_offset);
+
+                     opd_entry_value (sec, off, &code_sec, NULL, FALSE);
                    }
+                 if (code_sec == input_section)
+                   can_plt_call = TRUE;
+               }
+
+             if (!can_plt_call)
+               {
+                 info->callbacks->einfo
+                   (_("%P: %H: call to `%T' lacks nop, can't restore toc; "
+                      "recompile with -fPIC"),
+                    input_bfd, input_section, rel->r_offset, sym_name);
+
+                 bfd_set_error (bfd_error_bad_value);
+                 ret = FALSE;
                }
 
              if (can_plt_call
-                 && stub_entry->stub_type == ppc_stub_plt_call)
+                 && (stub_entry->stub_type == ppc_stub_plt_call
+                     || stub_entry->stub_type == ppc_stub_plt_call_r2save))
                unresolved_reloc = FALSE;
            }
 
@@ -12225,11 +13677,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              bfd_vma off = (relocation + addend
                             - sec->output_section->vma
                             - sec->output_offset);
-             bfd_vma dest = opd_entry_value (sec, off, NULL, NULL);
+             bfd_vma dest = opd_entry_value (sec, off, NULL, NULL, FALSE);
              if (dest != (bfd_vma) -1)
                {
                  relocation = dest;
                  addend = 0;
+                 reloc_dest = DEST_OPD;
                }
            }
 
@@ -12239,6 +13692,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)
@@ -12257,11 +13714,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                            + stub_entry->stub_sec->output_offset
                            + stub_entry->stub_sec->output_section->vma);
              addend = 0;
+             reloc_dest = DEST_STUB;
+
+             if ((stub_entry->stub_type == ppc_stub_plt_call
+                  || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+                 && (ALWAYS_EMIT_R2SAVE
+                     || stub_entry->stub_type == ppc_stub_plt_call_r2save)
+                 && rel + 1 < relend
+                 && rel[1].r_offset == rel->r_offset + 4
+                 && ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
+               relocation += 4;
            }
 
          if (insn != 0)
            {
-             if (is_power4)
+             if (is_isa_v2)
                {
                  /* Set 'a' bit.  This is 0b00010 in BO field for branch
                     on CR(BI) insns (BO == 001at or 011at), and 0b01000
@@ -12304,8 +13771,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       switch (r_type)
        {
        default:
-         (*_bfd_error_handler)
-           (_("%B: unknown relocation type %d for symbol %s"),
+         info->callbacks->einfo
+           (_("%P: %B: unknown relocation type %d for `%T'\n"),
             input_bfd, (int) r_type, sym_name);
 
          bfd_set_error (bfd_error_bad_value);
@@ -12316,6 +13783,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_TLS:
        case R_PPC64_TLSGD:
        case R_PPC64_TLSLD:
+       case R_PPC64_TOCSAVE:
        case R_PPC64_GNU_VTINHERIT:
        case R_PPC64_GNU_VTENTRY:
          continue;
@@ -12381,7 +13849,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
@@ -12389,6 +13857,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                      ;
                    else
                      {
+                       BFD_ASSERT (h->elf.dynindx != -1);
                        indx = h->elf.dynindx;
                        unresolved_reloc = FALSE;
                      }
@@ -12402,7 +13871,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                  }
 
                for (; ent != NULL; ent = ent->next)
-                 if (ent->addend == orig_addend
+                 if (ent->addend == orig_rel.r_addend
                      && ent->owner == input_bfd
                      && ent->tls_type == tls_type)
                    break;
@@ -12436,15 +13905,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                ifunc = (h != NULL
                         ? h->elf.type == STT_GNU_IFUNC
                         : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
-               if ((info->shared || indx != 0)
-                   && (h == NULL
-                       || (tls_type == (TLS_TLS | TLS_LD)
-                           && !h->elf.def_dynamic)
-                       || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
-                       || h->elf.root.type != bfd_link_hash_undefweak))
+               if (ifunc)
+                 relgot = htab->elf.irelplt;
+               else if ((info->shared || indx != 0)
+                        && (h == NULL
+                            || (tls_type == (TLS_TLS | TLS_LD)
+                                && !h->elf.def_dynamic)
+                            || ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
+                            || h->elf.root.type != bfd_link_hash_undefweak))
                  relgot = ppc64_elf_tdata (ent->owner)->relgot;
-               else if (ifunc)
-                 relgot = htab->reliplt;
                if (relgot != NULL)
                  {
                    outrel.r_offset = (got->output_section->vma
@@ -12551,17 +14020,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
             symbol.  This happens when statically linking PIC code,
             or when using -Bsymbolic.  Go find a match if there is a
             PLT entry.  */
-         if (htab->plt != NULL)
+         if (htab->elf.splt != NULL)
            {
              struct plt_entry *ent;
              for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
-               if (ent->addend == orig_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
+                   relocation = (htab->elf.splt->output_section->vma
+                                 + htab->elf.splt->output_offset
                                  + ent->plt.offset);
                    unresolved_reloc = FALSE;
+                   break;
                  }
            }
          break;
@@ -12621,6 +14091,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:
@@ -12655,6 +14127,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:
@@ -12687,6 +14161,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:
@@ -12758,10 +14234,13 @@ 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)
-               outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
+               {
+                 BFD_ASSERT (h->elf.dynindx != -1);
+                 outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type);
+               }
              else
                {
                  /* This symbol is local, or marked to become local,
@@ -12809,12 +14288,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                          ? h->elf.type == STT_GNU_IFUNC
                          : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
                        {
-                         (*_bfd_error_handler)
-                           (_("%B(%A+0x%lx): relocation %s for indirect "
-                              "function %s unsupported"),
-                            input_bfd,
-                            input_section,
-                            (long) rel->r_offset,
+                         info->callbacks->einfo
+                           (_("%P: %H: %s for indirect "
+                              "function `%T' unsupported\n"),
+                            input_bfd, input_section, rel->r_offset,
                             ppc64_elf_howto_table[r_type]->name,
                             sym_name);
                          ret = FALSE;
@@ -12857,8 +14334,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                }
 
              sreloc = elf_section_data (input_section)->sreloc;
-             if (!htab->elf.dynamic_sections_created)
-               sreloc = htab->reliplt;
+             if (h != NULL
+                 ? h->elf.type == STT_GNU_IFUNC
+                 : ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+               sreloc = htab->elf.irelplt;
              if (sreloc == NULL)
                abort ();
 
@@ -12916,8 +14395,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_PLTREL64:
          /* These ones haven't been implemented yet.  */
 
-         (*_bfd_error_handler)
-           (_("%B: relocation %s is not supported for symbol %s."),
+         info->callbacks->einfo
+           (_("%P: %B: %s is not supported for `%T'\n"),
             input_bfd,
             ppc64_elf_howto_table[r_type]->name, sym_name);
 
@@ -12955,7 +14434,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_GOT_DTPREL16_HA:
        case R_PPC64_GOT16_HA:
        case R_PPC64_TOC16_HA:
-         /* nop is done later.  */
+         if (htab->do_toc_opt && relocation + addend + 0x8000 < 0x10000
+             && !ppc64_elf_tdata (input_bfd)->unexpected_toc_insn)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             bfd_put_32 (input_bfd, NOP, p);
+           }
          break;
 
        case R_PPC64_GOT_TLSLD16_LO:
@@ -12966,56 +14450,23 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_GOT16_LO_DS:
        case R_PPC64_TOC16_LO:
        case R_PPC64_TOC16_LO_DS:
-         if (htab->do_toc_opt && relocation + addend + 0x8000 < 0x10000)
+         if (htab->do_toc_opt && relocation + addend + 0x8000 < 0x10000
+             && !ppc64_elf_tdata (input_bfd)->unexpected_toc_insn)
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              insn = bfd_get_32 (input_bfd, p);
-             if ((insn & (0x3f << 26)) == 14u << 26 /* addi */
-                 || (insn & (0x3f << 26)) == 32u << 26 /* lwz */
-                 || (insn & (0x3f << 26)) == 34u << 26 /* lbz */
-                 || (insn & (0x3f << 26)) == 36u << 26 /* stw */
-                 || (insn & (0x3f << 26)) == 38u << 26 /* stb */
-                 || (insn & (0x3f << 26)) == 40u << 26 /* lhz */
-                 || (insn & (0x3f << 26)) == 42u << 26 /* lha */
-                 || (insn & (0x3f << 26)) == 44u << 26 /* sth */
-                 || (insn & (0x3f << 26)) == 46u << 26 /* lmw */
-                 || (insn & (0x3f << 26)) == 47u << 26 /* stmw */
-                 || (insn & (0x3f << 26)) == 48u << 26 /* lfs */
-                 || (insn & (0x3f << 26)) == 50u << 26 /* lfd */
-                 || (insn & (0x3f << 26)) == 52u << 26 /* stfs */
-                 || (insn & (0x3f << 26)) == 54u << 26 /* stfd */
-                 || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */
-                     && (insn & 3) != 1)
-                 || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */
-                     && ((insn & 3) == 0 || (insn & 3) == 3)))
+             if ((insn & (0x3f << 26)) == 12u << 26 /* addic */)
                {
-                 unsigned int reg = (insn >> 16) & 0x1f;
-                 const Elf_Internal_Rela *ha;
-                 bfd_boolean match_addend;
-
-                 match_addend = (sym != NULL
-                                 && ELF_ST_TYPE (sym->st_info) == STT_SECTION);
-                 ha = ha_reloc_match (relocs, rel, &reg, match_addend,
-                                      input_bfd, contents);
-                 if (ha != NULL)
-                   {
-                     insn &= ~(0x1f << 16);
-                     insn |= reg << 16;
-                     bfd_put_32 (input_bfd, insn, p);
-                     if (ha_opt == NULL)
-                       {
-                         ha_opt = bfd_zmalloc (input_section->reloc_count);
-                         if (ha_opt == NULL)
-                           return FALSE;
-                       }
-                     ha_opt[ha - relocs] = 1;
-                   }
-                 else
-                   /* If we don't find a matching high part insn,
-                      something is fishy.  Refuse to nop any high
-                      part insn in this section.  */
-                   no_ha_opt = TRUE;
+                 /* Transform addic to addi when we change reg.  */
+                 insn &= ~((0x3f << 26) | (0x1f << 16));
+                 insn |= (14u << 26) | (2 << 16);
+               }
+             else
+               {
+                 insn &= ~(0x1f << 16);
+                 insn |= 2 << 16;
                }
+             bfd_put_32 (input_bfd, insn, p);
            }
          break;
        }
@@ -13026,21 +14477,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,
@@ -13093,9 +14543,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
            mask = 15;
          if (((relocation + addend) & mask) != 0)
            {
-             (*_bfd_error_handler)
-               (_("%B: error: relocation %s not a multiple of %d"),
-                input_bfd,
+             info->callbacks->einfo
+               (_("%P: %H: error: %s not a multiple of %u\n"),
+                input_bfd, input_section, rel->r_offset,
                 ppc64_elf_howto_table[r_type]->name,
                 mask + 1);
              bfd_set_error (bfd_error_bad_value);
@@ -13110,13 +14560,13 @@ ppc64_elf_relocate_section (bfd *output_bfd,
         not process them.  */
       if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
-              && h->elf.def_dynamic))
+              && h->elf.def_dynamic)
+         && _bfd_elf_section_offset (output_bfd, info, input_section,
+                                     rel->r_offset) != (bfd_vma) -1)
        {
-         (*_bfd_error_handler)
-           (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
-            input_bfd,
-            input_section,
-            (long) rel->r_offset,
+         info->callbacks->einfo
+           (_("%P: %H: unresolvable %s against `%T'\n"),
+            input_bfd, input_section, rel->r_offset,
             ppc64_elf_howto_table[(int) r_type]->name,
             h->elf.root.root.string);
          ret = FALSE;
@@ -13132,8 +14582,21 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
       if (r != bfd_reloc_ok)
        {
-         if (sym_name == NULL)
-           sym_name = "(null)";
+         char *more_info = NULL;
+         const char *reloc_name = ppc64_elf_howto_table[r_type]->name;
+
+         if (reloc_dest != DEST_NORMAL)
+           {
+             more_info = bfd_malloc (strlen (reloc_name) + 8);
+             if (more_info != NULL)
+               {
+                 strcpy (more_info, reloc_name);
+                 strcat (more_info, (reloc_dest == DEST_OPD
+                                     ? " (OPD)" : " (stub)"));
+                 reloc_name = more_info;
+               }
+           }
+
          if (r == bfd_reloc_overflow)
            {
              if (warned)
@@ -13152,43 +14615,24 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                }
 
              if (!((*info->callbacks->reloc_overflow)
-                   (info, (h ? &h->elf.root : NULL), sym_name,
-                    ppc64_elf_howto_table[r_type]->name,
-                    orig_addend, input_bfd, input_section, rel->r_offset)))
+                   (info, &h->elf.root, sym_name,
+                    reloc_name, orig_rel.r_addend,
+                    input_bfd, input_section, rel->r_offset)))
                return FALSE;
            }
          else
            {
-             (*_bfd_error_handler)
-               (_("%B(%A+0x%lx): %s reloc against `%s': error %d"),
-                input_bfd,
-                input_section,
-                (long) rel->r_offset,
-                ppc64_elf_howto_table[r_type]->name,
-                sym_name,
-                (int) r);
+             info->callbacks->einfo
+               (_("%P: %H: %s against `%T': error %d\n"),
+                input_bfd, input_section, rel->r_offset,
+                reloc_name, sym_name, (int) r);
              ret = FALSE;
            }
+         if (more_info != NULL)
+           free (more_info);
        }
     }
 
-  if (ha_opt != NULL)
-    {
-      if (!no_ha_opt)
-       {
-         unsigned char *opt = ha_opt;
-         rel = relocs;
-         relend = relocs + input_section->reloc_count;
-         for (; rel < relend; opt++, rel++)
-           if (*opt != 0)
-             {
-               bfd_byte *p = contents + (rel->r_offset & ~3);
-               bfd_put_32 (input_bfd, NOP, p);
-             }
-       }
-      free (ha_opt);
-    }
-
   /* If we're emitting relocations, then shortly after this function
      returns, reloc offsets and addends for this section will be
      adjusted.  Worse, reloc symbol indices will be for the output
@@ -13199,8 +14643,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       bfd_size_type amt;
       amt = input_section->reloc_count * sizeof (Elf_Internal_Rela);
       rel = bfd_alloc (input_bfd, amt);
-      BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd_relocs == NULL);
-      ppc64_elf_tdata (input_bfd)->opd_relocs = rel;
+      BFD_ASSERT (ppc64_elf_tdata (input_bfd)->opd.relocs == NULL);
+      ppc64_elf_tdata (input_bfd)->opd.relocs = rel;
       if (rel == NULL)
        return FALSE;
       memcpy (rel, relocs, amt);
@@ -13247,7 +14691,7 @@ static bfd_boolean
 ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
                                 struct bfd_link_info *info,
                                 struct elf_link_hash_entry *h,
-                                Elf_Internal_Sym *sym)
+                                Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
 {
   struct ppc_link_hash_table *htab;
   struct plt_entry *ent;
@@ -13270,30 +14714,57 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
                        && h->def_regular
                        && (h->root.type == bfd_link_hash_defined
                            || h->root.type == bfd_link_hash_defweak));
-           rela.r_offset = (htab->iplt->output_section->vma
-                            + htab->iplt->output_offset
+           rela.r_offset = (htab->elf.iplt->output_section->vma
+                            + htab->elf.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
                             + ent->addend);
-           loc = (htab->reliplt->contents
-                  + (htab->reliplt->reloc_count++
+           loc = (htab->elf.irelplt->contents
+                  + (htab->elf.irelplt->reloc_count++
                      * sizeof (Elf64_External_Rela)));
          }
        else
          {
-           rela.r_offset = (htab->plt->output_section->vma
-                            + htab->plt->output_offset
+           rela.r_offset = (htab->elf.splt->output_section->vma
+                            + htab->elf.splt->output_offset
                             + ent->plt.offset);
            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))));
+           loc = (htab->elf.srelplt->contents
+                  + ((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)
@@ -13316,10 +14787,6 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
     }
 
-  /* Mark some specially defined symbols as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0)
-    sym->st_shndx = SHN_ABS;
-
   return TRUE;
 }
 
@@ -13327,9 +14794,15 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
    dynamic linker, before writing them out.  */
 
 static enum elf_reloc_type_class
-ppc64_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+ppc64_elf_reloc_type_class (const struct bfd_link_info *info,
+                           const asection *rel_sec,
+                           const Elf_Internal_Rela *rela)
 {
   enum elf_ppc64_reloc_type r_type;
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+
+  if (rel_sec == htab->elf.irelplt)
+    return reloc_class_ifunc;
 
   r_type = ELF64_R_TYPE (rela->r_info);
   switch (r_type)
@@ -13360,13 +14833,13 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
     return FALSE;
 
   dynobj = htab->elf.dynobj;
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (htab->elf.dynamic_sections_created)
     {
       Elf64_External_Dyn *dyncon, *dynconend;
 
-      if (sdyn == NULL || htab->got == NULL)
+      if (sdyn == NULL || htab->elf.sgot == NULL)
        abort ();
 
       dyncon = (Elf64_External_Dyn *) sdyn->contents;
@@ -13390,7 +14863,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:
@@ -13400,6 +14873,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)
@@ -13408,23 +14886,23 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTGOT:
-             s = htab->plt;
+             s = htab->elf.splt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_JMPREL:
-             s = htab->relplt;
+             s = htab->elf.srelplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_PLTRELSZ:
-             dyn.d_un.d_val = htab->relplt->size;
+             dyn.d_un.d_val = htab->elf.srelplt->size;
              break;
 
            case DT_RELASZ:
              /* Don't count procedure linkage table relocs in the
                 overall reloc count.  */
-             s = htab->relplt;
+             s = htab->elf.srelplt;
              if (s == NULL)
                continue;
              dyn.d_un.d_val -= s->size;
@@ -13434,7 +14912,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
              /* We may not be using the standard ELF linker script.
                 If .rela.plt is the first .rela section, we adjust
                 DT_RELA to not include it.  */
-             s = htab->relplt;
+             s = htab->elf.srelplt;
              if (s == NULL)
                continue;
              if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
@@ -13447,23 +14925,23 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  if (htab->got != NULL && htab->got->size != 0)
+  if (htab->elf.sgot != NULL && htab->elf.sgot->size != 0)
     {
       /* Fill in the first entry in the global offset table.
         We use it to hold the link-time TOCbase.  */
       bfd_put_64 (output_bfd,
                  elf_gp (output_bfd) + TOC_BASE_OFF,
-                 htab->got->contents);
+                 htab->elf.sgot->contents);
 
       /* Set .got entry size.  */
-      elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 8;
+      elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 8;
     }
 
-  if (htab->plt != NULL && htab->plt->size != 0)
+  if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
     {
       /* Set .plt entry size.  */
-      elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
-       = PLT_ENTRY_SIZE;
+      elf_section_data (htab->elf.splt->output_section)->this_hdr.sh_entsize
+       = PLT_ENTRY_SIZE (htab);
     }
 
   /* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
@@ -13472,7 +14950,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
       && htab->brlt->reloc_count != 0
       && !_bfd_elf_link_output_relocs (output_bfd,
                                       htab->brlt,
-                                      &elf_section_data (htab->brlt)->rel_hdr,
+                                      elf_section_data (htab->brlt)->rela.hdr,
                                       elf_section_data (htab->brlt)->relocs,
                                       NULL))
     return FALSE;
@@ -13481,11 +14959,19 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
       && htab->glink->reloc_count != 0
       && !_bfd_elf_link_output_relocs (output_bfd,
                                       htab->glink,
-                                      &elf_section_data (htab->glink)->rel_hdr,
+                                      elf_section_data (htab->glink)->rela.hdr,
                                       elf_section_data (htab->glink)->relocs,
                                       NULL))
     return FALSE;
 
+
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+                                          htab->glink_eh_frame,
+                                          htab->glink_eh_frame->contents))
+    return FALSE;
+
   /* We need to handle writing out multiple GOT sections ourselves,
      since we didn't add them to DYNOBJ.  We know dynobj is the first
      bfd.  */
@@ -13518,3 +15004,22 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
 }
 
 #include "elf64-target.h"
+
+/* FreeBSD support */
+
+#undef  TARGET_LITTLE_SYM
+#undef  TARGET_LITTLE_NAME
+
+#undef  TARGET_BIG_SYM
+#define TARGET_BIG_SYM bfd_elf64_powerpc_freebsd_vec
+#undef  TARGET_BIG_NAME
+#define TARGET_BIG_NAME "elf64-powerpc-freebsd"
+
+#undef  ELF_OSABI
+#define        ELF_OSABI       ELFOSABI_FREEBSD
+
+#undef  elf64_bed
+#define elf64_bed      elf64_powerpc_fbsd_bed
+
+#include "elf64-target.h"
+