Add support for locating separate debug info files via the build-id method.
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index b1c75a675f2db7b24123974ea7b58b34ff4c1337..989f785276441faac76e2b930ee0ad51ee839887 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 32-bit ELF
-   Copyright (C) 1994-2016 Free Software Foundation, Inc.
+   Copyright (C) 1994-2017 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -35,6 +35,7 @@
 #include "elf32-ppc.h"
 #include "elf-vxworks.h"
 #include "dwarf2.h"
+#include "opcode/ppc.h"
 
 typedef enum split16_format_type
 {
@@ -413,7 +414,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_GOT16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -429,7 +430,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_GOT16_LO",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -445,7 +446,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_GOT16_HI",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -461,7 +462,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        ppc_elf_addr16_ha_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_GOT16_HA",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -476,8 +477,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         26,                    /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_signed,  /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        complain_overflow_signed, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLTREL24",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -496,7 +497,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_COPY",          /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -512,7 +513,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_GLOB_DAT",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -527,7 +528,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_JMP_SLOT",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -622,7 +623,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLT32",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -638,7 +639,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLTREL32",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -654,7 +655,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLT16_LO",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -670,7 +671,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLT16_HI",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -686,7 +687,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        ppc_elf_addr16_ha_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_PLT16_HA",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -702,7 +703,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_SDAREL16",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -717,7 +718,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_SECTOFF",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -732,7 +733,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_SECTOFF_LO",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -747,7 +748,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_SECTOFF_HI",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -762,7 +763,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        ppc_elf_addr16_ha_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_SECTOFF_HA",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1238,7 +1239,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_NADDR32",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1253,7 +1254,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_NADDR16",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1268,7 +1269,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_ADDR16_LO", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1283,7 +1284,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_NADDR16_HI", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1300,7 +1301,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        ppc_elf_addr16_ha_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_NADDR16_HA", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1317,7 +1318,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_SDAI16",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1334,7 +1335,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_SDA2I16",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1350,7 +1351,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_SDA2REL",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1367,7 +1368,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_SDA21",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1391,7 +1392,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_EMB_RELSDA",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1425,7 +1426,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_REL15",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0xfe,                  /* dst_mask */
+        0xfffe,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   /* A relative 24 bit branch.  */
@@ -1451,11 +1452,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_VLE_LO16A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* The 16 LSBS in split16d format.  */
@@ -1466,11 +1467,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_LO16D",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_LO16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 split16a format.  */
@@ -1481,11 +1482,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_HI16A",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_HI16A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 split16d format.  */
@@ -1496,11 +1497,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_HI16D",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_HI16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (High Adjusted) in split16a format.  */
@@ -1511,11 +1512,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_HA16A",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_HA16A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (High Adjusted) in split16d format.  */
@@ -1526,11 +1527,11 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_HA16D",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_HA16D",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
@@ -1543,8 +1544,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
-        "R_PPC_VLE_SDA21",             /* name */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDA21",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
@@ -1558,7 +1559,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_VLE_SDA21_LO",  /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1572,12 +1573,12 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_dont,        /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_SDAREL_LO16A",      /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_LO16A", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16d format.  */
@@ -1587,72 +1588,72 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_dont,        /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
-        "R_PPC_VLE_SDAREL_LO16D",              /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_LO16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
-  HOWTO (R_PPC_VLE_SDAREL_HI16A,       /* type */
+  HOWTO (R_PPC_VLE_SDAREL_HI16A, /* type */
         16,                    /* rightshift */
         2,                     /* 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_PPC_VLE_SDAREL_HI16A",      /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_HI16A", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
-  HOWTO (R_PPC_VLE_SDAREL_HI16D,       /* type */
+  HOWTO (R_PPC_VLE_SDAREL_HI16D, /* type */
         16,                    /* rightshift */
         2,                     /* 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_PPC_VLE_SDAREL_HI16D",      /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_HI16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
-  HOWTO (R_PPC_VLE_SDAREL_HA16A,       /* type */
+  HOWTO (R_PPC_VLE_SDAREL_HA16A, /* type */
         16,                    /* rightshift */
         2,                     /* 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_PPC_VLE_SDAREL_HA16A",      /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_HA16A", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f007ff,             /* dst_mask */
+        0x1f07ff,              /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
-  HOWTO (R_PPC_VLE_SDAREL_HA16D,       /* type */
+  HOWTO (R_PPC_VLE_SDAREL_HA16D, /* type */
         16,                    /* rightshift */
         2,                     /* 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_PPC_VLE_SDAREL_HA16D",      /* name */
+        complain_overflow_dont, /* complain_on_overflow */
+        ppc_elf_unhandled_reloc, /* special_function */
+        "R_PPC_VLE_SDAREL_HA16D", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x1f07ff,              /* dst_mask */
+        0x1f007ff,             /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   HOWTO (R_PPC_IRELATIVE,      /* type */
@@ -1662,7 +1663,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc,  /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_IRELATIVE",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1783,7 +1784,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        ppc_elf_unhandled_reloc, /* special_function */
         "R_PPC_TOC16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -2041,8 +2042,9 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
   r_type = ELF32_R_TYPE (dst->r_info);
   if (r_type >= R_PPC_max)
     {
-      (*_bfd_error_handler) (_("%B: unrecognised PPC reloc number: %d"),
-                            abfd, r_type);
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%B: unrecognised PPC reloc number: %d"),
+                         abfd, r_type);
       bfd_set_error (bfd_error_bad_value);
       r_type = R_PPC_NONE;
     }
@@ -2052,8 +2054,9 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
      ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation.  */
   if (!cache_ptr->howto)
     {
-      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-                             abfd, r_type);
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%B: invalid relocation type %d"),
+                         abfd, r_type);
       bfd_set_error (bfd_error_bad_value);
 
       cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE];
@@ -2246,6 +2249,7 @@ _bfd_elf_ppc_set_arch (bfd *abfd)
                case PPC_APUINFO_BRLOCK:
                  if (mach != bfd_mach_ppc_vle)
                    mach = bfd_mach_ppc_e500;
+                 break;
 
                case PPC_APUINFO_VLE:
                  mach = bfd_mach_ppc_vle;
@@ -2443,18 +2447,6 @@ ppc_elf_lookup_section_flags (char *flag_name)
   return 0;
 }
 
-/* Add the VLE flag if required.  */
-
-bfd_boolean
-ppc_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *shdr)
-{
-  if (bfd_get_mach (abfd) == bfd_mach_ppc_vle
-      && (shdr->sh_flags & SHF_EXECINSTR) != 0)
-    shdr->sh_flags |= SHF_PPC_VLE;
-
-  return TRUE;
-}
-
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -2534,10 +2526,7 @@ bfd_boolean
 ppc_elf_modify_segment_map (bfd *abfd,
                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
-  struct elf_segment_map *m, *n;
-  bfd_size_type amt;
-  unsigned int j, k;
-  bfd_boolean sect0_vle, sectj_vle;
+  struct elf_segment_map *m;
 
   /* At this point in the link, output sections have already been sorted by
      LMA and assigned to segments.  All that is left to do is to ensure
@@ -2547,25 +2536,59 @@ ppc_elf_modify_segment_map (bfd *abfd,
 
   for (m = elf_seg_map (abfd); m != NULL; m = m->next)
     {
-      if (m->count == 0)
+      struct elf_segment_map *n;
+      bfd_size_type amt;
+      unsigned int j, k;
+      unsigned int p_flags;
+
+      if (m->p_type != PT_LOAD || m->count == 0)
        continue;
 
-      sect0_vle = (elf_section_flags (m->sections[0]) & SHF_PPC_VLE) != 0;
-      for (j = 1; j < m->count; ++j)
+      for (p_flags = PF_R, j = 0; j != m->count; ++j)
        {
-         sectj_vle = (elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0;
+         if ((m->sections[j]->flags & SEC_READONLY) == 0)
+           p_flags |= PF_W;
+         if ((m->sections[j]->flags & SEC_CODE) != 0)
+           {
+             p_flags |= PF_X;
+             if ((elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0)
+               p_flags |= PF_PPC_VLE;
+             break;
+           }
+       }
+      if (j != m->count)
+       while (++j != m->count)
+         {
+           unsigned int p_flags1 = PF_R;
 
-         if (sectj_vle != sect0_vle)
-           break;
-        }
-      if (j >= m->count)
+           if ((m->sections[j]->flags & SEC_READONLY) == 0)
+             p_flags1 |= PF_W;
+           if ((m->sections[j]->flags & SEC_CODE) != 0)
+             {
+               p_flags1 |= PF_X;
+               if ((elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0)
+                 p_flags1 |= PF_PPC_VLE;
+               if (((p_flags1 ^ p_flags) & PF_PPC_VLE) != 0)
+                 break;
+             }
+           p_flags |= p_flags1;
+         }
+      /* If we're splitting a segment which originally contained rw
+        sections then those sections might now only be in one of the
+        two parts.  So always set p_flags if splitting, even if we
+        are being called for objcopy with p_flags_valid set.  */
+      if (j != m->count || !m->p_flags_valid)
+       {
+         m->p_flags_valid = 1;
+         m->p_flags = p_flags;
+       }
+      if (j == m->count)
        continue;
 
-      /* sections 0..j-1 stay in this (current) segment,
+      /* Sections 0..j-1 stay in this (current) segment,
         the remainder are put in a new segment.
         The scan resumes with the new segment.  */
 
-      /* Fix the new segment.  */
       amt = sizeof (struct elf_segment_map);
       amt += (m->count - j - 1) * sizeof (asection *);
       n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -2573,20 +2596,13 @@ ppc_elf_modify_segment_map (bfd *abfd,
         return FALSE;
 
       n->p_type = PT_LOAD;
-      n->p_flags = PF_X | PF_R;
-      if (sectj_vle)
-        n->p_flags |= PF_PPC_VLE;
       n->count = m->count - j;
       for (k = 0; k < n->count; ++k)
-        {
-          n->sections[k] = m->sections[j+k];
-          m->sections[j+k] = NULL;
-       }
+       n->sections[k] = m->sections[j + k];
+      m->count = j;
+      m->p_size_valid = 0;
       n->next = m->next;
       m->next = n;
-
-      /* Fix the current segment  */
-      m->count = j;
     }
 
   return TRUE;
@@ -2745,6 +2761,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
       if (asec == NULL)
        continue;
 
+      /* xgettext:c-format */
       error_message = _("corrupt %s section in %B");
       length = asec->size;
       if (length < 20)
@@ -2764,6 +2781,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
       if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
          || (bfd_bread (buffer, length, ibfd) != length))
        {
+         /* xgettext:c-format */
          error_message = _("unable to read in %s section from %B");
          goto fail;
        }
@@ -2805,6 +2823,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
       if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4))
        {
          ibfd = abfd;
+         /* xgettext:c-format */
          error_message = _("warning: unable to set size of %s section in %B");
        }
     }
