gas: detect DCTI couples in sparc
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index 5c26077ad03bf8007c20ad6f1637d35c6f917680..e808cb523f53d12eec082d82862b015ebf78d141 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 32-bit ELF
 /* PowerPC-specific support for 32-bit ELF
-   Copyright (C) 1994-2015 Free Software Foundation, Inc.
+   Copyright (C) 1994-2016 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -35,7 +35,6 @@
 #include "elf32-ppc.h"
 #include "elf-vxworks.h"
 #include "dwarf2.h"
 #include "elf32-ppc.h"
 #include "elf-vxworks.h"
 #include "dwarf2.h"
-#include "elf-linux-psinfo.h"
 
 typedef enum split16_format_type
 {
 
 typedef enum split16_format_type
 {
@@ -414,7 +413,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_GOT16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -430,7 +429,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_GOT16_LO",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -446,7 +445,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_GOT16_HI",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -462,7 +461,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_GOT16_HA",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -477,8 +476,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         26,                    /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         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 */
         "R_PPC_PLTREL24",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -497,7 +496,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_COPY",          /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -513,7 +512,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_GLOB_DAT",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -528,7 +527,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_JMP_SLOT",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -623,7 +622,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_PLT32",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -639,7 +638,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_PLTREL32",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -655,7 +654,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_PLT16_LO",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -671,7 +670,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_PLT16_HI",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -687,7 +686,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_PLT16_HA",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -703,7 +702,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_SDAREL16",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -718,7 +717,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_SECTOFF",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -733,7 +732,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_SECTOFF_LO",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -748,7 +747,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_SECTOFF_HI",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -763,7 +762,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_SECTOFF_HA",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1239,7 +1238,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_NADDR32",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1254,7 +1253,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_NADDR16",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1269,7 +1268,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,/* complain_on_overflow */
         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 */
         "R_PPC_EMB_ADDR16_LO", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1284,7 +1283,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_NADDR16_HI", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1301,7 +1300,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_NADDR16_HA", /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1318,7 +1317,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_SDAI16",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1335,7 +1334,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_SDA2I16",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1351,7 +1350,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_SDA2REL",   /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1368,7 +1367,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_SDA21",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1392,7 +1391,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_EMB_RELSDA",    /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1426,7 +1425,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         "R_PPC_VLE_REL15",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         "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.  */
         TRUE),                 /* pcrel_offset */
 
   /* A relative 24 bit branch.  */
@@ -1452,7 +1451,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_VLE_LO16A",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1467,8 +1466,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* dst_mask */
@@ -1482,8 +1481,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f007ff,             /* dst_mask */
@@ -1497,8 +1496,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* dst_mask */
@@ -1512,8 +1511,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f007ff,             /* dst_mask */
@@ -1527,8 +1526,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* dst_mask */
@@ -1544,8 +1543,8 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
@@ -1559,7 +1558,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_VLE_SDA21_LO",  /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1573,9 +1572,9 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f007ff,             /* dst_mask */
@@ -1588,69 +1587,69 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         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 */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* 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 */
         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 */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f007ff,             /* 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 */
         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 */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* 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 */
         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 */
         FALSE),                /* pcrel_offset */
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f007ff,             /* 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 */
         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 */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         0x1f07ff,              /* dst_mask */
@@ -1663,7 +1662,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         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 */
         "R_PPC_IRELATIVE",     /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1731,6 +1730,21 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         0xffff,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
         0xffff,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
+  /* Like R_PPC_REL16_HA but for split field in addpcis.  */
+  HOWTO (R_PPC_REL16DX_HA,     /* type */
+        16,                    /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        ppc_elf_addr16_ha_reloc, /* special_function */
+        "R_PPC_REL16DX_HA",    /* name */
+        FALSE,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x1fffc1,              /* dst_mask */
+        TRUE),                 /* pcrel_offset */
+
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_PPC_GNU_VTINHERIT,  /* type */
         0,                     /* rightshift */
   /* GNU extension to record C++ vtable hierarchy.  */
   HOWTO (R_PPC_GNU_VTINHERIT,  /* type */
         0,                     /* rightshift */
@@ -1769,7 +1783,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         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 */
         "R_PPC_TOC16",         /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -1804,30 +1818,28 @@ struct elf_external_ppc_linux_prpsinfo32
     char pr_psargs[80];                        /* Initial part of arg list.  */
   };
 
     char pr_psargs[80];                        /* Initial part of arg list.  */
   };
 