@@ -2814,7 +2833,7 @@ ppc_elf_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
     free (buffer);
 
   if (error_message)
-    (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME);
+    _bfd_error_handler (error_message, ibfd, APUINFO_SECTION_NAME);
 }
 
 /* Prevent the output section from accumulating the input sections'
@@ -2854,7 +2873,7 @@ ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
   buffer = bfd_malloc (length);
   if (buffer == NULL)
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("failed to allocate space for new APUinfo section."));
       return;
     }
@@ -2874,10 +2893,10 @@ ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
     }
 
   if (length != asec->size)
-    (*_bfd_error_handler) (_("failed to compute new APUinfo section."));
+    _bfd_error_handler (_("failed to compute new APUinfo section."));
 
   if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length))
-    (*_bfd_error_handler) (_("failed to install new APUinfo section."));
+    _bfd_error_handler (_("failed to install new APUinfo section."));
 
   free (buffer);
 
@@ -3256,15 +3275,7 @@ struct ppc_elf_link_hash_table
   struct ppc_elf_params *params;
 
   /* Short-cuts to get to dynamic linker sections.  */
-  asection *got;
-  asection *relgot;
   asection *glink;
-  asection *plt;
-  asection *relplt;
-  asection *iplt;
-  asection *reliplt;
-  asection *dynbss;
-  asection *relbss;
   asection *dynsbss;
   asection *relsbss;
   elf_linker_section_t sdata[2];
@@ -3274,9 +3285,6 @@ struct ppc_elf_link_hash_table
   /* The (unloaded but important) .rela.plt.unloaded on VxWorks.  */
   asection *srelplt2;
 
-  /* The .got.plt section (VxWorks only)*/
-  asection *sgotplt;
-
   /* Shortcut to __tls_get_addr.  */
   struct elf_link_hash_entry *tls_get_addr;
 
@@ -3366,7 +3374,7 @@ ppc_elf_link_hash_table_create (bfd *abfd)
 {
   struct ppc_elf_link_hash_table *ret;
   static struct ppc_elf_params default_params
-    = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 };
+    = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0, 0 };
 
   ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
   if (ret == NULL)
@@ -3421,37 +3429,21 @@ static bfd_boolean
 ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info)
 {
   struct ppc_elf_link_hash_table *htab;
-  asection *s;
-  flagword flags;
 
   if (!_bfd_elf_create_got_section (abfd, info))
     return FALSE;
 
   htab = ppc_elf_hash_table (info);
-  htab->got = s = bfd_get_linker_section (abfd, ".got");
-  if (s == NULL)
-    abort ();
-
-  if (htab->is_vxworks)
-    {
-      htab->sgotplt = bfd_get_linker_section (abfd, ".got.plt");
-      if (!htab->sgotplt)
-       abort ();
-    }
-  else
+  if (!htab->is_vxworks)
     {
       /* The powerpc .got has a blrl instruction in it.  Mark it
         executable.  */
-      flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS
-              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-      if (!bfd_set_section_flags (abfd, s, flags))
+      flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS
+                       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      if (!bfd_set_section_flags (abfd, htab->elf.sgot, flags))
        return FALSE;
     }
 
-  htab->relgot = bfd_get_linker_section (abfd, ".rela.got");
-  if (!htab->relgot)
-    abort ();
-
   return TRUE;
 }
 
@@ -3514,7 +3506,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
 
   flags = SEC_ALLOC | SEC_LINKER_CREATED;
   s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags);
-  htab->iplt = s;
+  htab->elf.iplt = s;
   if (s == NULL
       || !bfd_set_section_alignment (abfd, s, 4))
     return FALSE;
@@ -3522,7 +3514,7 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
           | SEC_IN_MEMORY | SEC_LINKER_CREATED);
   s = bfd_make_section_anyway_with_flags (abfd, ".rela.iplt", flags);
-  htab->reliplt = s;
+  htab->elf.irelplt = s;
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, 2))
     return FALSE;
@@ -3551,7 +3543,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   htab = ppc_elf_hash_table (info);
 
-  if (htab->got == NULL
+  if (htab->elf.sgot == NULL
       && !ppc_elf_create_got (abfd, info))
     return FALSE;
 
@@ -3562,7 +3554,6 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       && !ppc_elf_create_glink (abfd, info))
     return FALSE;
 
-  htab->dynbss = bfd_get_linker_section (abfd, ".dynbss");
   s = bfd_make_section_anyway_with_flags (abfd, ".dynsbss",
                                          SEC_ALLOC | SEC_LINKER_CREATED);
   htab->dynsbss = s;
@@ -3571,7 +3562,6 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   if (! bfd_link_pic (info))
     {
-      htab->relbss = bfd_get_linker_section (abfd, ".rela.bss");
       flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
       s = bfd_make_section_anyway_with_flags (abfd, ".rela.sbss", flags);
@@ -3585,11 +3575,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
     return FALSE;
 
-  htab->relplt = bfd_get_linker_section (abfd, ".rela.plt");
-  htab->plt = s = bfd_get_linker_section (abfd, ".plt");
-  if (s == NULL)
-    abort ();
-
+  s = htab->elf.splt;
   flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED;
   if (htab->plt_type == PLT_VXWORKS)
     /* The VxWorks PLT is a loaded section with contents.  */
@@ -3620,7 +3606,8 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
        && edir->elf.dynamic_adjusted))
     edir->elf.non_got_ref |= eind->elf.non_got_ref;
 
-  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
+  if (edir->elf.versioned != versioned_hidden)
+    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;
@@ -3948,13 +3935,15 @@ is_branch_reloc (enum elf_ppc_reloc_type r_type)
          || r_type == R_PPC_ADDR24
          || r_type == R_PPC_ADDR14
          || r_type == R_PPC_ADDR14_BRTAKEN