-/* Helper macro to swap (properly handling endianess) things from the
-   `elf_internal_prpsinfo' structure to the `elf_external_ppc_prpsinfo32'
-   structure.
-
-   Note that FROM should be a pointer, and TO should be the explicit type.  */
-
-#define PPC_LINUX_PRPSINFO32_SWAP_FIELDS(abfd, from, to)             \
-  do                                                                 \
-    {                                                                \
-      H_PUT_8 (abfd, from->pr_state, &to.pr_state);                  \
-      H_PUT_8 (abfd, from->pr_sname, &to.pr_sname);                  \
-      H_PUT_8 (abfd, from->pr_zomb, &to.pr_zomb);                    \
-      H_PUT_8 (abfd, from->pr_nice, &to.pr_nice);                    \
-      H_PUT_32 (abfd, from->pr_flag, to.pr_flag);                    \
-      H_PUT_32 (abfd, from->pr_uid, to.pr_uid);                              \
-      H_PUT_32 (abfd, from->pr_gid, to.pr_gid);                              \
-      H_PUT_32 (abfd, from->pr_pid, to.pr_pid);                              \
-      H_PUT_32 (abfd, from->pr_ppid, to.pr_ppid);                    \
-      H_PUT_32 (abfd, from->pr_pgrp, to.pr_pgrp);                    \
-      H_PUT_32 (abfd, from->pr_sid, to.pr_sid);                              \
-      strncpy (to.pr_fname, from->pr_fname, sizeof (to.pr_fname));    \
-      strncpy (to.pr_psargs, from->pr_psargs, sizeof (to.pr_psargs)); \
-    } while (0)
+/* Helper function to copy an elf_internal_linux_prpsinfo in host
+   endian to an elf_external_ppc_linux_prpsinfo32 in target endian.  */
 
 
+static inline void
+swap_ppc_linux_prpsinfo32_out (bfd *obfd,
+                              const struct elf_internal_linux_prpsinfo *from,
+                              struct elf_external_ppc_linux_prpsinfo32 *to)
+{
+  bfd_put_8 (obfd, from->pr_state, &to->pr_state);
+  bfd_put_8 (obfd, from->pr_sname, &to->pr_sname);
+  bfd_put_8 (obfd, from->pr_zomb, &to->pr_zomb);
+  bfd_put_8 (obfd, from->pr_nice, &to->pr_nice);
+  bfd_put_32 (obfd, from->pr_flag, to->pr_flag);
+  bfd_put_32 (obfd, from->pr_uid, to->pr_uid);
+  bfd_put_32 (obfd, from->pr_gid, to->pr_gid);
+  bfd_put_32 (obfd, from->pr_pid, to->pr_pid);
+  bfd_put_32 (obfd, from->pr_ppid, to->pr_ppid);
+  bfd_put_32 (obfd, from->pr_pgrp, to->pr_pgrp);
+  bfd_put_32 (obfd, from->pr_sid, to->pr_sid);
+  strncpy (to->pr_fname, from->pr_fname, sizeof (to->pr_fname));
+  strncpy (to->pr_psargs, from->pr_psargs, sizeof (to->pr_psargs));
+}
 \f
 /* Initialize the ppc_elf_howto_table, so that linear accesses can be done.  */
 
 \f
 /* Initialize the ppc_elf_howto_table, so that linear accesses can be done.  */
 