-         || r_type == R_PPC_ADDR14_BRNTAKEN);
+         || r_type == R_PPC_ADDR14_BRNTAKEN
+         || r_type == R_PPC_VLE_REL24);
 }
 
 static void
 bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
 {
-  (*_bfd_error_handler)
+  _bfd_error_handler
+    /* xgettext:c-format */
     (_("%B: relocation %s cannot be used when making a shared object"),
      abfd,
      ppc_elf_howto_table[r_type]->name);
@@ -4045,7 +4034,7 @@ ppc_elf_check_relocs (bfd *abfd,
         This shows up in particular in an R_PPC_ADDR32 in the eabi
         startup code.  */
       if (h != NULL
-         && htab->got == NULL
+         && htab->elf.sgot == NULL
          && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
        {
          if (htab->elf.dynobj == NULL)
@@ -4146,7 +4135,7 @@ ppc_elf_check_relocs (bfd *abfd,
          tls_type = TLS_TLS | TLS_DTPREL;
        dogottls:
          sec->has_tls_reloc = 1;
-         /* Fall thru */
+         /* Fall through.  */
 
          /* GOT16 relocations */
        case R_PPC_GOT16:
@@ -4154,7 +4143,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_GOT16_HI:
        case R_PPC_GOT16_HA:
          /* This symbol requires a global offset table entry.  */
-         if (htab->got == NULL)
+         if (htab->elf.sgot == NULL)
            {
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
@@ -4218,7 +4207,7 @@ ppc_elf_check_relocs (bfd *abfd,
 
        case R_PPC_SDAREL16:
          htab->sdata[0].sym->ref_regular = 1;
-         /* Fall thru */
+         /* Fall through.  */
 
        case R_PPC_VLE_SDAREL_LO16A:
        case R_PPC_VLE_SDAREL_LO16D:
@@ -4308,6 +4297,7 @@ ppc_elf_check_relocs (bfd *abfd,
                  /* It does not make sense to have a procedure linkage
                     table entry for a non-ifunc local symbol.  */
                  info->callbacks->einfo
+                   /* xgettext:c-format */
                    (_("%P: %H: %s reloc against local symbol\n"),
                     abfd, sec, rel->r_offset,
                     ppc_elf_howto_table[r_type]->name);
@@ -4389,15 +4379,6 @@ ppc_elf_check_relocs (bfd *abfd,
            }
          if (h != NULL && h->type == STT_GNU_IFUNC)
            {
-             if (bfd_link_pic (info))
-               {
-                 info->callbacks->einfo
-                   (_("%P: %H: @local call to ifunc %s\n"),
-                    abfd, sec, rel->r_offset,
-                    h->root.root.string);
-                 bfd_set_error (bfd_error_bad_value);
-                 return FALSE;
-               }
              h->needs_plt = 1;
              if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
                return FALSE;
@@ -4648,68 +4629,98 @@ ppc_elf_check_relocs (bfd *abfd,
   return TRUE;
 }
 \f
-
-/* Merge object attributes from IBFD into OBFD.  Raise an error if
-   there are conflicting attributes.  */
-static bfd_boolean
-ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
+/* Warn for conflicting Tag_GNU_Power_ABI_FP attributes between IBFD
+   and OBFD, and merge non-conflicting ones.  */
+void
+_bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
   obj_attribute *in_attr, *in_attrs;
   obj_attribute *out_attr, *out_attrs;
 
-  if (!elf_known_obj_attributes_proc (obfd)[0].i)
-    {
-      /* This is the first object.  Copy the attributes.  */
-      _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
-      /* Use the Tag_null value to indicate the attributes have been
-        initialized.  */
-      elf_known_obj_attributes_proc (obfd)[0].i = 1;
-
-      return TRUE;
-    }
-
   in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
   out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
 
-  /* Check for conflicting Tag_GNU_Power_ABI_FP attributes and merge
-     non-conflicting ones.  */
   in_attr = &in_attrs[Tag_GNU_Power_ABI_FP];
   out_attr = &out_attrs[Tag_GNU_Power_ABI_FP];
+
   if (in_attr->i != out_attr->i)
     {
-      out_attr->type = 1;
-      if (out_attr->i == 0)
-       out_attr->i = in_attr->i;
-      else if (in_attr->i == 0)
+      int in_fp = in_attr->i & 3;
+      int out_fp = out_attr->i & 3;
+
+      if (in_fp == 0)
        ;
-      else if (out_attr->i == 1 && in_attr->i == 2)
+      else if (out_fp == 0)
+       {
+         out_attr->type = 1;
+         out_attr->i ^= in_fp;
+       }
+      else if (out_fp != 2 && in_fp == 2)
        _bfd_error_handler
+         /* xgettext:c-format */
          (_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd);
-      else if (out_attr->i == 1 && in_attr->i == 3)
+      else if (out_fp == 2 && in_fp != 2)
+       _bfd_error_handler
+         /* xgettext:c-format */
+         (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
+      else if (out_fp == 1 && in_fp == 3)
        _bfd_error_handler
-         (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
-         obfd, ibfd);
-      else if (out_attr->i == 3 && in_attr->i == 1)
+         /* xgettext:c-format */
+         (_("Warning: %B uses double-precision hard float, "
+            "%B uses single-precision hard float"), obfd, ibfd);
+      else if (out_fp == 3 && in_fp == 1)
        _bfd_error_handler
-         (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
-         ibfd, obfd);
-      else if (out_attr->i == 3 && in_attr->i == 2)
+         /* xgettext:c-format */
+         (_("Warning: %B uses double-precision hard float, "
+            "%B uses single-precision hard float"), ibfd, obfd);
+
+      in_fp = in_attr->i & 0xc;
+      out_fp = out_attr->i & 0xc;
+      if (in_fp == 0)
+       ;
+      else if (out_fp == 0)
+       {
+         out_attr->type = 1;
+         out_attr->i ^= in_fp;
+       }
+      else if (out_fp != 2 * 4 && in_fp == 2 * 4)
        _bfd_error_handler
-         (_("Warning: %B uses soft float, %B uses single-precision hard float"),
-         ibfd, obfd);
-      else if (out_attr->i == 2 && (in_attr->i == 1 || in_attr->i == 3))
+         /* xgettext:c-format */
+         (_("Warning: %B uses 64-bit long double, "
+            "%B uses 128-bit long double"), ibfd, obfd);
+      else if (in_fp != 2 * 4 && out_fp == 2 * 4)
        _bfd_error_handler
-         (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
-      else if (in_attr->i > 3)
+         /* xgettext:c-format */
+         (_("Warning: %B uses 64-bit long double, "
+            "%B uses 128-bit long double"), obfd, ibfd);
+      else if (out_fp == 1 * 4 && in_fp == 3 * 4)
        _bfd_error_handler
-         (_("Warning: %B uses unknown floating point ABI %d"), ibfd,
-          in_attr->i);
-      else
+         /* xgettext:c-format */
+         (_("Warning: %B uses IBM long double, "
+            "%B uses IEEE long double"), ibfd, obfd);
+      else if (out_fp == 3 * 4 && in_fp == 1 * 4)
        _bfd_error_handler
-         (_("Warning: %B uses unknown floating point ABI %d"), obfd,
-          out_attr->i);
+         /* xgettext:c-format */
+         (_("Warning: %B uses IBM long double, "
+            "%B uses IEEE long double"), obfd, ibfd);
     }
+}
+
+/* Merge object attributes from IBFD into OBFD.  Warn if
+   there are conflicting attributes.  */
+static bfd_boolean
+ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd;
+  obj_attribute *in_attr, *in_attrs;
+  obj_attribute *out_attr, *out_attrs;
+
+  _bfd_elf_ppc_merge_fp_attributes (ibfd, info);
+
+  obfd = info->output_bfd;
+  in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
 
   /* Check for conflicting Tag_GNU_Power_ABI_Vector attributes and
      merge non-conflicting ones.  */
@@ -4717,48 +4728,38 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
   out_attr = &out_attrs[Tag_GNU_Power_ABI_Vector];
   if (in_attr->i != out_attr->i)
     {
-      const char *in_abi = NULL, *out_abi = NULL;
-
-      switch (in_attr->i)
-       {
-       case 1: in_abi = "generic"; break;
-       case 2: in_abi = "AltiVec"; break;
-       case 3: in_abi = "SPE"; break;
-       }
+      int in_vec = in_attr->i & 3;
+      int out_vec = out_attr->i & 3;
 
-      switch (out_attr->i)
+      if (in_vec == 0)
+       ;
+      else if (out_vec == 0)
        {
-       case 1: out_abi = "generic"; break;
-       case 2: out_abi = "AltiVec"; break;
-       case 3: out_abi = "SPE"; break;
+         out_attr->type = 1;
+         out_attr->i = in_vec;
        }
-
-      out_attr->type = 1;
-      if (out_attr->i == 0)
-       out_attr->i = in_attr->i;
-      else if (in_attr->i == 0)
-       ;
       /* For now, allow generic to transition to AltiVec or SPE
         without a warning.  If GCC marked files with their stack
         alignment and used don't-care markings for files which are
         not affected by the vector ABI, we could warn about this
         case too.  */
-      else if (out_attr->i == 1)
-       out_attr->i = in_attr->i;
-      else if (in_attr->i == 1)
+      else if (in_vec == 1)
        ;
-      else if (in_abi == NULL)
-       _bfd_error_handler
-         (_("Warning: %B uses unknown vector ABI %d"), ibfd,
-          in_attr->i);
-      else if (out_abi == NULL)
+      else if (out_vec == 1)
+       {
+         out_attr->type = 1;
+         out_attr->i = in_vec;
+       }
+      else if (out_vec < in_vec)
        _bfd_error_handler
-         (_("Warning: %B uses unknown vector ABI %d"), obfd,
-          in_attr->i);
-      else
+         /* xgettext:c-format */
+         (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+          obfd, ibfd);
+      else if (out_vec > in_vec)
        _bfd_error_handler
-         (_("Warning: %B uses vector ABI \"%s\", %B uses \"%s\""),
-          ibfd, obfd, in_abi, out_abi);
+         /* xgettext:c-format */
+         (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+          ibfd, obfd);
     }
 
   /* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes
@@ -4767,29 +4768,30 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
   out_attr = &out_attrs[Tag_GNU_Power_ABI_Struct_Return];
   if (in_attr->i != out_attr->i)
     {
-      out_attr->type = 1;
-      if (out_attr->i == 0)
-       out_attr->i = in_attr->i;
-      else if (in_attr->i == 0)
+      int in_struct = in_attr->i & 3;
+      int out_struct = out_attr->i & 3;
+
+      if (in_struct == 0 || in_struct == 3)
        ;
-      else if (out_attr->i == 1 && in_attr->i == 2)
-       _bfd_error_handler
-         (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), obfd, ibfd);
-      else if (out_attr->i == 2 && in_attr->i == 1)
-       _bfd_error_handler
-         (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), ibfd, obfd);
-      else if (in_attr->i > 2)
-       _bfd_error_handler
-         (_("Warning: %B uses unknown small structure return convention %d"), ibfd,
-          in_attr->i);
-      else
-       _bfd_error_handler
-         (_("Warning: %B uses unknown small structure return convention %d"), obfd,
-          out_attr->i);
+      else if (out_struct == 0)
+       {
+         out_attr->type = 1;
+         out_attr->i = in_struct;
+       }
+      else if (out_struct < in_struct)
+       _bfd_error_handler
+         /* xgettext:c-format */
+         (_("Warning: %B uses r3/r4 for small structure returns, "
+            "%B uses memory"), obfd, ibfd);
+      else if (out_struct > in_struct)
+       _bfd_error_handler
+         /* xgettext:c-format */
+         (_("Warning: %B uses r3/r4 for small structure returns, "
+            "%B uses memory"), ibfd, obfd);
     }
 
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
-  _bfd_elf_merge_object_attributes (ibfd, obfd);
+  _bfd_elf_merge_object_attributes (ibfd, info);
 
   return TRUE;
 }
@@ -4798,8 +4800,9 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
    object file when linking.  */
 
 static bfd_boolean
-ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
   flagword old_flags;
   flagword new_flags;
   bfd_boolean error;
@@ -4808,10 +4811,10 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
     return TRUE;
 
   /* Check if we have the same endianness.  */
-  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+  if (! _bfd_generic_verify_endian_match (ibfd, info))
     return FALSE;
 
-  if (!ppc_elf_merge_obj_attributes (ibfd, obfd))
+  if (!ppc_elf_merge_obj_attributes (ibfd, info))
     return FALSE;
 
   new_flags = elf_elfheader (ibfd)->e_flags;
@@ -4837,7 +4840,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
          && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
        {
          error = TRUE;
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("%B: compiled with -mrelocatable and linked with "
               "modules compiled normally"), ibfd);
        }
@@ -4845,7 +4848,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
               && (old_flags & EF_PPC_RELOCATABLE) != 0)
        {
          error = TRUE;
-         (*_bfd_error_handler)
+         _bfd_error_handler
            (_("%B: compiled normally and linked with "
               "modules compiled with -mrelocatable"), ibfd);
        }
@@ -4872,7 +4875,8 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       if (new_flags != old_flags)
        {
          error = TRUE;
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: uses different e_flags (0x%lx) fields "
               "than previous modules (0x%lx)"),
             ibfd, (long) new_flags, (long) old_flags);
@@ -4889,21 +4893,61 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 }
 
 static void
-ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *loc,
+ppc_elf_vle_split16 (bfd *input_bfd,
+                    asection *input_section,
+                    unsigned long offset,
+                    bfd_byte *loc,
                     bfd_vma value,
-                    split16_format_type split16_format)
-
+                    split16_format_type split16_format,
+                    bfd_boolean fixup)
 {
-  unsigned int insn, top5;
-
-  insn = bfd_get_32 (output_bfd, loc);
+  unsigned int insn, opcode, top5;
+
+  insn = bfd_get_32 (input_bfd, loc);
+  opcode = insn & 0xf300f800;
+  if (opcode == E_OR2I_INSN
+      || opcode == E_AND2I_DOT_INSN
+      || opcode == E_OR2IS_INSN
+      || opcode == E_LIS_INSN
+      || opcode == E_AND2IS_DOT_INSN)
+    {
+      if (split16_format != split16a_type)
+       {
+         if (fixup)
+           split16_format = split16a_type;
+         else
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%B(%A+0x%lx): expected 16A style relocation on 0x%08x insn"),
+              input_bfd, input_section, offset, opcode);
+       }
+    }
+  else if (opcode == E_ADD2I_DOT_INSN
+          || opcode == E_ADD2IS_INSN
+          || opcode == E_CMP16I_INSN
+          || opcode == E_MULL2I_INSN
+          || opcode == E_CMPL16I_INSN
+          || opcode == E_CMPH16I_INSN
+          || opcode == E_CMPHL16I_INSN)
+    {
+      if (split16_format != split16d_type)
+       {
+         if (fixup)
+           split16_format = split16d_type;
+         else
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%B(%A+0x%lx): expected 16D style relocation on 0x%08x insn"),
+              input_bfd, input_section, offset, opcode);
+       }
+    }
   top5 = value & 0xf800;
-  top5 = top5 << (split16_format == split16a_type ? 9 : 5);
+  top5 = top5 << (split16_format == split16a_type ? 5 : 9);
+  insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x1f007ff);
   insn |= top5;
   insn |= value & 0x7ff;
-  bfd_put_32 (output_bfd, insn, loc);
+  bfd_put_32 (input_bfd, insn, loc);
 }
-
 \f
 /* Choose which PLT scheme to use, and set .plt flags appropriately.
    Returns -1 on error, 0 for old PLT, 1 for new PLT.  */
@@ -4982,13 +5026,13 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
 
       /* The new PLT is a loaded section.  */
-      if (htab->plt != NULL
-         && !bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags))
+      if (htab->elf.splt != NULL
+         && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.splt, flags))
        return -1;
 
       /* The new GOT is not executable.  */
-      if (htab->got != NULL
-         && !bfd_set_section_flags (htab->elf.dynobj, htab->got, flags))
+      if (htab->elf.sgot != NULL
+         && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.sgot, flags))
        return -1;
     }
   else
@@ -5155,7 +5199,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
        case R_PPC_REL32:
          if (h == NULL || h == htab->elf.hgot)
            break;
-         /* Fall thru */
+         /* Fall through.  */
 
        case R_PPC_ADDR32:
        case R_PPC_ADDR24:
@@ -5170,6 +5214,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
        case R_PPC_UADDR16:
          if (bfd_link_pic (info))
            break;
+         /* Fall through.  */
 
        case R_PPC_PLT32:
        case R_PPC_PLTREL24:
@@ -5260,11 +5305,11 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
        htab->params->no_tls_get_addr_opt = TRUE;
     }
   if (htab->plt_type == PLT_NEW
-      && htab->plt != NULL
-      && htab->plt->output_section != NULL)
+      && htab->elf.splt != NULL
+      && htab->elf.splt->output_section != NULL)
     {
-      elf_section_type (htab->plt->output_section) = SHT_PROGBITS;
-      elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE;
+      elf_section_type (htab->elf.splt->output_section) = SHT_PROGBITS;
+      elf_section_flags (htab->elf.splt->output_section) = SHF_ALLOC + SHF_WRITE;
     }
 
   return _bfd_elf_tls_setup (obfd, info);
@@ -5397,7 +5442,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
                    case R_PPC_GOT_TLSLD16:
                    case R_PPC_GOT_TLSLD16_LO:
                      expecting_tls_get_addr = 1;
-                     /* Fall thru */
+                     /* Fall through.  */
 
                    case R_PPC_GOT_TLSLD16_HI:
                    case R_PPC_GOT_TLSLD16_HA:
@@ -5415,7 +5460,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
                    case R_PPC_GOT_TLSGD16:
                    case R_PPC_GOT_TLSGD16_LO:
                      expecting_tls_get_addr = 1;
-                     /* Fall thru */
+                     /* Fall through.  */
 
                    case R_PPC_GOT_TLSGD16_HI:
                    case R_PPC_GOT_TLSGD16_HA:
@@ -5762,8 +5807,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   if (ppc_elf_hash_entry (h)->has_sda_refs)
     s = htab->dynsbss;
+  else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+    s = htab->elf.sdynrelro;
   else
-    s = htab->dynbss;
+    s = htab->elf.sdynbss;
   BFD_ASSERT (s != NULL);
 
   /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
@@ -5776,8 +5823,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
       if (ppc_elf_hash_entry (h)->has_sda_refs)
        srel = htab->relsbss;
+      else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+       srel = htab->elf.sreldynrelro;
       else
-       srel = htab->relbss;
+       srel = htab->elf.srelbss;
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
@@ -5850,8 +5899,8 @@ allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
 
   if (htab->plt_type == PLT_VXWORKS)
     {
-      where = htab->got->size;
-      htab->got->size += need;
+      where = htab->elf.sgot->size;
+      htab->elf.sgot->size += need;
     }
   else
     {
@@ -5863,14 +5912,14 @@ allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
        }
       else
        {
-         if (htab->got->size + need > max_before_header
-             && htab->got->size <= max_before_header)
+         if (htab->elf.sgot->size + need > max_before_header
+             && htab->elf.sgot->size <= max_before_header)
            {
-             htab->got_gap = max_before_header - htab->got->size;
-             htab->got->size = max_before_header + htab->got_header_size;
+             htab->got_gap = max_before_header - htab->elf.sgot->size;
+             htab->elf.sgot->size = max_before_header + htab->got_header_size;
            }
-         where = htab->got->size;
-         htab->got->size += need;
+         where = htab->elf.sgot->size;
+         htab->elf.sgot->size += need;
        }
     }
   return where;