@@ -1989,6 +2001,7 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     case BFD_RELOC_LO16_PCREL:         r = R_PPC_REL16_LO;             break;
     case BFD_RELOC_HI16_PCREL:         r = R_PPC_REL16_HI;             break;
     case BFD_RELOC_HI16_S_PCREL:       r = R_PPC_REL16_HA;             break;
     case BFD_RELOC_LO16_PCREL:         r = R_PPC_REL16_LO;             break;
     case BFD_RELOC_HI16_PCREL:         r = R_PPC_REL16_HI;             break;
     case BFD_RELOC_HI16_S_PCREL:       r = R_PPC_REL16_HA;             break;
+    case BFD_RELOC_PPC_REL16DX_HA:     r = R_PPC_REL16DX_HA;           break;
     case BFD_RELOC_VTABLE_INHERIT:     r = R_PPC_GNU_VTINHERIT;        break;
     case BFD_RELOC_VTABLE_ENTRY:       r = R_PPC_GNU_VTENTRY;          break;
     }
     case BFD_RELOC_VTABLE_INHERIT:     r = R_PPC_GNU_VTINHERIT;        break;
     case BFD_RELOC_VTABLE_ENTRY:       r = R_PPC_GNU_VTENTRY;          break;
     }
@@ -2058,7 +2071,10 @@ ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
                         bfd *output_bfd,
                         char **error_message ATTRIBUTE_UNUSED)
 {
                         bfd *output_bfd,
                         char **error_message ATTRIBUTE_UNUSED)
 {
-  bfd_vma relocation;
+  enum elf_ppc_reloc_type r_type;
+  long insn;
+  bfd_size_type octets;
+  bfd_vma value;
 
   if (output_bfd != NULL)
     {
 
   if (output_bfd != NULL)
     {
@@ -2066,20 +2082,28 @@ ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
       return bfd_reloc_ok;
     }
 
       return bfd_reloc_ok;
     }
 
-  if (bfd_is_com_section (symbol->section))
-    relocation = 0;
-  else
-    relocation = symbol->value;
-
-  relocation += symbol->section->output_section->vma;
-  relocation += symbol->section->output_offset;
-  relocation += reloc_entry->addend;
-  if (reloc_entry->howto->pc_relative)
-    relocation -= reloc_entry->address;
-
-  reloc_entry->addend += (relocation & 0x8000) << 1;
-
-  return bfd_reloc_continue;
+  reloc_entry->addend += 0x8000;
+  r_type = reloc_entry->howto->type;
+  if (r_type != R_PPC_REL16DX_HA)
+    return bfd_reloc_continue;
+
+  value = 0;
+  if (!bfd_is_com_section (symbol->section))
+    value = symbol->value;
+  value += (reloc_entry->addend
+           + symbol->section->output_offset
+           + symbol->section->output_section->vma);
+  value -= (reloc_entry->address
+           + input_section->output_offset
+           + input_section->output_section->vma);
+  value >>= 16;
+
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
+  insn &= ~0x1fffc1;
+  insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
+  bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
+  return bfd_reloc_ok;
 }
 
 static bfd_reloc_status_type
 }
 
 static bfd_reloc_status_type
@@ -2172,13 +2196,94 @@ ppc_elf_mkobject (bfd *abfd)
                                  PPC32_ELF_DATA);
 }
 
                                  PPC32_ELF_DATA);
 }
 