@@ -5916,9 +5965,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                || h->type == STT_GNU_IFUNC
                || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
              {
-               asection *s = htab->plt;
+               asection *s = htab->elf.splt;
                if (!dyn || h->dynindx == -1)
-                 s = htab->iplt;
+                 s = htab->elf.iplt;
 
                if (htab->plt_type == PLT_NEW || !dyn || h->dynindx == -1)
                  {
@@ -6004,10 +6053,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                  {
                    if (!htab->elf.dynamic_sections_created
                        || h->dynindx == -1)
-                     htab->reliplt->size += sizeof (Elf32_External_Rela);
+                     htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
                    else
                      {
-                       htab->relplt->size += sizeof (Elf32_External_Rela);
+                       htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
 
                        if (htab->plt_type == PLT_VXWORKS)
                          {
@@ -6030,7 +6079,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
                            /* Every PLT entry has an associated GOT entry in
                               .got.plt.  */
-                           htab->sgotplt->size += 4;
+                           htab->elf.sgotplt->size += 4;
                          }
                      }
                    doneone = TRUE;
@@ -6109,10 +6158,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
              && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
                  || eh->elf.root.type != bfd_link_hash_undefweak))
            {
-             asection *rsec = htab->relgot;
+             asection *rsec = htab->elf.srelgot;
 
              if (eh->elf.type == STT_GNU_IFUNC)
-               rsec = htab->reliplt;
+               rsec = htab->elf.irelplt;
              /* All the entries we allocated need relocs.
                 Except LD only needs one.  */
              if ((eh->tls_mask & TLS_LD) != 0
@@ -6235,7 +6284,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
     {
       asection *sreloc = elf_section_data (p->sec)->sreloc;
       if (eh->elf.type == STT_GNU_IFUNC)
-       sreloc = htab->reliplt;
+       sreloc = htab->elf.irelplt;
       sreloc->size += p->count * sizeof (Elf32_External_Rela);
     }
 
@@ -6353,7 +6402,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
                {
                  asection *sreloc = elf_section_data (p->sec)->sreloc;
                  if (p->ifunc)
-                   sreloc = htab->reliplt;
+                   sreloc = htab->elf.irelplt;
                  sreloc->size += p->count * sizeof (Elf32_External_Rela);
                  if ((p->sec->output_section->flags
                       & (SEC_READONLY | SEC_ALLOC))
@@ -6398,9 +6447,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
                *local_got = allocate_got (htab, need);
                if (bfd_link_pic (info))
                  {
-                   asection *srel = htab->relgot;
+                   asection *srel = htab->elf.srelgot;
                    if ((*lgot_masks & PLT_IFUNC) != 0)
-                     srel = htab->reliplt;
+                     srel = htab->elf.irelplt;
                    srel->size += need * (sizeof (Elf32_External_Rela) / 4);
                  }
              }
@@ -6421,7 +6470,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
          for (ent = *local_plt; ent != NULL; ent = ent->next)
            if (ent->plt.refcount > 0)
              {
-               s = htab->iplt;
+               s = htab->elf.iplt;
 
                if (!doneone)
                  {
@@ -6440,7 +6489,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
 
                if (!doneone)
                  {
-                   htab->reliplt->size += sizeof (Elf32_External_Rela);
+                   htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
                    doneone = TRUE;
                  }
              }
@@ -6456,12 +6505,12 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
     {
       htab->tlsld_got.offset = allocate_got (htab, 8);
       if (bfd_link_pic (info))
-       htab->relgot->size += sizeof (Elf32_External_Rela);
+       htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
     }
   else
     htab->tlsld_got.offset = (bfd_vma) -1;
 
-  if (htab->got != NULL && htab->plt_type != PLT_VXWORKS)
+  if (htab->elf.sgot != NULL && htab->plt_type != PLT_VXWORKS)
     {
       unsigned int g_o_t = 32768;
 
@@ -6469,12 +6518,12 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
         for old plt/got the got size will be 0 to 32764 (not allocated),
         or 32780 to 65536 (header allocated).  For new plt/got, the
         corresponding ranges are 0 to 32768 and 32780 to 65536.  */
-      if (htab->got->size <= 32768)
+      if (htab->elf.sgot->size <= 32768)
        {
-         g_o_t = htab->got->size;
+         g_o_t = htab->elf.sgot->size;
          if (htab->plt_type == PLT_OLD)
            g_o_t += 4;
-         htab->got->size += htab->got_header_size;
+         htab->elf.sgot->size += htab->got_header_size;
        }
 
       htab->elf.hgot->root.u.def.value = g_o_t;
@@ -6502,7 +6551,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       && htab->elf.dynamic_sections_created)
     {
       htab->glink_pltresolve = htab->glink->size;
-      /* Space for the branch table.  */
+      /* Space for the branch table.  ??? We don't need entries for
+        non-dynamic symbols in this table.  This case can arise with
+        static ifuncs or forced local ifuncs.  */
       htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4;
       /* Pad out to align the start of PLTresolve.  */
       htab->glink->size += -htab->glink->size & (htab->params->ppc476_workaround
@@ -6573,8 +6624,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
 
-      if (s == htab->plt
-         || s == htab->got)
+      if (s == htab->elf.splt
+         || s == htab->elf.sgot)
        {
          /* We'd like to strip these sections if they aren't needed, but if
             we've exported dynamic symbols from them we must leave them.
@@ -6584,12 +6635,13 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (s == htab->iplt
+      else if (s == htab->elf.iplt
               || s == htab->glink
               || s == htab->glink_eh_frame
-              || s == htab->sgotplt
+              || s == htab->elf.sgotplt
               || s == htab->sbss
-              || s == htab->dynbss
+              || s == htab->elf.sdynbss
+              || s == htab->elf.sdynrelro
               || s == htab->dynsbss)
        {
          /* Strip these too.  */
@@ -6658,7 +6710,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
            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)
@@ -7157,7 +7209,7 @@ ppc_elf_relax_section (bfd *abfd,
                    }
                  else
                    {
-                     tsec = htab->plt;
+                     tsec = htab->elf.splt;
                      toff = ent->plt.offset;
                    }
                }
@@ -7260,7 +7312,7 @@ ppc_elf_relax_section (bfd *abfd,
                  insn_offset = 0;
                }
              stub_rtype = R_PPC_RELAX;
-             if (tsec == htab->plt
+             if (tsec == htab->elf.splt
                  || tsec == htab->glink)
                {
                  stub_rtype = R_PPC_RELAX_PLT;
@@ -7763,7 +7815,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
   asection *got2;
   bfd_vma *local_got_offsets;
   bfd_boolean ret = TRUE;
-  bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
+  bfd_vma d_offset = (bfd_big_endian (input_bfd) ? 2 : 0);
   bfd_boolean is_vxworks_tls;
   unsigned int picfixup_size = 0;
   struct ppc_elf_relax_info *relax_info = NULL;
@@ -7925,11 +7977,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
            {
              bfd_vma insn;
 
-             insn = bfd_get_32 (output_bfd,
+             insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
              insn &= 31 << 21;
              insn |= 0x3c020000;       /* addis 0,2,0 */
-             bfd_put_32 (output_bfd, insn,
+             bfd_put_32 (input_bfd, insn,
                          contents + rel->r_offset - d_offset);
              r_type = R_PPC_TPREL16_HA;
              rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@@ -7942,11 +7994,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
            {
              bfd_vma insn;
 
-             insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
              insn = _bfd_elf_ppc_at_tls_transform (insn, 2);
              if (insn == 0)
                abort ();
-             bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
              r_type = R_PPC_TPREL16_LO;
              rel->r_info = ELF32_R_INFO (r_symndx, r_type);
 
@@ -7974,7 +8026,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              else
                {
                  rel->r_offset -= d_offset;
-                 bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
+                 bfd_put_32 (input_bfd, NOP, contents + rel->r_offset);
                  r_type = R_PPC_NONE;
                }
              rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@@ -8011,7 +8063,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                 the destination reg.  It may be something other than
                 the usual r3, and moved to r3 before the call by
                 intervening code.  */
-             insn1 = bfd_get_32 (output_bfd,
+             insn1 = bfd_get_32 (input_bfd,
                                  contents + rel->r_offset - d_offset);
              if ((tls_mask & tls_gd) != 0)
                {
@@ -8022,7 +8074,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                    {
                      rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
                      insn2 = 0x7c631214;       /* add 3,3,2 */
-                     bfd_put_32 (output_bfd, insn2, contents + offset);
+                     bfd_put_32 (input_bfd, insn2, contents + offset);
                    }
                  r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
                            + R_PPC_GOT_TPREL16);
@@ -8057,10 +8109,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
                      rel[1].r_offset = offset + d_offset;
                      rel[1].r_addend = rel->r_addend;
                      insn2 = 0x38630000;       /* addi 3,3,0 */
-                     bfd_put_32 (output_bfd, insn2, contents + offset);
+                     bfd_put_32 (input_bfd, insn2, contents + offset);
                    }
                }
-             bfd_put_32 (output_bfd, insn1,
+             bfd_put_32 (input_bfd, insn1,
                          contents + rel->r_offset - d_offset);
              if (tls_gd == 0)
                {
@@ -8091,7 +8143,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  insn2 = 0x38630000;   /* addi 3,3,0 */
                }
              rel->r_info = ELF32_R_INFO (r_symndx, r_type);
-             bfd_put_32 (output_bfd, insn2, contents + offset);
+             bfd_put_32 (input_bfd, insn2, contents + offset);
              /* Zap the reloc on the _tls_get_addr call too.  */
              BFD_ASSERT (offset == rel[1].r_offset);
              rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
@@ -8119,7 +8171,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
              rel->r_offset += d_offset;
              insn2 = 0x38630000;       /* addi 3,3,0 */
-             bfd_put_32 (output_bfd, insn2,
+             bfd_put_32 (input_bfd, insn2,
                          contents + rel->r_offset - d_offset);
              /* Zap the reloc on the _tls_get_addr call too.  */
              BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset);
@@ -8140,7 +8192,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_ADDR14_BRTAKEN:
        case R_PPC_REL14_BRTAKEN:
          branch_bit = BRANCH_PREDICT_BIT;
-         /* Fall thru */
+         /* Fall through.  */
 
          /* Branch not taken prediction relocations.  */
        case R_PPC_ADDR14_BRNTAKEN:
@@ -8148,7 +8200,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          {
            bfd_vma insn;
 
-           insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+           insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
            insn &= ~BRANCH_PREDICT_BIT;
            insn |= branch_bit;
 
@@ -8160,7 +8212,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
              insn ^= BRANCH_PREDICT_BIT;
 
-           bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+           bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
            break;
          }
        }
@@ -8179,7 +8231,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
          if (r_type == R_PPC_ADDR16_HA)
            {
-             insn = bfd_get_32 (output_bfd,
+             insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
              if ((insn & (0x3f << 26)) == (15u << 26)
                  && (insn & (0x1f << 16)) == 0 /* lis */)
@@ -8198,26 +8250,26 @@ ppc_elf_relocate_section (bfd *output_bfd,
                      (_("%P: %H: fixup branch overflow\n"),
                       input_bfd, input_section, rel->r_offset);
 
-                 bfd_put_32 (output_bfd, B | off,
+                 bfd_put_32 (input_bfd, B | off,
                              contents + rel->r_offset - d_offset);
-                 got_addr = (htab->got->output_section->vma
-                             + htab->got->output_offset
+                 got_addr = (htab->elf.sgot->output_section->vma
+                             + htab->elf.sgot->output_offset
                              + (h->got.offset & ~1));
                  wrel->r_offset = (p - contents) + d_offset;
                  wrel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
                  wrel->r_addend = got_addr;
                  insn &= ~0xffff;
                  insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
-                 bfd_put_32 (output_bfd, insn, p);
+                 bfd_put_32 (input_bfd, insn, p);
 
                  /* Convert lis to lwz, loading address from GOT.  */
                  insn &= ~0xffff;
                  insn ^= (32u ^ 15u) << 26;
                  insn |= (insn & (0x1f << 21)) >> 5;
                  insn |= got_addr & 0xffff;
-                 bfd_put_32 (output_bfd, insn, p + 4);
+                 bfd_put_32 (input_bfd, insn, p + 4);
 
-                 bfd_put_32 (output_bfd, B | ((-4 - off) & 0x3ffffff), p + 8);
+                 bfd_put_32 (input_bfd, B | ((-4 - off) & 0x3ffffff), p + 8);
                  picfixup_size += 12;
 
                  /* Use one of the spare relocs, so --emit-relocs
@@ -8234,13 +8286,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
                }
              else
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %H: error: %s with unexpected instruction %x\n"),
                   input_bfd, input_section, rel->r_offset,
                   "R_PPC_ADDR16_HA", insn);
            }
          else if (r_type == R_PPC_ADDR16_LO)
            {
-             insn = bfd_get_32 (output_bfd,
+             insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
              if ((insn & (0x3f << 26)) == 14u << 26    /* addi */
                  || (insn & (0x3f << 26)) == 32u << 26 /* lwz */
@@ -8268,6 +8321,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                }
              else
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %H: error: %s with unexpected instruction %x\n"),
                   input_bfd, input_section, rel->r_offset,
                   "R_PPC_ADDR16_LO", insn);
@@ -8306,18 +8360,39 @@ ppc_elf_relocate_section (bfd *output_bfd,
            }
          if (ent != NULL)
            {
+             if (bfd_link_pic (info)
+                 && ent->sec != got2
+                 && htab->plt_type != PLT_NEW
+                 && (!htab->elf.dynamic_sections_created
+                     || h == NULL
+                     || h->dynindx == -1))
+               {
+                 /* Uh oh, we are going to create a pic glink stub
+                    for an ifunc (here for h == NULL and later in
+                    finish_dynamic_symbol for h != NULL), and
+                    apparently are using code compiled with
+                    -mbss-plt.  The difficulty is that -mbss-plt code
+                    gives no indication via a magic PLTREL24 addend
+                    whether r30 is equal to _GLOBAL_OFFSET_TABLE_ or
+                    is pointing into a .got2 section (and how far
+                    into .got2).  */
+                   info->callbacks->einfo
+                     /* xgettext:c-format */
+                     (_("%X%P: %H: unsupported bss-plt -fPIC ifunc %s\n"),
+                      input_bfd, input_section, rel->r_offset, sym_name);
+               }
              if (h == NULL && (ent->plt.offset & 1) == 0)
                {
                  Elf_Internal_Rela rela;
                  bfd_byte *loc;
 
-                 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 = ELF32_R_INFO (0, R_PPC_IRELATIVE);
                  rela.r_addend = relocation;
-                 loc = htab->reliplt->contents;
-                 loc += (htab->reliplt->reloc_count++
+                 loc = htab->elf.irelplt->contents;
+                 loc += (htab->elf.irelplt->reloc_count++
                          * sizeof (Elf32_External_Rela));
                  bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
 
@@ -8327,7 +8402,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                {
                  unsigned char *p = ((unsigned char *) htab->glink->contents
                                      + ent->glink_offset);
-                 write_glink_stub (ent, htab->iplt, p, info);
+                 write_glink_stub (ent, htab->elf.iplt, p, info);
                  ent->glink_offset |= 1;
                }
 
@@ -8340,8 +8415,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                              + htab->glink->output_offset
                              + (ent->glink_offset & ~1));
              else
-               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);
            }
        }
@@ -8355,6 +8430,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        {
        default:
          info->callbacks->einfo
+           /* xgettext:c-format */
            (_("%P: %B: unknown relocation type %d for symbol %s\n"),
             input_bfd, (int) r_type, sym_name);
 
@@ -8416,7 +8492,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            bfd_vma *offp;
            unsigned long indx;
 
-           if (htab->got == NULL)
+           if (htab->elf.sgot == NULL)
              abort ();
 
            indx = 0;
@@ -8503,13 +8579,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
                            || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                            || h->root.type != bfd_link_hash_undefweak))
                      {
-                       asection *rsec = htab->relgot;
+                       asection *rsec = htab->elf.srelgot;
                        bfd_byte * loc;
 
                        if (ifunc != NULL)
-                         rsec = htab->reliplt;
-                       outrel.r_offset = (htab->got->output_section->vma
-                                          + htab->got->output_offset
+                         rsec = htab->elf.irelplt;
+                       outrel.r_offset = (htab->elf.sgot->output_section->vma
+                                          + htab->elf.sgot->output_offset
                                           + off);
                        outrel.r_addend = 0;
                        if (tls_ty & (TLS_LD | TLS_GD))
@@ -8575,13 +8651,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
                            if (tls_ty == (TLS_TLS | TLS_GD))
                              {
-                               bfd_put_32 (output_bfd, value,
-                                           htab->got->contents + off + 4);
+                               bfd_put_32 (input_bfd, value,
+                                           htab->elf.sgot->contents + off + 4);
                                value = 1;
                              }
                          }
-                       bfd_put_32 (output_bfd, value,
-                                   htab->got->contents + off);
+                       bfd_put_32 (input_bfd, value,
+                                   htab->elf.sgot->contents + off);
                      }
 
                    off += 4;
@@ -8622,8 +8698,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
            if (r_type != ELF32_R_TYPE (rel->r_info))
              goto copy_reloc;
 
-           relocation = (htab->got->output_section->vma
-                         + htab->got->output_offset
+           relocation = (htab->elf.sgot->output_section->vma
+                         + htab->elf.sgot->output_offset
                          + off
                          - SYM_VAL (htab->elf.hgot));
 
@@ -8633,6 +8709,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
               got at entry m+n bears little relation to the entry m.  */
            if (addend != 0)
              info->callbacks->einfo
+               /* xgettext:c-format */
                (_("%P: %H: non-zero addend on %s reloc against `%s'\n"),
                 input_bfd, input_section, rel->r_offset,
                 howto->name,
@@ -8654,6 +8731,21 @@ ppc_elf_relocate_section (bfd *output_bfd,
                                                    TRUE);
              goto copy_reloc;
            }
+         if (h != NULL && h->type == STT_GNU_IFUNC && bfd_link_pic (info))
+           {
+             /* @local on an ifunc does not really make sense since
+                the ifunc resolver can take you anywhere.  More
+                seriously, calls to ifuncs must go through a plt call
+                stub, and for pic the plt call stubs uses r30 to
+                access the PLT.  The problem is that a call that is
+                local won't have the +32k reloc addend trick marking
+                -fPIC code, so the linker won't know whether r30 is
+                _GLOBAL_OFFSET_TABLE_ or pointing into a .got2 section.  */
+             /* xgettext:c-format */
+             info->callbacks->einfo (_("%X%P: %H: @local call to ifunc %s\n"),
+                                     input_bfd, input_section, rel->r_offset,
+                                     h->root.root.string);
+           }
          break;
 
        case R_PPC_DTPREL16:
@@ -8679,10 +8771,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
                 code using weak externs ought to check that they are
                 defined before using them.  */
              bfd_byte *p = contents + rel->r_offset - d_offset;
-             unsigned int insn = bfd_get_32 (output_bfd, p);
+             unsigned int insn = bfd_get_32 (input_bfd, p);
              insn = _bfd_elf_ppc_at_tprel_transform (insn, 2);
              if (insn != 0)
-               bfd_put_32 (output_bfd, insn, p);
+               bfd_put_32 (input_bfd, insn, p);
              break;
            }
          if (htab->elf.tls_sec != NULL)
@@ -8790,7 +8882,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                 time.  */
              sreloc = elf_section_data (input_section)->sreloc;
              if (ifunc)
-               sreloc = htab->reliplt;
+               sreloc = htab->elf.irelplt;
              if (sreloc == NULL)
                return FALSE;
 
@@ -8839,6 +8931,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                             So we'll segfault when trying to run the
                             indirection function to resolve the reloc.  */
                          info->callbacks->einfo
+                           /* xgettext:c-format */
                            (_("%P: %H: relocation %s for indirect "
                               "function %s unsupported\n"),
                             input_bfd, input_section, rel->r_offset,
@@ -8926,11 +9019,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
                              + htab->glink->output_offset
                              + ent->glink_offset);
              else
-               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);
            }
-         /* Fall thru */
+         /* Fall through.  */
 
        case R_PPC_RELAX:
          {
@@ -8945,9 +9038,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                               + input_section->output_offset
                               + rel->r_offset - 4);
                stub = shared_stub_entry;
-               bfd_put_32 (output_bfd, stub[0], contents + insn_offset - 12);
-               bfd_put_32 (output_bfd, stub[1], contents + insn_offset - 8);
-               bfd_put_32 (output_bfd, stub[2], contents + insn_offset - 4);
+               bfd_put_32 (input_bfd, stub[0], contents + insn_offset - 12);
+               bfd_put_32 (input_bfd, stub[1], contents + insn_offset - 8);
+               bfd_put_32 (input_bfd, stub[2], contents + insn_offset - 4);
                stub += 3;
                size = ARRAY_SIZE (shared_stub_entry) - 3;
              }
@@ -8964,12 +9057,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
            /* First insn is HA, second is LO.  */
            insn = *stub++;
            insn |= ((relocation + 0x8000) >> 16) & 0xffff;
-           bfd_put_32 (output_bfd, insn, contents + insn_offset);
+           bfd_put_32 (input_bfd, insn, contents + insn_offset);
            insn_offset += 4;
 
            insn = *stub++;
            insn |= relocation & 0xffff;
-           bfd_put_32 (output_bfd, insn, contents + insn_offset);
+           bfd_put_32 (input_bfd, insn, contents + insn_offset);
            insn_offset += 4;
            size -= 2;
 
@@ -8977,7 +9070,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              {
                insn = *stub++;
                --size;
-               bfd_put_32 (output_bfd, insn, contents + insn_offset);
+               bfd_put_32 (input_bfd, insn, contents + insn_offset);
                insn_offset += 4;
              }
 
@@ -9049,7 +9142,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              ent = find_plt_ent (&h->plt.plist, got2,
                                  bfd_link_pic (info) ? addend : 0);
              if (ent == NULL
-                 || htab->plt == NULL)
+                 || htab->elf.splt == NULL)
                {
                  /* We didn't make a PLT entry for this symbol.  This
                     happens when statically linking PIC code, or when
@@ -9065,8 +9158,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                                  + htab->glink->output_offset
                                  + ent->glink_offset);
                  else
-                   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);
                }
            }
@@ -9097,6 +9190,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  || strcmp (name, ".sbss") == 0))
              {
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
@@ -9127,6 +9221,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  || strcmp (name, ".sbss2") == 0))
              {
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
@@ -9139,38 +9234,44 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_VLE_LO16A:
          relocation = relocation + addend;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16a_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16a_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
        case R_PPC_VLE_LO16D:
          relocation = relocation + addend;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16d_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16d_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
        case R_PPC_VLE_HI16A:
          relocation = (relocation + addend) >> 16;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16a_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16a_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
        case R_PPC_VLE_HI16D:
          relocation = (relocation + addend) >> 16;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16d_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16d_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
        case R_PPC_VLE_HA16A:
          relocation = (relocation + addend + 0x8000) >> 16;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16a_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16a_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
        case R_PPC_VLE_HA16D:
          relocation = (relocation + addend + 0x8000) >> 16;
-         ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                              relocation, split16d_type);
+         ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                              contents + rel->r_offset, relocation,
+                              split16d_type, htab->params->vle_reloc_fixup);
          goto copy_reloc;
 
          /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0.  */
@@ -9211,6 +9312,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            else
              {
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
@@ -9233,7 +9335,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                addend -= SYM_VAL (sda);
              }
 
-           insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+           insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
            if (reg == 0
                && (r_type == R_PPC_VLE_SDA21
                    || r_type == R_PPC_VLE_SDA21_LO))
@@ -9253,7 +9355,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                /* And the final 11 bits of the value to bits 21 to 31.  */
                insn |= relocation & 0x7ff;
 
-               bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+               bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
 
                if (r_type == R_PPC_VLE_SDA21
                    && ((relocation + 0x80000) & 0xffffffff) > 0x100000)
@@ -9267,7 +9369,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                /* Fill in register field.  */
                insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
              }
-           bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+           bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
          }
          break;
 
@@ -9304,7 +9406,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
              }
            else
              {
-               (*_bfd_error_handler)
+               _bfd_error_handler
+                 /* xgettext:c-format */
                  (_("%B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)"),
                   input_bfd,
@@ -9331,34 +9434,46 @@ ppc_elf_relocate_section (bfd *output_bfd,
                     + addend);
 
            if (r_type == R_PPC_VLE_SDAREL_LO16A)
-             ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                  value, split16a_type);
+             ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, value,
+                                  split16a_type,
+                                  htab->params->vle_reloc_fixup);
            else if (r_type == R_PPC_VLE_SDAREL_LO16D)
-             ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                  value, split16d_type);
+             ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, value,
+                                  split16d_type,
+                                  htab->params->vle_reloc_fixup);
            else if (r_type == R_PPC_VLE_SDAREL_HI16A)
              {
                value = value >> 16;
-               ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                    value, split16a_type);
+               ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                    contents + rel->r_offset, value,
+                                    split16a_type,
+                                    htab->params->vle_reloc_fixup);
              }
            else if (r_type == R_PPC_VLE_SDAREL_HI16D)
              {
                value = value >> 16;
-               ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                    value, split16d_type);
+               ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                    contents + rel->r_offset, value,
+                                    split16d_type,
+                                    htab->params->vle_reloc_fixup);
              }
            else if (r_type == R_PPC_VLE_SDAREL_HA16A)
              {
                value = (value + 0x8000) >> 16;
-               ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                    value, split16a_type);
+               ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                    contents + rel->r_offset, value,
+                                    split16a_type,
+                                    htab->params->vle_reloc_fixup);
              }
            else if (r_type == R_PPC_VLE_SDAREL_HA16D)
              {
                value = (value + 0x8000) >> 16;
-               ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
-                                    value, split16d_type);
+               ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                    contents + rel->r_offset, value,
+                                    split16d_type,
+                                    htab->params->vle_reloc_fixup);
              }
          }
          goto copy_reloc;