+/* When defaulting arch/mach, decode apuinfo to find a better match.  */
+
+bfd_boolean
+_bfd_elf_ppc_set_arch (bfd *abfd)
+{
+  unsigned long mach = 0;
+  asection *s;
+  unsigned char *contents;
+
+  if (abfd->arch_info->bits_per_word == 32
+      && bfd_big_endian (abfd))
+    {
+
+      for (s = abfd->sections; s != NULL; s = s->next)
+       if ((elf_section_data (s)->this_hdr.sh_flags & SHF_PPC_VLE) != 0)
+         break;
+      if (s != NULL)
+       mach = bfd_mach_ppc_vle;
+    }
+
+  if (mach == 0)
+    {
+      s = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
+      if (s != NULL && bfd_malloc_and_get_section (abfd, s, &contents))
+       {
+         unsigned int apuinfo_size = bfd_get_32 (abfd, contents + 4);
+         unsigned int i;
+
+         for (i = 20; i < apuinfo_size + 20 && i + 4 <= s->size; i += 4)
+           {
+             unsigned int val = bfd_get_32 (abfd, contents + i);
+             switch (val >> 16)
+               {
+               case PPC_APUINFO_PMR:
+               case PPC_APUINFO_RFMCI:
+                 if (mach == 0)
+                   mach = bfd_mach_ppc_titan;
+                 break;
+
+               case PPC_APUINFO_ISEL:
+               case PPC_APUINFO_CACHELCK:
+                 if (mach == bfd_mach_ppc_titan)
+                   mach = bfd_mach_ppc_e500mc;
+                 break;
+
+               case PPC_APUINFO_SPE:
+               case PPC_APUINFO_EFS:
+               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;
+                 break;
+
+               default:
+                 mach = -1ul;
+               }
+           }
+         free (contents);
+       }
+    }
+
+  if (mach != 0 && mach != -1ul)
+    {
+      const bfd_arch_info_type *arch;
+
+      for (arch = abfd->arch_info->next; arch; arch = arch->next)
+       if (arch->mach == mach)
+         {
+           abfd->arch_info = arch;
+           break;
+         }
+    }
+  return TRUE;
+}
+
 /* Fix bad default arch selected for a 32 bit input bfd when the
 /* Fix bad default arch selected for a 32 bit input bfd when the
-   default is 64 bit.  */
+   default is 64 bit.  Also select arch based on apuinfo.  */
 
 static bfd_boolean
 ppc_elf_object_p (bfd *abfd)
 {
 
 static bfd_boolean
 ppc_elf_object_p (bfd *abfd)
 {
-  if (abfd->arch_info->the_default && abfd->arch_info->bits_per_word == 64)
+  if (!abfd->arch_info->the_default)
+    return TRUE;
+
+  if (abfd->arch_info->bits_per_word == 64)
     {
       Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
 
     {
       Elf_Internal_Ehdr *i_ehdr = elf_elfheader (abfd);
 
@@ -2189,7 +2294,7 @@ ppc_elf_object_p (bfd *abfd)
          BFD_ASSERT (abfd->arch_info->bits_per_word == 32);
        }
     }
          BFD_ASSERT (abfd->arch_info->bits_per_word == 32);
        }
     }
-  return TRUE;
+  return _bfd_elf_ppc_set_arch (abfd);
 }
 
 /* Function to set whether a module needs the -mrelocatable bit set.  */
 }
 
 /* Function to set whether a module needs the -mrelocatable bit set.  */
@@ -2270,14 +2375,15 @@ ppc_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 }
 
 char *
 }
 
 char *
-elfcore_write_ppc_linux_prpsinfo32 (bfd *abfd, char *buf, int *bufsiz,
-                                     const struct elf_internal_linux_prpsinfo *prpsinfo)
+elfcore_write_ppc_linux_prpsinfo32
+  (bfd *abfd,
+   char *buf,
+   int *bufsiz,
+   const struct elf_internal_linux_prpsinfo *prpsinfo)
 {
   struct elf_external_ppc_linux_prpsinfo32 data;
 
 {
   struct elf_external_ppc_linux_prpsinfo32 data;
 
-  memset (&data, 0, sizeof (data));
-  PPC_LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
-
+  swap_ppc_linux_prpsinfo32_out (abfd, prpsinfo, &data);
   return elfcore_write_note (abfd, buf, bufsiz,
                             "CORE", NT_PRPSINFO, &data, sizeof (data));
 }
   return elfcore_write_note (abfd, buf, bufsiz,
                             "CORE", NT_PRPSINFO, &data, sizeof (data));
 }