@@ -9402,6 +9517,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_RELST_HA:
        case R_PPC_EMB_BIT_FLD:
          info->callbacks->einfo
+           /* xgettext:c-format */
            (_("%P: %B: relocation %s is not yet supported for symbol %s\n"),
             input_bfd,
             howto->name,
@@ -9432,7 +9548,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
             alone (it will be set to zero elsewhere in the link).  */
          if (sec == NULL)
            break;
-         /* Fall thru */
+         /* Fall through.  */
 
        case R_PPC_PLT16_HA:
        case R_PPC_GOT16_HA:
@@ -9470,7 +9586,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
               that make up part of the insn opcode.  */
            unsigned int insn, mask, lobit;
 
-           insn = bfd_get_32 (output_bfd,
+           insn = bfd_get_32 (input_bfd,
                               contents + rel->r_offset - d_offset);
            mask = 0;
            if (is_insn_ds_form (insn))
@@ -9486,6 +9602,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              {
                relocation ^= lobit;
                info->callbacks->einfo
+                 /* xgettext:c-format */
                  (_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
                   input_bfd, input_section, rel->r_offset,
                   howto->name, sym_name, mask + 1);
@@ -9514,6 +9631,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                                      rel->r_offset) != (bfd_vma) -1)
        {
          info->callbacks->einfo
+           /* xgettext:c-format */
            (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
             input_bfd, input_section, rel->r_offset,
             howto->name,
@@ -9594,6 +9712,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          else
            {
              info->callbacks->einfo
+               /* xgettext:c-format */
                (_("%P: %H: %s reloc against `%s': error %d\n"),
                 input_bfd, input_section, rel->r_offset,
                 howto->name, sym_name, (int) r);
@@ -9991,10 +10110,10 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                  {
                    bfd_put_32 (output_bfd,
                                plt_entry[0] | PPC_HA (got_offset),
-                               htab->plt->contents + ent->plt.offset + 0);
+                               htab->elf.splt->contents + ent->plt.offset + 0);
                    bfd_put_32 (output_bfd,
                                plt_entry[1] | PPC_LO (got_offset),
-                               htab->plt->contents + ent->plt.offset + 4);
+                               htab->elf.splt->contents + ent->plt.offset + 4);
                  }
                else
                  {
@@ -10002,16 +10121,16 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
                    bfd_put_32 (output_bfd,
                                plt_entry[0] | PPC_HA (got_loc),
-                               htab->plt->contents + ent->plt.offset + 0);
+                               htab->elf.splt->contents + ent->plt.offset + 0);
                    bfd_put_32 (output_bfd,
                                plt_entry[1] | PPC_LO (got_loc),
-                               htab->plt->contents + ent->plt.offset + 4);
+                               htab->elf.splt->contents + ent->plt.offset + 4);
                  }
 
                bfd_put_32 (output_bfd, plt_entry[2],
-                           htab->plt->contents + ent->plt.offset + 8);
+                           htab->elf.splt->contents + ent->plt.offset + 8);
                bfd_put_32 (output_bfd, plt_entry[3],
-                           htab->plt->contents + ent->plt.offset + 12);
+                           htab->elf.splt->contents + ent->plt.offset + 12);
 
                /* This instruction is an immediate load.  The value loaded is
                   the byte offset of the R_PPC_JMP_SLOT relocation from the
@@ -10021,7 +10140,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                   prescaled offset.  */
                bfd_put_32 (output_bfd,
                            plt_entry[4] | reloc_index,
-                           htab->plt->contents + ent->plt.offset + 16);
+                           htab->elf.splt->contents + ent->plt.offset + 16);
                /* This instruction is a PC-relative branch whose target is
                   the start of the PLT section.  The address of this branch
                   instruction is 20 bytes beyond the start of this PLT entry.
@@ -10031,19 +10150,19 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                bfd_put_32 (output_bfd,
                            (plt_entry[5]
                             | (-(ent->plt.offset + 20) & 0x03fffffc)),
-                           htab->plt->contents + ent->plt.offset + 20);
+                           htab->elf.splt->contents + ent->plt.offset + 20);
                bfd_put_32 (output_bfd, plt_entry[6],
-                           htab->plt->contents + ent->plt.offset + 24);
+                           htab->elf.splt->contents + ent->plt.offset + 24);
                bfd_put_32 (output_bfd, plt_entry[7],
-                           htab->plt->contents + ent->plt.offset + 28);
+                           htab->elf.splt->contents + ent->plt.offset + 28);
 
                /* Fill in the GOT entry corresponding to this PLT slot with
                   the address immediately after the "bctr" instruction
                   in this PLT entry.  */
-               bfd_put_32 (output_bfd, (htab->plt->output_section->vma
-                                        + htab->plt->output_offset
+               bfd_put_32 (output_bfd, (htab->elf.splt->output_section->vma
+                                        + htab->elf.splt->output_offset
                                         + ent->plt.offset + 16),
-                           htab->sgotplt->contents + got_offset);
+                           htab->elf.sgotplt->contents + got_offset);
 
                if (!bfd_link_pic (info))
                  {
@@ -10054,8 +10173,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                         * sizeof (Elf32_External_Rela));
 
                    /* Provide the @ha relocation for the first instruction.  */
-                   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 + 2);
                    rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
                                                R_PPC_ADDR16_HA);
@@ -10064,8 +10183,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                    loc += sizeof (Elf32_External_Rela);
 
                    /* Provide the @l relocation for the second instruction.  */
-                   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 + 6);
                    rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
                                                R_PPC_ADDR16_LO);
@@ -10075,8 +10194,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
                    /* Provide a relocation for the GOT entry corresponding to this
                       PLT slot.  Point it at the middle of the .plt entry.  */
-                   rela.r_offset = (htab->sgotplt->output_section->vma
-                                    + htab->sgotplt->output_offset
+                   rela.r_offset = (htab->elf.sgotplt->output_section->vma
+                                    + htab->elf.sgotplt->output_offset
                                     + got_offset);
                    rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
                                                R_PPC_ADDR32);