@@ -2338,18 +2444,6 @@ ppc_elf_lookup_section_flags (char *flag_name)
   return 0;
 }
 
   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.  */
 
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -2429,10 +2523,7 @@ bfd_boolean
 ppc_elf_modify_segment_map (bfd *abfd,
                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
 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
 
   /* 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
@@ -2442,25 +2533,59 @@ ppc_elf_modify_segment_map (bfd *abfd,
 
   for (m = elf_seg_map (abfd); m != NULL; m = m->next)
     {
 
   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;
 
        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;
 
        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.  */
 
         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);
       amt = sizeof (struct elf_segment_map);
       amt += (m->count - j - 1) * sizeof (asection *);
       n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -2468,20 +2593,13 @@ ppc_elf_modify_segment_map (bfd *abfd,
         return FALSE;
 
       n->p_type = PT_LOAD;
         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->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;
       n->next = m->next;
       m->next = n;
-
-      /* Fix the current segment  */
-      m->count = j;
     }
 
   return TRUE;
     }
 
   return TRUE;
@@ -2494,16 +2612,16 @@ ppc_elf_modify_segment_map (bfd *abfd,
 
 static const struct bfd_elf_special_section ppc_elf_special_sections[] =
 {
 
 static const struct bfd_elf_special_section ppc_elf_special_sections[] =
 {
-  { STRING_COMMA_LEN (".plt"),             0, SHT_NOBITS,   SHF_ALLOC + SHF_EXECINSTR },
-  { STRING_COMMA_LEN (".sbss"),           -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".sbss2"),          -2, SHT_PROGBITS, SHF_ALLOC },
-  { STRING_COMMA_LEN (".sdata"),          -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { STRING_COMMA_LEN (".sdata2"),         -2, SHT_PROGBITS, SHF_ALLOC },
-  { STRING_COMMA_LEN (".tags"),            0, SHT_ORDERED,  SHF_ALLOC },
-  { STRING_COMMA_LEN (".PPC.EMB.apuinfo"), 0, SHT_NOTE,     0 },
-  { STRING_COMMA_LEN (".PPC.EMB.sbss0"),   0, SHT_PROGBITS, SHF_ALLOC },
-  { STRING_COMMA_LEN (".PPC.EMB.sdata0"),  0, SHT_PROGBITS, SHF_ALLOC },
-  { NULL,                              0,  0, 0,            0 }
+  { STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, SHF_ALLOC + SHF_EXECINSTR },
+  { STRING_COMMA_LEN (".sbss"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".sbss2"), -2, SHT_PROGBITS, SHF_ALLOC },
+  { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".sdata2"), -2, SHT_PROGBITS, SHF_ALLOC },
+  { STRING_COMMA_LEN (".tags"), 0, SHT_ORDERED, SHF_ALLOC },
+  { STRING_COMMA_LEN (APUINFO_SECTION_NAME), 0, SHT_NOTE, 0 },
+  { STRING_COMMA_LEN (".PPC.EMB.sbss0"), 0, SHT_PROGBITS, SHF_ALLOC },
+  { STRING_COMMA_LEN (".PPC.EMB.sdata0"), 0, SHT_PROGBITS, SHF_ALLOC },
+  { NULL, 0, 0, 0, 0 }
 };
 
 /* This is what we want for new plt/got.  */
 };
 
 /* This is what we want for new plt/got.  */
@@ -2612,9 +2730,6 @@ apuinfo_list_finish (void)
   head = NULL;
 }
 
   head = NULL;
 }
 
-#define APUINFO_SECTION_NAME   ".PPC.EMB.apuinfo"
-#define APUINFO_LABEL          "APUinfo"
-
 /* Scan the input BFDs and create a linked list of
    the APUinfo values that will need to be emitted.  */
 
 /* Scan the input BFDs and create a linked list of
    the APUinfo values that will need to be emitted.  */
 
@@ -3263,7 +3378,8 @@ static struct bfd_link_hash_table *
 ppc_elf_link_hash_table_create (bfd *abfd)
 {
   struct ppc_elf_link_hash_table *ret;
 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 };
+  static struct ppc_elf_params default_params
+    = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 };
 
   ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
   if (ret == NULL)
 
   ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
   if (ret == NULL)
@@ -3309,6 +3425,7 @@ ppc_elf_link_params (struct bfd_link_info *info, struct ppc_elf_params *params)
 
   if (htab)
     htab->params = params;
 
   if (htab)
     htab->params = params;