@@ -10089,17 +10208,17 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                   address of the PLT entry for this function, as specified
                   by the ABI.  Instead, the offset is set to the address of
                   the GOT slot for this function.  See EABI 4.4.4.1.  */
-               rela.r_offset = (htab->sgotplt->output_section->vma
-                                + htab->sgotplt->output_offset
+               rela.r_offset = (htab->elf.sgotplt->output_section->vma
+                                + htab->elf.sgotplt->output_offset
                                 + got_offset);
 
              }
            else
              {
-               asection *splt = htab->plt;
+               asection *splt = htab->elf.splt;
                if (!htab->elf.dynamic_sections_created
                    || h->dynindx == -1)
-                 splt = htab->iplt;
+                 splt = htab->elf.iplt;
 
                rela.r_offset = (splt->output_section->vma
                                 + splt->output_offset
@@ -10138,11 +10257,11 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
            if (!htab->elf.dynamic_sections_created
                || h->dynindx == -1)
-             loc = (htab->reliplt->contents
-                    + (htab->reliplt->reloc_count++
+             loc = (htab->elf.irelplt->contents
+                    + (htab->elf.irelplt->reloc_count++
                        * sizeof (Elf32_External_Rela)));
            else
-             loc = (htab->relplt->contents
+             loc = (htab->elf.srelplt->contents
                     + reloc_index * sizeof (Elf32_External_Rela));
            bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
 
@@ -10190,10 +10309,10 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
            || h->dynindx == -1)
          {
            unsigned char *p;
-           asection *splt = htab->plt;
+           asection *splt = htab->elf.splt;
            if (!htab->elf.dynamic_sections_created
                || h->dynindx == -1)
-             splt = htab->iplt;
+             splt = htab->elf.iplt;
 
            p = (unsigned char *) htab->glink->contents + ent->glink_offset;
 
@@ -10243,8 +10362,10 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       if (ppc_elf_hash_entry (h)->has_sda_refs)
        s = htab->relsbss;
+      else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+       s = htab->elf.sreldynrelro;
       else
-       s = htab->relbss;
+       s = htab->elf.srelbss;
       BFD_ASSERT (s != NULL);
 
       rela.r_offset = SYM_VAL (h);
@@ -10268,7 +10389,7 @@ ppc_elf_reloc_type_class (const struct bfd_link_info *info,
 {
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
 
-  if (rel_sec == htab->reliplt)
+  if (rel_sec == htab->elf.irelplt)
     return reloc_class_ifunc;
 
   switch (ELF32_R_TYPE (rela->r_info))
@@ -10302,10 +10423,10 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #endif
 
   htab = ppc_elf_hash_table (info);
-  dynobj = elf_hash_table (info)->dynobj;
+  dynobj = htab->elf.dynobj;
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   if (htab->is_vxworks)
-    splt = bfd_get_linker_section (dynobj, ".plt");
+    splt = htab->elf.splt;
   else
     splt = NULL;
 
@@ -10317,7 +10438,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
     {
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      BFD_ASSERT (htab->plt != NULL && sdyn != NULL);
+      BFD_ASSERT (htab->elf.splt != NULL && sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
@@ -10332,18 +10453,18 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
            {
            case DT_PLTGOT:
              if (htab->is_vxworks)
-               s = htab->sgotplt;
+               s = htab->elf.sgotplt;
              else
-               s = htab->plt;
+               s = htab->elf.splt;
              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_JMPREL:
-             s = htab->relplt;
+             s = htab->elf.srelplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
@@ -10351,15 +10472,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
              dyn.d_un.d_ptr = got;
              break;
 
-           case DT_RELASZ:
-             if (htab->is_vxworks)
-               {
-                 if (htab->relplt)
-                   dyn.d_un.d_ptr -= htab->relplt->size;
-                 break;
-               }
-             continue;
-
            default:
              if (htab->is_vxworks
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
@@ -10371,10 +10483,10 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  if (htab->got != NULL)
+  if (htab->elf.sgot != NULL)
     {
-      if (htab->elf.hgot->root.u.def.section == htab->got
-         || htab->elf.hgot->root.u.def.section == htab->sgotplt)
+      if (htab->elf.hgot->root.u.def.section == htab->elf.sgot
+         || htab->elf.hgot->root.u.def.section == htab->elf.sgotplt)
        {
          unsigned char *p = htab->elf.hgot->root.u.def.section->contents;
 
@@ -10399,15 +10511,17 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
       else
        {
+         /* xgettext:c-format */
          info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"),
                                  htab->elf.hgot->root.root.string,
-                                 (htab->sgotplt != NULL
-                                  ? htab->sgotplt->name : htab->got->name));
+                                 (htab->elf.sgotplt != NULL
+                                  ? htab->elf.sgotplt->name
+                                  : htab->elf.sgot->name));
          bfd_set_error (bfd_error_bad_value);
          ret = FALSE;
        }
 
-      elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
+      elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
     }
 
   /* Fill in the first entry in the VxWorks procedure linkage table.  */
@@ -10447,8 +10561,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
          loc = htab->srelplt2->contents;
 
          /* Output the @ha relocation for the first instruction.  */
-         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
                           + 2);
          rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA);
          rela.r_addend = 0;
@@ -10456,8 +10570,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
          loc += sizeof (Elf32_External_Rela);
 
          /* Output the @l relocation for the second instruction.  */
-         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
                           + 6);
          rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO);
          rela.r_addend = 0;
@@ -10787,6 +10901,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #endif
 
 #define elf_backend_plt_not_loaded     1
+#define elf_backend_want_dynrelro      1
 #define elf_backend_can_gc_sections    1
 #define elf_backend_can_refcount       1
 #define elf_backend_rela_normal                1
@@ -10830,7 +10945,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define elf_backend_action_discarded           ppc_elf_action_discarded
 #define elf_backend_init_index_section         _bfd_elf_init_1_index_section
 #define elf_backend_lookup_section_flags_hook  ppc_elf_lookup_section_flags
-#define elf_backend_section_processing         ppc_elf_section_processing
 
 #include "elf32-target.h"
 
@@ -10936,6 +11050,8 @@ ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 #define elf_backend_plt_readonly               1
 #undef elf_backend_got_header_size
 #define elf_backend_got_header_size            12
+#undef elf_backend_dtrel_excludes_plt
+#define elf_backend_dtrel_excludes_plt         1
 
 #undef bfd_elf32_get_synthetic_symtab
 
This page took 0.069381 seconds and 4 git commands to generate.