+  params->pagesize_p2 = bfd_log2 (params->pagesize);
 }
 
 /* Create .got and the related sections.  */
 }
 
 /* Create .got and the related sections.  */
@@ -3649,11 +3766,10 @@ ppc_elf_add_symbol_hook (bfd *abfd,
       *valp = sym->st_size;
     }
 
       *valp = sym->st_size;
     }
 
-  if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
-       || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
+  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
       && (abfd->flags & DYNAMIC) == 0
       && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
       && (abfd->flags & DYNAMIC) == 0
       && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
-    elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any;
+    elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc;
 
   return TRUE;
 }
 
   return TRUE;
 }
@@ -3845,7 +3961,8 @@ 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_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
 }
 
 static void
@@ -3921,6 +4038,7 @@ ppc_elf_check_relocs (bfd *abfd,
       enum elf_ppc_reloc_type r_type;
       struct elf_link_hash_entry *h;
       int tls_type;
       enum elf_ppc_reloc_type r_type;
       struct elf_link_hash_entry *h;
       int tls_type;
+      struct plt_entry **ifunc;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
@@ -3953,6 +4071,7 @@ ppc_elf_check_relocs (bfd *abfd,
 
       tls_type = 0;
       r_type = ELF32_R_TYPE (rel->r_info);
 
       tls_type = 0;
       r_type = ELF32_R_TYPE (rel->r_info);
+      ifunc = NULL;
       if (h == NULL && !htab->is_vxworks)
        {
          Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
       if (h == NULL && !htab->is_vxworks)
        {
          Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
@@ -3962,8 +4081,6 @@ ppc_elf_check_relocs (bfd *abfd,
 
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
 
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
-             struct plt_entry **ifunc;
-
              /* Set PLT_IFUNC flag for this sym, no GOT entry yet.  */
              ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
                                             PLT_IFUNC);
              /* Set PLT_IFUNC flag for this sym, no GOT entry yet.  */
              ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
                                             PLT_IFUNC);
@@ -4197,21 +4314,20 @@ ppc_elf_check_relocs (bfd *abfd,
 #ifdef DEBUG
          fprintf (stderr, "Reloc requires a PLT entry\n");
 #endif
 #ifdef DEBUG
          fprintf (stderr, "Reloc requires a PLT entry\n");
 #endif
-         /* This symbol requires a procedure linkage table entry.  We
-            actually build the entry in finish_dynamic_symbol,
-            because this might be a case of linking PIC code without
-            linking in any dynamic objects, in which case we don't
-            need to generate a procedure linkage table after all.  */
-
+         /* This symbol requires a procedure linkage table entry.  */
          if (h == NULL)
            {
          if (h == NULL)
            {
-             /* It does not make sense to have a procedure linkage
-                table entry for a local symbol.  */
-             info->callbacks->einfo (_("%P: %H: %s reloc against local symbol\n"),
-                                     abfd, sec, rel->r_offset,
-                                     ppc_elf_howto_table[r_type]->name);
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
+             if (ifunc == NULL)
+               {
+                 /* It does not make sense to have a procedure linkage
+                    table entry for a non-ifunc local symbol.  */
+                 info->callbacks->einfo
+                   (_("%P: %H: %s reloc against local symbol\n"),
+                    abfd, sec, rel->r_offset,
+                    ppc_elf_howto_table[r_type]->name);
+                 bfd_set_error (bfd_error_bad_value);
+                 return FALSE;
+               }
            }
          else
            {
            }
          else
            {
@@ -4247,6 +4363,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_REL16_LO:
        case R_PPC_REL16_HI:
        case R_PPC_REL16_HA:
        case R_PPC_REL16_LO:
        case R_PPC_REL16_HI:
        case R_PPC_REL16_HA:
+       case R_PPC_REL16DX_HA:
          ppc_elf_tdata (abfd)->has_rel16 = 1;
          break;
 
          ppc_elf_tdata (abfd)->has_rel16 = 1;
          break;
 
@@ -4286,14 +4403,6 @@ ppc_elf_check_relocs (bfd *abfd,
            }
          if (h != NULL && h->type == STT_GNU_IFUNC)
            {
            }
          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;
              h->needs_plt = 1;
              if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
                return FALSE;
@@ -4795,6 +4904,7 @@ ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *loc,
   insn = bfd_get_32 (output_bfd, loc);
   top5 = value & 0xf800;
   top5 = top5 << (split16_format == split16a_type ? 9 : 5);
   insn = bfd_get_32 (output_bfd, loc);
   top5 = value & 0xf800;
   top5 = top5 << (split16_format == split16a_type ? 9 : 5);
+  insn &= (split16_format == split16a_type ? ~0x1f007ff : ~0x1f07ff);
   insn |= top5;
   insn |= value & 0x7ff;
   bfd_put_32 (output_bfd, insn, loc);
   insn |= top5;
   insn |= value & 0x7ff;
   bfd_put_32 (output_bfd, insn, loc);
@@ -5138,6 +5248,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
                  tga->root.type = bfd_link_hash_indirect;
                  tga->root.u.i.link = &opt->root;
                  ppc_elf_copy_indirect_symbol (info, opt, tga);
                  tga->root.type = bfd_link_hash_indirect;
                  tga->root.u.i.link = &opt->root;
                  ppc_elf_copy_indirect_symbol (info, opt, tga);
+                 opt->forced_local = 0;
                  if (opt->dynindx != -1)
                    {
                      /* Use __tls_get_addr_opt in dynamic relocations.  */
                  if (opt->dynindx != -1)
                    {
                      /* Use __tls_get_addr_opt in dynamic relocations.  */
@@ -6397,7 +6508,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       && htab->elf.dynamic_sections_created)
     {
       htab->glink_pltresolve = htab->glink->size;
       && 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
       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
@@ -7604,7 +7717,9 @@ is_insn_ds_form (unsigned int insn)
 static bfd_boolean
 is_insn_dq_form (unsigned int insn)
 {
 static bfd_boolean
 is_insn_dq_form (unsigned int insn)
 {
-  return (insn & (0x3f << 26)) == 56u << 26; /* lq */
+  return ((insn & (0x3f << 26)) == 56u << 26 /* lq */
+         || ((insn & (0x3f << 26)) == (61u << 26) /* lxv, stxv */
+             && (insn & 3) == 1));
 }
 
 /* The RELOCATE_SECTION function is called by the ELF backend linker
 }
 
 /* The RELOCATE_SECTION function is called by the ELF backend linker
@@ -8199,6 +8314,26 @@ ppc_elf_relocate_section (bfd *output_bfd,
            }
          if (ent != NULL)
            {
            }
          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
+                     (_("%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;
              if (h == NULL && (ent->plt.offset & 1) == 0)
                {
                  Elf_Internal_Rela rela;
@@ -8539,15 +8674,28 @@ ppc_elf_relocate_section (bfd *output_bfd,
             at a symbol not in this object.  */
          if (unresolved_reloc)
            {
             at a symbol not in this object.  */
          if (unresolved_reloc)
            {
-             if (! (*info->callbacks->undefined_symbol) (info,
-                                                         h->root.root.string,
-                                                         input_bfd,
-                                                         input_section,
-                                                         rel->r_offset,
-                                                         TRUE))
-               return FALSE;
+             (*info->callbacks->undefined_symbol) (info,
+                                                   h->root.root.string,
+                                                   input_bfd,
+                                                   input_section,
+                                                   rel->r_offset,
+                                                   TRUE);
              goto copy_reloc;
            }
              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.  */
+             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:
          break;
 
        case R_PPC_DTPREL16:
@@ -8605,6 +8753,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_REL16_LO:
        case R_PPC_REL16_HI:
        case R_PPC_REL16_HA:
        case R_PPC_REL16_LO:
        case R_PPC_REL16_HI:
        case R_PPC_REL16_HA:
+       case R_PPC_REL16DX_HA:
          break;
 
        case R_PPC_REL32:
          break;
 
        case R_PPC_REL32:
@@ -8937,8 +9086,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_PLTREL24:
          if (h != NULL && ifunc == NULL)
            {
        case R_PPC_PLTREL24:
          if (h != NULL && ifunc == NULL)
            {
-             struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
-                                                   bfd_link_pic (info) ? addend : 0);
+             struct plt_entry *ent;
+
+             ent = find_plt_ent (&h->plt.plist, got2,
+                                 bfd_link_pic (info) ? addend : 0);
              if (ent == NULL
                  || htab->plt == NULL)
                {
              if (ent == NULL
                  || htab->plt == NULL)
                {
@@ -9311,6 +9462,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_ADDR16_HA:
        case R_PPC_REL16_HA:
 
        case R_PPC_ADDR16_HA:
        case R_PPC_REL16_HA:
+       case R_PPC_REL16DX_HA:
        case R_PPC_SECTOFF_HA:
        case R_PPC_TPREL16_HA:
        case R_PPC_DTPREL16_HA:
        case R_PPC_SECTOFF_HA:
        case R_PPC_TPREL16_HA:
        case R_PPC_DTPREL16_HA:
@@ -9369,10 +9521,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
              mask = 15;
            else
              break;
              mask = 15;
            else
              break;
-           lobit = mask & (relocation + addend);
+           relocation += addend;
+           addend = insn & mask;
+           lobit = mask & relocation;
            if (lobit != 0)
              {
            if (lobit != 0)
              {
-               addend -= lobit;
+               relocation ^= lobit;
                info->callbacks->einfo
                  (_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
                   input_bfd, input_section, rel->r_offset,
                info->callbacks->einfo
                  (_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
                   input_bfd, input_section, rel->r_offset,
@@ -9380,7 +9534,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                bfd_set_error (bfd_error_bad_value);
                ret = FALSE;
              }
                bfd_set_error (bfd_error_bad_value);
                ret = FALSE;
              }
-           addend += insn & mask;
          }
          break;
        }
          }
          break;
        }
@@ -9439,8 +9592,30 @@ ppc_elf_relocate_section (bfd *output_bfd,
            }
        }
 
            }
        }
 
-      r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
-                                   rel->r_offset, relocation, addend);
+      if (r_type == R_PPC_REL16DX_HA)
+       {
+         /* Split field reloc isn't handled by _bfd_final_link_relocate.  */
+         if (rel->r_offset + 4 > input_section->size)
+           r = bfd_reloc_outofrange;
+         else
+           {
+             unsigned int insn;
+
+             relocation += addend;
+             relocation -= (rel->r_offset
+                            + input_section->output_offset
+                            + input_section->output_section->vma);
+             relocation >>= 16;
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             insn &= ~0x1fffc1;
+             insn |= (relocation & 0xffc1) | ((relocation & 0x3e) << 15);
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+             r = bfd_reloc_ok;
+           }
+       }
+      else
+       r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
+                                     rel->r_offset, relocation, addend);
 
       if (r != bfd_reloc_ok)
        {
 
       if (r != bfd_reloc_ok)
        {
@@ -9454,13 +9629,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                       && (h->root.type == bfd_link_hash_undefweak
                           || h->root.type == bfd_link_hash_undefined)
                       && is_branch_reloc (r_type)))
                       && (h->root.type == bfd_link_hash_undefweak
                           || h->root.type == bfd_link_hash_undefined)
                       && is_branch_reloc (r_type)))
-               {
-                 if (!((*info->callbacks->reloc_overflow)
-                       (info, (h ? &h->root : NULL), sym_name,
-                        howto->name, rel->r_addend,
-                        input_bfd, input_section, rel->r_offset)))
-                   return FALSE;
-               }
+               info->callbacks->reloc_overflow
+                 (info, (h ? &h->root : NULL), sym_name, howto->name,
+                  rel->r_addend, input_bfd, input_section, rel->r_offset);
            }
          else
            {
            }
          else
            {
@@ -10701,7 +10872,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_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"
 
 
 #include "elf32-target.h"
 
This page took 0.046995 seconds and 4 git commands to generate.