gdb/dwarf: pass compilation directory to line header
[binutils-gdb.git] / bfd / elf32-ppc.c
index 0ae7e0bcf6495423059add314000b44d0703ac41..3582711d9620054219c014a5c8e8d8b0104e138f 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 32-bit ELF
 /* PowerPC-specific support for 32-bit ELF
-   Copyright (C) 1994-2021 Free Software Foundation, Inc.
+   Copyright (C) 1994-2022 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.
    Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
    Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
-/* Don't generate unused section symbols.  */
-#define TARGET_KEEP_UNUSED_SECTION_SYMBOLS false
+/* The assembler should generate a full set of section symbols even
+   when they appear unused.  The linux kernel build tool recordmcount
+   needs them.  */
+#define TARGET_KEEP_UNUSED_SECTION_SYMBOLS true
 
 #include "sysdep.h"
 #include <stdarg.h>
 
 #include "sysdep.h"
 #include <stdarg.h>
@@ -204,95 +206,95 @@ static reloc_howto_type *ppc_elf_howto_table[R_PPC_max];
 
 static reloc_howto_type ppc_elf_howto_raw[] = {
   /* This reloc does nothing.  */
 
 static reloc_howto_type ppc_elf_howto_raw[] = {
   /* This reloc does nothing.  */
-  HOW (R_PPC_NONE, 3, 0, 0, 0, false, dont,
+  HOW (R_PPC_NONE, 0, 0, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* A standard 32 bit relocation.  */
        bfd_elf_generic_reloc),
 
   /* A standard 32 bit relocation.  */
-  HOW (R_PPC_ADDR32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_ADDR32, 4, 32, 0xffffffff, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* An absolute 26 bit branch; the lower two bits must be zero.
      FIXME: we don't check that, we just clear them.  */
        bfd_elf_generic_reloc),
 
   /* An absolute 26 bit branch; the lower two bits must be zero.
      FIXME: we don't check that, we just clear them.  */
-  HOW (R_PPC_ADDR24, 2, 26, 0x3fffffc, 0, false, signed,
+  HOW (R_PPC_ADDR24, 4, 26, 0x3fffffc, 0, false, signed,
        bfd_elf_generic_reloc),
 
   /* A standard 16 bit relocation.  */
        bfd_elf_generic_reloc),
 
   /* A standard 16 bit relocation.  */
-  HOW (R_PPC_ADDR16, 1, 16, 0xffff, 0, false, bitfield,
+  HOW (R_PPC_ADDR16, 2, 16, 0xffff, 0, false, bitfield,
        bfd_elf_generic_reloc),
 
   /* A 16 bit relocation without overflow.  */
        bfd_elf_generic_reloc),
 
   /* A 16 bit relocation without overflow.  */
-  HOW (R_PPC_ADDR16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_ADDR16_LO, 2, 16, 0xffff, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of an address.  */
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of an address.  */
-  HOW (R_PPC_ADDR16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_ADDR16_HI, 2, 16, 0xffff, 16, false, dont,
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of an address, plus 1 if the contents of
      the low 16 bits, treated as a signed number, is negative.  */
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of an address, plus 1 if the contents of
      the low 16 bits, treated as a signed number, is negative.  */
-  HOW (R_PPC_ADDR16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_ADDR16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_addr16_ha_reloc),
 
   /* An absolute 16 bit branch; the lower two bits must be zero.
      FIXME: we don't check that, we just clear them.  */
        ppc_elf_addr16_ha_reloc),
 
   /* An absolute 16 bit branch; the lower two bits must be zero.
      FIXME: we don't check that, we just clear them.  */
-  HOW (R_PPC_ADDR14, 2, 16, 0xfffc, 0, false, signed,
+  HOW (R_PPC_ADDR14, 4, 16, 0xfffc, 0, false, signed,
        bfd_elf_generic_reloc),
 
   /* An absolute 16 bit branch, for which bit 10 should be set to
      indicate that the branch is expected to be taken. The lower two
      bits must be zero.  */
        bfd_elf_generic_reloc),
 
   /* An absolute 16 bit branch, for which bit 10 should be set to
      indicate that the branch is expected to be taken. The lower two
      bits must be zero.  */
-  HOW (R_PPC_ADDR14_BRTAKEN, 2, 16, 0xfffc, 0, false, signed,
+  HOW (R_PPC_ADDR14_BRTAKEN, 4, 16, 0xfffc, 0, false, signed,
        bfd_elf_generic_reloc),
 
   /* An absolute 16 bit branch, for which bit 10 should be set to
      indicate that the branch is not expected to be taken.  The lower
      two bits must be zero.  */
        bfd_elf_generic_reloc),
 
   /* An absolute 16 bit branch, for which bit 10 should be set to
      indicate that the branch is not expected to be taken.  The lower
      two bits must be zero.  */
-  HOW (R_PPC_ADDR14_BRNTAKEN, 2, 16, 0xfffc, 0, false, signed,
+  HOW (R_PPC_ADDR14_BRNTAKEN, 4, 16, 0xfffc, 0, false, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 26 bit branch; the lower two bits must be zero.  */
        bfd_elf_generic_reloc),
 
   /* A relative 26 bit branch; the lower two bits must be zero.  */
-  HOW (R_PPC_REL24, 2, 26, 0x3fffffc, 0, true, signed,
+  HOW (R_PPC_REL24, 4, 26, 0x3fffffc, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch; the lower two bits must be zero.  */
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch; the lower two bits must be zero.  */
-  HOW (R_PPC_REL14, 2, 16, 0xfffc, 0, true, signed,
+  HOW (R_PPC_REL14, 4, 16, 0xfffc, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch.  Bit 10 should be set to indicate that
      the branch is expected to be taken.  The lower two bits must be
      zero.  */
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch.  Bit 10 should be set to indicate that
      the branch is expected to be taken.  The lower two bits must be
      zero.  */
-  HOW (R_PPC_REL14_BRTAKEN, 2, 16, 0xfffc, 0, true, signed,
+  HOW (R_PPC_REL14_BRTAKEN, 4, 16, 0xfffc, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch.  Bit 10 should be set to indicate that
      the branch is not expected to be taken.  The lower two bits must
      be zero.  */
        bfd_elf_generic_reloc),
 
   /* A relative 16 bit branch.  Bit 10 should be set to indicate that
      the branch is not expected to be taken.  The lower two bits must
      be zero.  */
-  HOW (R_PPC_REL14_BRNTAKEN, 2, 16, 0xfffc, 0, true, signed,
+  HOW (R_PPC_REL14_BRNTAKEN, 4, 16, 0xfffc, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR16, but referring to the GOT table entry for the
      symbol.  */
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR16, but referring to the GOT table entry for the
      symbol.  */
-  HOW (R_PPC_GOT16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_GOT16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
      the symbol.  */
-  HOW (R_PPC_GOT16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_GOT16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
      the symbol.  */
-  HOW (R_PPC_GOT16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
      the symbol.  */
-  HOW (R_PPC_GOT16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_REL24, but referring to the procedure linkage table
      entry for the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_REL24, but referring to the procedure linkage table
      entry for the symbol.  */
-  HOW (R_PPC_PLTREL24, 2, 26, 0x3fffffc, 0, true, signed,
+  HOW (R_PPC_PLTREL24, 4, 26, 0x3fffffc, 0, true, signed,
        ppc_elf_unhandled_reloc),
 
   /* This is used only by the dynamic linker.  The symbol should exist
        ppc_elf_unhandled_reloc),
 
   /* This is used only by the dynamic linker.  The symbol should exist
@@ -300,269 +302,269 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
      dynamic linker copies the data addressed by the symbol from the
      shared library into the object, because the object being
      run has to have the data at some particular address.  */
      dynamic linker copies the data addressed by the symbol from the
      shared library into the object, because the object being
      run has to have the data at some particular address.  */
-  HOW (R_PPC_COPY, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_COPY, 4, 32, 0, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR32, but used when setting global offset table
      entries.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR32, but used when setting global offset table
      entries.  */
-  HOW (R_PPC_GLOB_DAT, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_GLOB_DAT, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Marks a procedure linkage table entry for a symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Marks a procedure linkage table entry for a symbol.  */
-  HOW (R_PPC_JMP_SLOT, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_JMP_SLOT, 4, 32, 0, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Used only by the dynamic linker.  When the object is run, this
      longword is set to the load address of the object, plus the
      addend.  */
        ppc_elf_unhandled_reloc),
 
   /* Used only by the dynamic linker.  When the object is run, this
      longword is set to the load address of the object, plus the
      addend.  */
-  HOW (R_PPC_RELATIVE, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_RELATIVE, 4, 32, 0xffffffff, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_REL24, but uses the value of the symbol within the
      object rather than the final value.  Normally used for
      _GLOBAL_OFFSET_TABLE_.  */
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_REL24, but uses the value of the symbol within the
      object rather than the final value.  Normally used for
      _GLOBAL_OFFSET_TABLE_.  */
-  HOW (R_PPC_LOCAL24PC, 2, 26, 0x3fffffc, 0, true, signed,
+  HOW (R_PPC_LOCAL24PC, 4, 26, 0x3fffffc, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR32, but may be unaligned.  */
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR32, but may be unaligned.  */
-  HOW (R_PPC_UADDR32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_UADDR32, 4, 32, 0xffffffff, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR16, but may be unaligned.  */
        bfd_elf_generic_reloc),
 
   /* Like R_PPC_ADDR16, but may be unaligned.  */
-  HOW (R_PPC_UADDR16, 1, 16, 0xffff, 0, false, bitfield,
+  HOW (R_PPC_UADDR16, 2, 16, 0xffff, 0, false, bitfield,
        bfd_elf_generic_reloc),
 
   /* 32-bit PC relative */
        bfd_elf_generic_reloc),
 
   /* 32-bit PC relative */
-  HOW (R_PPC_REL32, 2, 32, 0xffffffff, 0, true, dont,
+  HOW (R_PPC_REL32, 4, 32, 0xffffffff, 0, true, dont,
        bfd_elf_generic_reloc),
 
   /* 32-bit relocation to the symbol's procedure linkage table.
      FIXME: not supported.  */
        bfd_elf_generic_reloc),
 
   /* 32-bit relocation to the symbol's procedure linkage table.
      FIXME: not supported.  */
-  HOW (R_PPC_PLT32, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_PLT32, 4, 32, 0, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* 32-bit PC relative relocation to the symbol's procedure linkage table.
      FIXME: not supported.  */
        ppc_elf_unhandled_reloc),
 
   /* 32-bit PC relative relocation to the symbol's procedure linkage table.
      FIXME: not supported.  */
-  HOW (R_PPC_PLTREL32, 2, 32, 0, 0, true, dont,
+  HOW (R_PPC_PLTREL32, 4, 32, 0, 0, true, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
      the symbol.  */
-  HOW (R_PPC_PLT16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_PLT16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
      the symbol.  */
-  HOW (R_PPC_PLT16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_PLT16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
      the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
      the symbol.  */
-  HOW (R_PPC_PLT16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_PLT16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
      small data items.  */
        ppc_elf_unhandled_reloc),
 
   /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
      small data items.  */
-  HOW (R_PPC_SDAREL16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_SDAREL16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* 16-bit section relative relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16-bit section relative relocation.  */
-  HOW (R_PPC_SECTOFF, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_SECTOFF, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* 16-bit lower half section relative relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16-bit lower half section relative relocation.  */
-  HOW (R_PPC_SECTOFF_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_SECTOFF_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* 16-bit upper half section relative relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16-bit upper half section relative relocation.  */
-  HOW (R_PPC_SECTOFF_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_SECTOFF_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* 16-bit upper half adjusted section relative relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16-bit upper half adjusted section relative relocation.  */
-  HOW (R_PPC_SECTOFF_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_SECTOFF_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Marker relocs for TLS.  */
        ppc_elf_unhandled_reloc),
 
   /* Marker relocs for TLS.  */
-  HOW (R_PPC_TLS, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_TLS, 4, 32, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
        bfd_elf_generic_reloc),
 
-  HOW (R_PPC_TLSGD, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_TLSGD, 4, 32, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
        bfd_elf_generic_reloc),
 
-  HOW (R_PPC_TLSLD, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_TLSLD, 4, 32, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* Marker relocs on inline plt call instructions.  */
        bfd_elf_generic_reloc),
 
   /* Marker relocs on inline plt call instructions.  */
-  HOW (R_PPC_PLTSEQ, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_PLTSEQ, 4, 32, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
        bfd_elf_generic_reloc),
 
-  HOW (R_PPC_PLTCALL, 2, 32, 0, 0, false, dont,
+  HOW (R_PPC_PLTCALL, 4, 32, 0, 0, false, dont,
        bfd_elf_generic_reloc),
 
   /* Computes the load module index of the load module that contains the
      definition of its TLS sym.  */
        bfd_elf_generic_reloc),
 
   /* Computes the load module index of the load module that contains the
      definition of its TLS sym.  */
-  HOW (R_PPC_DTPMOD32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_DTPMOD32, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Computes a dtv-relative displacement, the difference between the value
      of sym+add and the base address of the thread-local storage block that
      contains the definition of sym, minus 0x8000.  */
        ppc_elf_unhandled_reloc),
 
   /* Computes a dtv-relative displacement, the difference between the value
      of sym+add and the base address of the thread-local storage block that
      contains the definition of sym, minus 0x8000.  */
-  HOW (R_PPC_DTPREL32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_DTPREL32, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit dtprel reloc.  */
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit dtprel reloc.  */
-  HOW (R_PPC_DTPREL16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_DTPREL16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16, but no overflow.  */
-  HOW (R_PPC_DTPREL16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_DTPREL16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_DTPREL16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_DTPREL16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like DTPREL16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_DTPREL16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_DTPREL16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Computes a tp-relative displacement, the difference between the value of
      sym+add and the value of the thread pointer (r13).  */
        ppc_elf_unhandled_reloc),
 
   /* Computes a tp-relative displacement, the difference between the value of
      sym+add and the value of the thread pointer (r13).  */
-  HOW (R_PPC_TPREL32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_TPREL32, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit tprel reloc.  */
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit tprel reloc.  */
-  HOW (R_PPC_TPREL16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_TPREL16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16, but no overflow.  */
-  HOW (R_PPC_TPREL16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_TPREL16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_TPREL16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_TPREL16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like TPREL16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_TPREL16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_TPREL16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
      with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset
      to the first entry.  */
        ppc_elf_unhandled_reloc),
 
   /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
      with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset
      to the first entry.  */
-  HOW (R_PPC_GOT_TLSGD16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_GOT_TLSGD16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16, but no overflow.  */
-  HOW (R_PPC_GOT_TLSGD16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_GOT_TLSGD16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_GOT_TLSGD16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TLSGD16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSGD16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_GOT_TLSGD16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TLSGD16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
      with values (sym+add)@dtpmod and zero, and computes the offset to the
      first entry.  */
        ppc_elf_unhandled_reloc),
 
   /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
      with values (sym+add)@dtpmod and zero, and computes the offset to the
      first entry.  */
-  HOW (R_PPC_GOT_TLSLD16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_GOT_TLSLD16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16, but no overflow.  */
-  HOW (R_PPC_GOT_TLSLD16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_GOT_TLSLD16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_GOT_TLSLD16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TLSLD16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TLSLD16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_GOT_TLSLD16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TLSLD16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes
      the offset to the entry.  */
        ppc_elf_unhandled_reloc),
 
   /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes
      the offset to the entry.  */
-  HOW (R_PPC_GOT_DTPREL16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_GOT_DTPREL16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16, but no overflow.  */
-  HOW (R_PPC_GOT_DTPREL16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_GOT_DTPREL16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_GOT_DTPREL16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_DTPREL16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_DTPREL16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_GOT_DTPREL16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_DTPREL16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the
      offset to the entry.  */
        ppc_elf_unhandled_reloc),
 
   /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the
      offset to the entry.  */
-  HOW (R_PPC_GOT_TPREL16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_GOT_TPREL16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16, but no overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16, but no overflow.  */
-  HOW (R_PPC_GOT_TPREL16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_GOT_TPREL16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16_LO, but next higher group of 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16_LO, but next higher group of 16 bits.  */
-  HOW (R_PPC_GOT_TPREL16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TPREL16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16_HI, but adjust for low 16 bits.  */
        ppc_elf_unhandled_reloc),
 
   /* Like GOT_TPREL16_HI, but adjust for low 16 bits.  */
-  HOW (R_PPC_GOT_TPREL16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_GOT_TPREL16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The remaining relocs are from the Embedded ELF ABI, and are not
      in the SVR4 ELF ABI.  */
 
   /* 32 bit value resulting from the addend minus the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* The remaining relocs are from the Embedded ELF ABI, and are not
      in the SVR4 ELF ABI.  */
 
   /* 32 bit value resulting from the addend minus the symbol.  */
-  HOW (R_PPC_EMB_NADDR32, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_EMB_NADDR32, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from the addend minus the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from the addend minus the symbol.  */
-  HOW (R_PPC_EMB_NADDR16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_NADDR16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from the addend minus the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from the addend minus the symbol.  */
-  HOW (R_PPC_EMB_NADDR16_LO, 1, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_EMB_NADDR16_LO, 2, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The high order 16 bits of the addend minus the symbol.  */
        ppc_elf_unhandled_reloc),
 
   /* The high order 16 bits of the addend minus the symbol.  */
-  HOW (R_PPC_EMB_NADDR16_HI, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_EMB_NADDR16_HI, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The high order 16 bits of the result of the addend minus the address,
      plus 1 if the contents of the low 16 bits, treated as a signed number,
      is negative.  */
        ppc_elf_unhandled_reloc),
 
   /* The high order 16 bits of the result of the addend minus the address,
      plus 1 if the contents of the low 16 bits, treated as a signed number,
      is negative.  */
-  HOW (R_PPC_EMB_NADDR16_HA, 1, 16, 0xffff, 16, false, dont,
+  HOW (R_PPC_EMB_NADDR16_HA, 2, 16, 0xffff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from allocating a 4 byte word to hold an
      address in the .sdata section, and returning the offset from
      _SDA_BASE_ for that relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from allocating a 4 byte word to hold an
      address in the .sdata section, and returning the offset from
      _SDA_BASE_ for that relocation.  */
-  HOW (R_PPC_EMB_SDAI16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_SDAI16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from allocating a 4 byte word to hold an
      address in the .sdata2 section, and returning the offset from
      _SDA2_BASE_ for that relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* 16 bit value resulting from allocating a 4 byte word to hold an
      address in the .sdata2 section, and returning the offset from
      _SDA2_BASE_ for that relocation.  */
-  HOW (R_PPC_EMB_SDA2I16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_SDA2I16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
      small data items.  */
        ppc_elf_unhandled_reloc),
 
   /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
      small data items.  */
-  HOW (R_PPC_EMB_SDA2REL, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_SDA2REL, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
      signed offset from the appropriate base, and filling in the register
      field with the appropriate register (0, 2, or 13).  */
        ppc_elf_unhandled_reloc),
 
   /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
      signed offset from the appropriate base, and filling in the register
      field with the appropriate register (0, 2, or 13).  */
-  HOW (R_PPC_EMB_SDA21, 2, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_SDA21, 4, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Relocation not handled: R_PPC_EMB_MRKREF */
        ppc_elf_unhandled_reloc),
 
   /* Relocation not handled: R_PPC_EMB_MRKREF */
@@ -575,109 +577,109 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
   /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling
      in the 16 bit signed offset from the appropriate base, and filling in the
      register field with the appropriate register (0, 2, or 13).  */
   /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling
      in the 16 bit signed offset from the appropriate base, and filling in the
      register field with the appropriate register (0, 2, or 13).  */
-  HOW (R_PPC_EMB_RELSDA, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_EMB_RELSDA, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* A relative 8 bit branch.  */
        ppc_elf_unhandled_reloc),
 
   /* A relative 8 bit branch.  */
-  HOW (R_PPC_VLE_REL8, 1, 8, 0xff, 1, true, signed,
+  HOW (R_PPC_VLE_REL8, 2, 8, 0xff, 1, true, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 15 bit branch.  */
        bfd_elf_generic_reloc),
 
   /* A relative 15 bit branch.  */
-  HOW (R_PPC_VLE_REL15, 2, 16, 0xfffe, 0, true, signed,
+  HOW (R_PPC_VLE_REL15, 4, 16, 0xfffe, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* A relative 24 bit branch.  */
        bfd_elf_generic_reloc),
 
   /* A relative 24 bit branch.  */
-  HOW (R_PPC_VLE_REL24, 2, 25, 0x1fffffe, 0, true, signed,
+  HOW (R_PPC_VLE_REL24, 4, 25, 0x1fffffe, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* The 16 LSBS in split16a format.  */
        bfd_elf_generic_reloc),
 
   /* The 16 LSBS in split16a format.  */
-  HOW (R_PPC_VLE_LO16A, 2, 16, 0x1f07ff, 0, false, dont,
+  HOW (R_PPC_VLE_LO16A, 4, 16, 0x1f07ff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS in split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS in split16d format.  */
-  HOW (R_PPC_VLE_LO16D, 2, 16, 0x3e007ff, 0, false, dont,
+  HOW (R_PPC_VLE_LO16D, 4, 16, 0x3e007ff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 split16a format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 split16a format.  */
-  HOW (R_PPC_VLE_HI16A, 2, 16, 0x1f07ff, 16, false, dont,
+  HOW (R_PPC_VLE_HI16A, 4, 16, 0x1f07ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 split16d format.  */
-  HOW (R_PPC_VLE_HI16D, 2, 16, 0x3e007ff, 16, false, dont,
+  HOW (R_PPC_VLE_HI16D, 4, 16, 0x3e007ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (High Adjusted) in split16a format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (High Adjusted) in split16a format.  */
-  HOW (R_PPC_VLE_HA16A, 2, 16, 0x1f07ff, 16, false, dont,
+  HOW (R_PPC_VLE_HA16A, 4, 16, 0x1f07ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (High Adjusted) in split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (High Adjusted) in split16d format.  */
-  HOW (R_PPC_VLE_HA16D, 2, 16, 0x3e007ff, 16, false, dont,
+  HOW (R_PPC_VLE_HA16D, 4, 16, 0x3e007ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
      instructions.  If the register base is 0 then the linker changes
      the e_add16i to an e_li instruction.  */
        ppc_elf_unhandled_reloc),
 
   /* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
      instructions.  If the register base is 0 then the linker changes
      the e_add16i to an e_li instruction.  */
-  HOW (R_PPC_VLE_SDA21, 2, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_VLE_SDA21, 4, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_VLE_SDA21 but ignore overflow.  */
        ppc_elf_unhandled_reloc),
 
   /* Like R_PPC_VLE_SDA21 but ignore overflow.  */
-  HOW (R_PPC_VLE_SDA21_LO, 2, 16, 0xffff, 0, false, dont,
+  HOW (R_PPC_VLE_SDA21_LO, 4, 16, 0xffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16a format.  */
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16a format.  */
-  HOW (R_PPC_VLE_SDAREL_LO16A, 2, 16, 0x1f07ff, 0, false, dont,
+  HOW (R_PPC_VLE_SDAREL_LO16A, 4, 16, 0x1f07ff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* The 16 LSBS relative to _SDA_BASE_ in split16d format.  */
-  HOW (R_PPC_VLE_SDAREL_LO16D, 2, 16, 0x3e007ff, 0, false, dont,
+  HOW (R_PPC_VLE_SDAREL_LO16D, 4, 16, 0x3e007ff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16a format.  */
-  HOW (R_PPC_VLE_SDAREL_HI16A, 2, 16, 0x1f07ff, 16, false, dont,
+  HOW (R_PPC_VLE_SDAREL_HI16A, 4, 16, 0x1f07ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 relative to _SDA_BASE_ in split16d format.  */
-  HOW (R_PPC_VLE_SDAREL_HI16D, 2, 16, 0x3e007ff, 16, false, dont,
+  HOW (R_PPC_VLE_SDAREL_HI16D, 4, 16, 0x3e007ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16a format.  */
-  HOW (R_PPC_VLE_SDAREL_HA16A, 2, 16, 0x1f07ff, 16, false, dont,
+  HOW (R_PPC_VLE_SDAREL_HA16A, 4, 16, 0x1f07ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
        ppc_elf_unhandled_reloc),
 
   /* Bits 16-31 (HA) relative to _SDA_BASE split16d format.  */
-  HOW (R_PPC_VLE_SDAREL_HA16D, 2, 16, 0x3e007ff, 16, false, dont,
+  HOW (R_PPC_VLE_SDAREL_HA16D, 4, 16, 0x3e007ff, 16, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* e_li split20 format.  */
        ppc_elf_unhandled_reloc),
 
   /* e_li split20 format.  */
-  HOW (R_PPC_VLE_ADDR20, 2, 20, 0x1f7fff, 0, false, dont,
+  HOW (R_PPC_VLE_ADDR20, 4, 20, 0x1f7fff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
        ppc_elf_unhandled_reloc),
 
-  HOW (R_PPC_IRELATIVE, 2, 32, 0xffffffff, 0, false, dont,
+  HOW (R_PPC_IRELATIVE, 4, 32, 0xffffffff, 0, false, dont,
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit relative relocation.  */
        ppc_elf_unhandled_reloc),
 
   /* A 16 bit relative relocation.  */
-  HOW (R_PPC_REL16, 1, 16, 0xffff, 0, true, signed,
+  HOW (R_PPC_REL16, 2, 16, 0xffff, 0, true, signed,
        bfd_elf_generic_reloc),
 
   /* A 16 bit relative relocation without overflow.  */
        bfd_elf_generic_reloc),
 
   /* A 16 bit relative relocation without overflow.  */
-  HOW (R_PPC_REL16_LO, 1, 16, 0xffff, 0, true, dont,
+  HOW (R_PPC_REL16_LO, 2, 16, 0xffff, 0, true, dont,
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of a relative address.  */
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of a relative address.  */
-  HOW (R_PPC_REL16_HI, 1, 16, 0xffff, 16, true, dont,
+  HOW (R_PPC_REL16_HI, 2, 16, 0xffff, 16, true, dont,
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of a relative address, plus 1 if the contents of
      the low 16 bits, treated as a signed number, is negative.  */
        bfd_elf_generic_reloc),
 
   /* The high order 16 bits of a relative address, plus 1 if the contents of
      the low 16 bits, treated as a signed number, is negative.  */
-  HOW (R_PPC_REL16_HA, 1, 16, 0xffff, 16, true, dont,
+  HOW (R_PPC_REL16_HA, 2, 16, 0xffff, 16, true, dont,
        ppc_elf_addr16_ha_reloc),
 
   /* Like R_PPC_REL16_HA but for split field in addpcis.  */
        ppc_elf_addr16_ha_reloc),
 
   /* Like R_PPC_REL16_HA but for split field in addpcis.  */
-  HOW (R_PPC_REL16DX_HA, 2, 16, 0x1fffc1, 16, true, signed,
+  HOW (R_PPC_REL16DX_HA, 4, 16, 0x1fffc1, 16, true, signed,
        ppc_elf_addr16_ha_reloc),
 
   /* A split-field reloc for addpcis, non-relative (gas internal use only).  */
        ppc_elf_addr16_ha_reloc),
 
   /* A split-field reloc for addpcis, non-relative (gas internal use only).  */
-  HOW (R_PPC_16DX_HA, 2, 16, 0x1fffc1, 16, false, signed,
+  HOW (R_PPC_16DX_HA, 4, 16, 0x1fffc1, 16, false, signed,
        ppc_elf_addr16_ha_reloc),
 
   /* GNU extension to record C++ vtable hierarchy.  */
        ppc_elf_addr16_ha_reloc),
 
   /* GNU extension to record C++ vtable hierarchy.  */
@@ -689,7 +691,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
        NULL),
 
   /* Phony reloc to handle AIX style TOC entries.  */
        NULL),
 
   /* Phony reloc to handle AIX style TOC entries.  */
-  HOW (R_PPC_TOC16, 1, 16, 0xffff, 0, false, signed,
+  HOW (R_PPC_TOC16, 2, 16, 0xffff, 0, false, signed,
        ppc_elf_unhandled_reloc),
 };
 \f
        ppc_elf_unhandled_reloc),
 };
 \f
@@ -957,6 +959,10 @@ ppc_elf_addr16_ha_reloc (bfd *abfd,
   value >>= 16;
 
   octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section);
   value >>= 16;
 
   octets = reloc_entry->address * OCTETS_PER_BYTE (abfd, input_section);
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+                                 input_section, octets))
+    return bfd_reloc_outofrange;
+
   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
   insn &= ~0x1fffc1;
   insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
   insn &= ~0x1fffc1;
   insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
@@ -1338,10 +1344,10 @@ ppc_elf_section_from_shdr (bfd *abfd,
   if (hdr->sh_type == SHT_ORDERED)
     flags |= SEC_SORT_ENTRIES;
 
   if (hdr->sh_type == SHT_ORDERED)
     flags |= SEC_SORT_ENTRIES;
 
-  if (strncmp (name, ".PPC.EMB", 8) == 0)
+  if (startswith (name, ".PPC.EMB"))
     name += 8;
     name += 8;
-  if (strncmp (name, ".sbss", 5) == 0
-      || strncmp (name, ".sdata", 6) == 0)
+  if (startswith (name, ".sbss")
+      || startswith (name, ".sdata"))
     flags |= SEC_SMALL_DATA;
 
   return (flags == 0
     flags |= SEC_SMALL_DATA;
 
   return (flags == 0
@@ -2850,6 +2856,15 @@ is_plt_seq_reloc (enum elf_ppc_reloc_type r_type)
          || r_type == R_PPC_PLTSEQ);
 }
 
          || r_type == R_PPC_PLTSEQ);
 }
 
+/* Like bfd_reloc_offset_in_range but without a howto.  Return true
+   iff a field of SIZE bytes at OFFSET is within SEC limits.  */
+
+static bool
+offset_in_range (asection *sec, bfd_vma offset, size_t size)
+{
+  return offset <= sec->size && size <= sec->size - offset;
+}
+
 static void
 bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
 {
 static void
 bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
 {
@@ -2914,6 +2929,7 @@ ppc_elf_check_relocs (bfd *abfd,
       unsigned long r_symndx;
       enum elf_ppc_reloc_type r_type;
       struct elf_link_hash_entry *h;
       unsigned long r_symndx;
       enum elf_ppc_reloc_type r_type;
       struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *isym;
       int tls_type;
       struct plt_entry **ifunc;
       struct plt_entry **pltent;
       int tls_type;
       struct plt_entry **ifunc;
       struct plt_entry **pltent;
@@ -2921,13 +2937,19 @@ ppc_elf_check_relocs (bfd *abfd,
 
       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)
-       h = NULL;
+       {
+         h = NULL;
+         isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
+         if (isym == NULL)
+           return false;
+       }
       else
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
       else
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         isym = NULL;
        }
 
       /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
        }
 
       /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
@@ -2947,13 +2969,16 @@ ppc_elf_check_relocs (bfd *abfd,
       tls_type = 0;
       r_type = ELF32_R_TYPE (rel->r_info);
       ifunc = NULL;
       tls_type = 0;
       r_type = ELF32_R_TYPE (rel->r_info);
       ifunc = NULL;
-      if (h == NULL && htab->elf.target_os != is_vxworks)
+      if (h != NULL)
+       {
+         if (h->type == STT_GNU_IFUNC)
+           {
+             h->needs_plt = 1;
+             ifunc = &h->plt.plist;
+           }
+       }
+      else if (htab->elf.target_os != is_vxworks)
        {
        {
-         Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
-                                                         abfd, r_symndx);
-         if (isym == NULL)
-           return false;
-
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              /* Set PLT_IFUNC flag for this sym, no GOT entry yet.  */
          if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
            {
              /* Set PLT_IFUNC flag for this sym, no GOT entry yet.  */
@@ -3279,12 +3304,10 @@ ppc_elf_check_relocs (bfd *abfd,
              htab->plt_type = PLT_OLD;
              htab->old_bfd = abfd;
            }
              htab->plt_type = PLT_OLD;
              htab->old_bfd = abfd;
            }
-         if (h != NULL && h->type == STT_GNU_IFUNC)
-           {
-             h->needs_plt = 1;
-             if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
-               return false;
-           }
+         if (h != NULL
+             && ifunc != NULL
+             && !update_plt_info (abfd, ifunc, NULL, 0))
+           return false;
          break;
 
          /* This relocation describes the C++ object vtable hierarchy.
          break;
 
          /* This relocation describes the C++ object vtable hierarchy.
@@ -3332,12 +3355,6 @@ ppc_elf_check_relocs (bfd *abfd,
                 reliably deduce the GOT pointer value needed for
                 PLT call stubs.  */
              asection *s;
                 reliably deduce the GOT pointer value needed for
                 PLT call stubs.  */
              asection *s;
-             Elf_Internal_Sym *isym;
-
-             isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
-                                           abfd, r_symndx);
-             if (isym == NULL)
-               return false;
 
              s = bfd_section_from_elf_index (abfd, isym->st_shndx);
              if (s == got2)
 
              s = bfd_section_from_elf_index (abfd, isym->st_shndx);
              if (s == got2)
@@ -3406,38 +3423,21 @@ ppc_elf_check_relocs (bfd *abfd,
            }
 
        dodyn:
            }
 
        dodyn:
-         /* If we are creating a shared library, and this is a reloc
-            against a global symbol, or a non PC relative reloc
-            against a local symbol, then we need to copy the reloc
-            into the shared library.  However, if we are linking with
-            -Bsymbolic, we do not need to copy a reloc against a
-            global symbol which is defined in an object we are
-            including in the link (i.e., DEF_REGULAR is set).  At
-            this point we have not seen all the input files, so it is
-            possible that DEF_REGULAR is not set now but will be set
-            later (it is never cleared).  In case of a weak definition,
-            DEF_REGULAR may be cleared later by a strong definition in
-            a shared library.  We account for that possibility below by
-            storing information in the dyn_relocs field of the hash
-            table entry.  A similar situation occurs when creating
-            shared libraries and symbol visibility changes render the
-            symbol local.
-
-            If on the other hand, we are creating an executable, we
-            may need to keep relocations for symbols satisfied by a
-            dynamic library if we manage to avoid copy relocs for the
-            symbol.  */
-         if ((bfd_link_pic (info)
-              && (must_be_dyn_reloc (info, r_type)
-                  || (h != NULL
-                      && (!SYMBOLIC_BIND (info, h)
-                          || h->root.type == bfd_link_hash_defweak
-                          || !h->def_regular))))
-             || (ELIMINATE_COPY_RELOCS
-                 && !bfd_link_pic (info)
-                 && h != NULL
-                 && (h->root.type == bfd_link_hash_defweak
-                     || !h->def_regular)))
+         /* Set up information for symbols that might need dynamic
+            relocations.  At this point in linking we have read all
+            the input files and resolved most symbols, but have not
+            yet decided whether symbols are dynamic or finalized
+            symbol flags.  In some cases we might be setting dynamic
+            reloc info for symbols that do not end up needing such.
+            That's OK, adjust_dynamic_symbol and allocate_dynrelocs
+            work together with this code.  */
+         if ((h != NULL
+              && !SYMBOL_REFERENCES_LOCAL (info, h))
+             || (bfd_link_pic (info)
+                 && (h != NULL
+                     ? !bfd_is_abs_symbol (&h->root)
+                     : isym->st_shndx != SHN_ABS)
+                 && must_be_dyn_reloc (info, r_type)))
            {
 #ifdef DEBUG
              fprintf (stderr,
            {
 #ifdef DEBUG
              fprintf (stderr,
@@ -3492,12 +3492,6 @@ ppc_elf_check_relocs (bfd *abfd,
                  bool is_ifunc;
                  asection *s;
                  void *vpp;
                  bool is_ifunc;
                  asection *s;
                  void *vpp;
-                 Elf_Internal_Sym *isym;
-
-                 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
-                                               abfd, r_symndx);
-                 if (isym == NULL)
-                   return false;
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
                  if (s == NULL)
@@ -3505,7 +3499,7 @@ ppc_elf_check_relocs (bfd *abfd,
 
                  vpp = &elf_section_data (s)->local_dynrel;
                  rel_head = (struct ppc_dyn_relocs **) vpp;
 
                  vpp = &elf_section_data (s)->local_dynrel;
                  rel_head = (struct ppc_dyn_relocs **) vpp;
-                 is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
+                 is_ifunc = ifunc != NULL;
                  p = *rel_head;
                  if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
                    p = p->next;
                  p = *rel_head;
                  if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
                    p = p->next;
@@ -3878,7 +3872,7 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   return true;
 }
 
   return true;
 }
 
-static void
+static bfd_reloc_status_type
 ppc_elf_vle_split16 (bfd *input_bfd,
                     asection *input_section,
                     unsigned long offset,
 ppc_elf_vle_split16 (bfd *input_bfd,
                     asection *input_section,
                     unsigned long offset,
@@ -3889,6 +3883,8 @@ ppc_elf_vle_split16 (bfd *input_bfd,
 {
   unsigned int insn, opcode;
 
 {
   unsigned int insn, opcode;
 
+  if (!offset_in_range (input_section, offset, 4))
+    return bfd_reloc_outofrange;
   insn = bfd_get_32 (input_bfd, loc);
   opcode = insn & E_OPCODE_MASK;
   if (opcode == E_OR2I_INSN
   insn = bfd_get_32 (input_bfd, loc);
   opcode = insn & E_OPCODE_MASK;
   if (opcode == E_OR2I_INSN
@@ -3945,6 +3941,7 @@ ppc_elf_vle_split16 (bfd *input_bfd,
     }
   insn |= value & 0x7ff;
   bfd_put_32 (input_bfd, insn, loc);
     }
   insn |= value & 0x7ff;
   bfd_put_32 (input_bfd, insn, loc);
+  return bfd_reloc_ok;
 }
 
 static void
 }
 
 static void
@@ -4242,7 +4239,7 @@ ppc_elf_inline_plt (struct bfd_link_info *info)
              return false;
 
            relend = relstart + sec->reloc_count;
              return false;
 
            relend = relstart + sec->reloc_count;
-           for (rel = relstart; rel < relend; )
+           for (rel = relstart; rel < relend; rel++)
              {
                enum elf_ppc_reloc_type r_type;
                unsigned long r_symndx;
              {
                enum elf_ppc_reloc_type r_type;
                unsigned long r_symndx;
@@ -5152,7 +5149,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          if (((bfd_link_pic (info)
                && !((eh->tls_mask & TLS_TLS) != 0
                     && bfd_link_executable (info)
          if (((bfd_link_pic (info)
                && !((eh->tls_mask & TLS_TLS) != 0
                     && bfd_link_executable (info)
-                    && SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
+                    && SYMBOL_REFERENCES_LOCAL (info, &eh->elf))
+               && !bfd_is_abs_symbol (&h->root))
               || (htab->elf.dynamic_sections_created
                   && eh->elf.dynindx != -1
                   && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
               || (htab->elf.dynamic_sections_created
                   && eh->elf.dynindx != -1
                   && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
@@ -5245,7 +5243,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       /* For the non-pic case, discard space for relocs against
         symbols which turn out to need copy relocs or are not
         dynamic.  */
       /* For the non-pic case, discard space for relocs against
         symbols which turn out to need copy relocs or are not
         dynamic.  */
-      if (h->dynamic_adjusted
+      if ((h->dynamic_adjusted
+          || (h->ref_regular
+              && h->root.type == bfd_link_hash_undefweak
+              && (info->dynamic_undefined_weak > 0
+                  || !_bfd_elf_readonly_dynrelocs (h))))
          && !h->def_regular
          && !ELF_COMMON_DEF_P (h)
          && !(h->protected_def
          && !h->def_regular
          && !ELF_COMMON_DEF_P (h)
          && !(h->protected_def
@@ -5296,9 +5298,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       for (ent = h->plt.plist; ent != NULL; ent = ent->next)
        if (ent->plt.refcount > 0)
          {
       for (ent = h->plt.plist; ent != NULL; ent = ent->next)
        if (ent->plt.refcount > 0)
          {
-           asection *s = htab->elf.splt;
-           bool dyn = !use_local_plt (info, h);
+           asection *s;
+           bool dyn;
 
 
+           if (!ensure_undef_dynamic (info, h))
+             return false;
+
+           dyn = !use_local_plt (info, h);
+           s = htab->elf.splt;
            if (!dyn)
              {
                if (h->type == STT_GNU_IFUNC)
            if (!dyn)
              {
                if (h->type == STT_GNU_IFUNC)
@@ -5513,6 +5520,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
+      Elf_Internal_Sym *local_syms;
+      Elf_Internal_Sym *isym;
 
       if (!is_ppc_elf (ibfd))
        continue;
 
       if (!is_ppc_elf (ibfd))
        continue;
@@ -5569,8 +5578,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       local_plt = (struct plt_entry **) end_local_got;
       end_local_plt = local_plt + locsymcount;
       lgot_masks = (char *) end_local_plt;
       local_plt = (struct plt_entry **) end_local_got;
       end_local_plt = local_plt + locsymcount;
       lgot_masks = (char *) end_local_plt;
+      local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
+      if (local_syms == NULL && locsymcount != 0)
+       {
+         local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
+                                            0, NULL, NULL, NULL);
+         if (local_syms == NULL)
+           return false;
+       }
 
 
-      for (; local_got < end_local_got; ++local_got, ++lgot_masks)
+      for (isym = local_syms;
+          local_got < end_local_got;
+          ++local_got, ++lgot_masks, ++isym)
        if (*local_got > 0)
          {
            unsigned int need;
        if (*local_got > 0)
          {
            unsigned int need;
@@ -5584,7 +5603,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
                *local_got = allocate_got (htab, need);
                if (bfd_link_pic (info)
                    && !((*lgot_masks & TLS_TLS) != 0
                *local_got = allocate_got (htab, need);
                if (bfd_link_pic (info)
                    && !((*lgot_masks & TLS_TLS) != 0
-                        && bfd_link_executable (info)))
+                        && bfd_link_executable (info))
+                   && isym->st_shndx != SHN_ABS)
                  {
                    asection *srel;
 
                  {
                    asection *srel;
 
@@ -5657,6 +5677,15 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
            else
              ent->plt.offset = (bfd_vma) -1;
        }
            else
              ent->plt.offset = (bfd_vma) -1;
        }
+
+      if (local_syms != NULL
+         && symtab_hdr->contents != (unsigned char *) local_syms)
+       {
+         if (!info->keep_memory)
+           free (local_syms);
+         else
+           symtab_hdr->contents = (unsigned char *) local_syms;
+       }
     }
 
   /* Allocate space for global sym dynamic relocs.  */
     }
 
   /* Allocate space for global sym dynamic relocs.  */
@@ -7117,7 +7146,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_GOT_TPREL16:
        case R_PPC_GOT_TPREL16_LO:
          if ((tls_mask & TLS_TLS) != 0
        case R_PPC_GOT_TPREL16:
        case R_PPC_GOT_TPREL16_LO:
          if ((tls_mask & TLS_TLS) != 0
-             && (tls_mask & TLS_TPREL) == 0)
+             && (tls_mask & TLS_TPREL) == 0
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            {
              bfd_vma insn;
 
            {
              bfd_vma insn;
 
@@ -7134,7 +7164,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_TLS:
          if ((tls_mask & TLS_TLS) != 0
 
        case R_PPC_TLS:
          if ((tls_mask & TLS_TLS) != 0
-             && (tls_mask & TLS_TPREL) == 0)
+             && (tls_mask & TLS_TPREL) == 0
+             && offset_in_range (input_section, rel->r_offset, 4))
            {
              bfd_vma insn;
 
            {
              bfd_vma insn;
 
@@ -7155,13 +7186,15 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_GOT_TLSGD16_HI:
        case R_PPC_GOT_TLSGD16_HA:
          tls_gd = TLS_GDIE;
        case R_PPC_GOT_TLSGD16_HI:
        case R_PPC_GOT_TLSGD16_HA:
          tls_gd = TLS_GDIE;
-         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            goto tls_gdld_hi;
          break;
 
        case R_PPC_GOT_TLSLD16_HI:
        case R_PPC_GOT_TLSLD16_HA:
            goto tls_gdld_hi;
          break;
 
        case R_PPC_GOT_TLSLD16_HI:
        case R_PPC_GOT_TLSLD16_HA:
-         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            {
            tls_gdld_hi:
              if ((tls_mask & tls_gd) != 0)
            {
            tls_gdld_hi:
              if ((tls_mask & tls_gd) != 0)
@@ -7180,13 +7213,15 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_GOT_TLSGD16:
        case R_PPC_GOT_TLSGD16_LO:
          tls_gd = TLS_GDIE;
        case R_PPC_GOT_TLSGD16:
        case R_PPC_GOT_TLSGD16_LO:
          tls_gd = TLS_GDIE;
-         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            goto tls_ldgd_opt;
          break;
 
        case R_PPC_GOT_TLSLD16:
        case R_PPC_GOT_TLSLD16_LO:
            goto tls_ldgd_opt;
          break;
 
        case R_PPC_GOT_TLSLD16:
        case R_PPC_GOT_TLSLD16_LO:
-         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0)
+         if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            {
              unsigned int insn1, insn2;
              bfd_vma offset;
            {
              unsigned int insn1, insn2;
              bfd_vma offset;
@@ -7214,7 +7249,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  /* IE */
                  insn1 &= (0x1f << 21) | (0x1f << 16);
                  insn1 |= 32u << 26;   /* lwz */
                  /* IE */
                  insn1 &= (0x1f << 21) | (0x1f << 16);
                  insn1 |= 32u << 26;   /* lwz */
-                 if (offset != (bfd_vma) -1)
+                 if (offset != (bfd_vma) -1
+                     && offset_in_range (input_section, offset, 4))
                    {
                      rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
                      insn2 = 0x7c631214;       /* add 3,3,2 */
                    {
                      rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
                      insn2 = 0x7c631214;       /* add 3,3,2 */
@@ -7247,7 +7283,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                    }
                  r_type = R_PPC_TPREL16_HA;
                  rel->r_info = ELF32_R_INFO (r_symndx, r_type);
                    }
                  r_type = R_PPC_TPREL16_HA;
                  rel->r_info = ELF32_R_INFO (r_symndx, r_type);
-                 if (offset != (bfd_vma) -1)
+                 if (offset != (bfd_vma) -1
+                     && offset_in_range (input_section, offset, 4))
                    {
                      rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
                      rel[1].r_offset = offset + d_offset;
                    {
                      rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
                      rel[1].r_offset = offset + d_offset;
@@ -7269,7 +7306,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_TLSGD:
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
 
        case R_PPC_TLSGD:
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0
-             && rel + 1 < relend)
+             && rel + 1 < relend
+             && offset_in_range (input_section, rel->r_offset, 4))
            {
              unsigned int insn2;
              bfd_vma offset = rel->r_offset;
            {
              unsigned int insn2;
              bfd_vma offset = rel->r_offset;
@@ -7304,7 +7342,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_TLSLD:
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
 
        case R_PPC_TLSLD:
          if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0
-             && rel + 1 < relend)
+             && rel + 1 < relend
+             && offset_in_range (input_section, rel->r_offset, 4))
            {
              unsigned int insn2;
 
            {
              unsigned int insn2;
 
@@ -7357,48 +7396,50 @@ ppc_elf_relocate_section (bfd *output_bfd,
          /* Branch not taken prediction relocations.  */
        case R_PPC_ADDR14_BRNTAKEN:
        case R_PPC_REL14_BRNTAKEN:
          /* Branch not taken prediction relocations.  */
        case R_PPC_ADDR14_BRNTAKEN:
        case R_PPC_REL14_BRNTAKEN:
-         {
-           unsigned int insn;
+         if (offset_in_range (input_section, rel->r_offset, 4))
+           {
+             unsigned int insn;
 
 
-           insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
-           insn &= ~BRANCH_PREDICT_BIT;
-           insn |= branch_bit;
+             insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+             insn &= ~BRANCH_PREDICT_BIT;
+             insn |= branch_bit;
 
 
-           from = (rel->r_offset
-                   + input_section->output_offset
-                   + input_section->output_section->vma);
+             from = (rel->r_offset
+                     + input_section->output_offset
+                     + input_section->output_section->vma);
 
 
-           /* Invert 'y' bit if not the default.  */
-           if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
-             insn ^= BRANCH_PREDICT_BIT;
+             /* Invert 'y' bit if not the default.  */
+             if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
+               insn ^= BRANCH_PREDICT_BIT;
 
 
-           bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
-         }
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+           }
          break;
 
        case R_PPC_PLT16_HA:
          break;
 
        case R_PPC_PLT16_HA:
-         {
-           unsigned int insn;
+         if (offset_in_range (input_section, rel->r_offset - d_offset, 4))
+           {
+             unsigned int insn;
 
 
-           insn = bfd_get_32 (input_bfd,
-                              contents + rel->r_offset - d_offset);
-           if ((insn & (0x3fu << 26)) == 15u << 26
-               && (insn & (0x1f << 16)) != 0)
-             {
-               if (!bfd_link_pic (info))
-                 {
-                   /* Convert addis to lis.  */
-                   insn &= ~(0x1f << 16);
-                   bfd_put_32 (input_bfd, insn,
-                               contents + rel->r_offset - d_offset);
-                 }
-             }
-           else if (bfd_link_pic (info))
-             info->callbacks->einfo
-               (_("%P: %H: error: %s with unexpected instruction %x\n"),
-                input_bfd, input_section, rel->r_offset,
-                "R_PPC_PLT16_HA", insn);
-         }
+             insn = bfd_get_32 (input_bfd,
+                                contents + rel->r_offset - d_offset);
+             if ((insn & (0x3fu << 26)) == 15u << 26
+                 && (insn & (0x1f << 16)) != 0)
+               {
+                 if (!bfd_link_pic (info))
+                   {
+                     /* Convert addis to lis.  */
+                     insn &= ~(0x1f << 16);
+                     bfd_put_32 (input_bfd, insn,
+                                 contents + rel->r_offset - d_offset);
+                   }
+               }
+             else if (bfd_link_pic (info))
+               info->callbacks->einfo
+                 (_("%P: %H: error: %s with unexpected instruction %x\n"),
+                  input_bfd, input_section, rel->r_offset,
+                  "R_PPC_PLT16_HA", insn);
+           }
          break;
        }
 
          break;
        }
 
@@ -7414,7 +7455,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
             variable defined in a shared library to PIC.  */
          unsigned int insn;
 
             variable defined in a shared library to PIC.  */
          unsigned int insn;
 
-         if (r_type == R_PPC_ADDR16_HA)
+         if (r_type == R_PPC_ADDR16_HA
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            {
              insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
            {
              insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
@@ -7477,7 +7519,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   input_bfd, input_section, (uint64_t) rel->r_offset,
                   "R_PPC_ADDR16_HA", insn);
            }
                   input_bfd, input_section, (uint64_t) rel->r_offset,
                   "R_PPC_ADDR16_HA", insn);
            }
-         else if (r_type == R_PPC_ADDR16_LO)
+         else if (r_type == R_PPC_ADDR16_LO
+                  && offset_in_range (input_section,
+                                      rel->r_offset - d_offset, 4))
            {
              insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
            {
              insn = bfd_get_32 (input_bfd,
                                 contents + rel->r_offset - d_offset);
@@ -7601,9 +7645,15 @@ ppc_elf_relocate_section (bfd *output_bfd,
       switch (r_type)
        {
        default:
       switch (r_type)
        {
        default:
-         /* xgettext:c-format */
-         _bfd_error_handler (_("%pB: %s unsupported"),
-                             input_bfd, howto->name);
+       de_fault:
+         if (howto)
+           /* xgettext:c-format */
+           _bfd_error_handler (_("%pB: %s unsupported"),
+                               input_bfd, howto->name);
+         else
+           /* xgettext:c-format */
+           _bfd_error_handler (_("%pB: reloc %#x unsupported"),
+                               input_bfd, r_type);
 
          bfd_set_error (bfd_error_bad_value);
          ret = false;
 
          bfd_set_error (bfd_error_bad_value);
          ret = false;
@@ -7748,7 +7798,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
                                || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
                            && !(tls_ty != 0
                                 && bfd_link_executable (info)
                                || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
                            && !(tls_ty != 0
                                 && bfd_link_executable (info)
-                                && SYMBOL_REFERENCES_LOCAL (info, h))))
+                                && SYMBOL_REFERENCES_LOCAL (info, h))
+                           && (h != NULL
+                               ? !bfd_is_abs_symbol (&h->root)
+                               : sym->st_shndx != SHN_ABS)))
                      {
                        asection *rsec = htab->elf.srelgot;
                        bfd_byte * loc;
                      {
                        asection *rsec = htab->elf.srelgot;
                        bfd_byte * loc;
@@ -7941,7 +7994,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_TPREL16_HA:
          if (h != NULL
              && h->root.type == bfd_link_hash_undefweak
        case R_PPC_TPREL16_HA:
          if (h != NULL
              && h->root.type == bfd_link_hash_undefweak
-             && h->dynindx == -1)
+             && h->dynindx == -1
+             && offset_in_range (input_section, rel->r_offset - d_offset, 4))
            {
              /* Make this relocation against an undefined weak symbol
                 resolve to zero.  This is really just a tweak, since
            {
              /* Make this relocation against an undefined weak symbol
                 resolve to zero.  This is really just a tweak, since
@@ -8209,66 +8263,73 @@ ppc_elf_relocate_section (bfd *output_bfd,
          /* Fall through.  */
 
        case R_PPC_RELAX:
          /* Fall through.  */
 
        case R_PPC_RELAX:
-         {
-           const int *stub;
-           size_t size;
-           size_t insn_offset = rel->r_offset;
-           unsigned int insn;
-
-           if (bfd_link_pic (info))
-             {
-               relocation -= (input_section->output_section->vma
-                              + input_section->output_offset
-                              + rel->r_offset - 4);
-               stub = shared_stub_entry;
-               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;
-             }
-           else
-             {
-               stub = stub_entry;
-               size = ARRAY_SIZE (stub_entry);
-             }
-
-           relocation += addend;
-           if (bfd_link_relocatable (info))
-             relocation = 0;
-
-           /* First insn is HA, second is LO.  */
-           insn = *stub++;
-           insn |= ((relocation + 0x8000) >> 16) & 0xffff;
-           bfd_put_32 (input_bfd, insn, contents + insn_offset);
-           insn_offset += 4;
+         if (bfd_link_pic (info)
+             ? offset_in_range (input_section, rel->r_offset - 12,
+                                ARRAY_SIZE (shared_stub_entry) * 4)
+             : offset_in_range (input_section, rel->r_offset,
+                                ARRAY_SIZE (stub_entry) * 4))
+           {
+             const int *stub;
+             size_t size;
+             size_t insn_offset = rel->r_offset;
+             unsigned int insn;
 
 
-           insn = *stub++;
-           insn |= relocation & 0xffff;
-           bfd_put_32 (input_bfd, insn, contents + insn_offset);
-           insn_offset += 4;
-           size -= 2;
+             if (bfd_link_pic (info))
+               {
+                 relocation -= (input_section->output_section->vma
+                                + input_section->output_offset
+                                + rel->r_offset - 4);
+                 stub = shared_stub_entry;
+                 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;
+               }
+             else
+               {
+                 stub = stub_entry;
+                 size = ARRAY_SIZE (stub_entry);
+               }
 
 
-           while (size != 0)
-             {
-               insn = *stub++;
-               --size;
-               bfd_put_32 (input_bfd, insn, contents + insn_offset);
-               insn_offset += 4;
-             }
+             relocation += addend;
+             if (bfd_link_relocatable (info))
+               relocation = 0;
+
+             /* First insn is HA, second is LO.  */
+             insn = *stub++;
+             insn |= ((relocation + 0x8000) >> 16) & 0xffff;
+             bfd_put_32 (input_bfd, insn, contents + insn_offset);
+             insn_offset += 4;
+
+             insn = *stub++;
+             insn |= relocation & 0xffff;
+             bfd_put_32 (input_bfd, insn, contents + insn_offset);
+             insn_offset += 4;
+             size -= 2;
+
+             while (size != 0)
+               {
+                 insn = *stub++;
+                 --size;
+                 bfd_put_32 (input_bfd, insn, contents + insn_offset);
+                 insn_offset += 4;
+               }
 
 
-           /* Rewrite the reloc and convert one of the trailing nop
-              relocs to describe this relocation.  */
-           BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE);
-           /* The relocs are at the bottom 2 bytes */
-           wrel->r_offset = rel->r_offset + d_offset;
-           wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
-           wrel->r_addend = rel->r_addend;
-           memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel));
-           wrel++, rel++;
-           wrel->r_offset += 4;
-           wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
-         }
+             /* Rewrite the reloc and convert one of the trailing nop
+                relocs to describe this relocation.  */
+             BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE);
+             /* The relocs are at the bottom 2 bytes */
+             wrel->r_offset = rel->r_offset + d_offset;
+             wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
+             wrel->r_addend = rel->r_addend;
+             memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel));
+             wrel++, rel++;
+             wrel->r_offset += 4;
+             wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
+           }
+         else
+           goto de_fault;
          continue;
 
          /* Indirect .sdata relocation.  */
          continue;
 
          /* Indirect .sdata relocation.  */
@@ -8472,151 +8533,164 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_VLE_LO16A:
          relocation = relocation + addend;
 
        case R_PPC_VLE_LO16A:
          relocation = relocation + addend;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16a_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
        case R_PPC_VLE_LO16D:
          relocation = relocation + addend;
 
        case R_PPC_VLE_LO16D:
          relocation = relocation + addend;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16d_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
        case R_PPC_VLE_HI16A:
          relocation = (relocation + addend) >> 16;
 
        case R_PPC_VLE_HI16A:
          relocation = (relocation + addend) >> 16;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16a_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
        case R_PPC_VLE_HI16D:
          relocation = (relocation + addend) >> 16;
 
        case R_PPC_VLE_HI16D:
          relocation = (relocation + addend) >> 16;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16d_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
        case R_PPC_VLE_HA16A:
          relocation = (relocation + addend + 0x8000) >> 16;
 
        case R_PPC_VLE_HA16A:
          relocation = (relocation + addend + 0x8000) >> 16;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16a_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
        case R_PPC_VLE_HA16D:
          relocation = (relocation + addend + 0x8000) >> 16;
 
        case R_PPC_VLE_HA16D:
          relocation = (relocation + addend + 0x8000) >> 16;
-         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;
+         r = ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+                                  contents + rel->r_offset, relocation,
+                                  split16d_type,
+                                  htab->params->vle_reloc_fixup);
+         goto report_reloc;
 
          /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0.  */
        case R_PPC_EMB_SDA21:
        case R_PPC_VLE_SDA21:
        case R_PPC_EMB_RELSDA:
        case R_PPC_VLE_SDA21_LO:
 
          /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0.  */
        case R_PPC_EMB_SDA21:
        case R_PPC_VLE_SDA21:
        case R_PPC_EMB_RELSDA:
        case R_PPC_VLE_SDA21_LO:
-         {
-           const char *name;
-           int reg;
-           unsigned int insn;
-           struct elf_link_hash_entry *sda = NULL;
+         if (!offset_in_range (input_section, rel->r_offset, 4))
+           {
+             r = bfd_reloc_outofrange;
+             goto report_reloc;
+           }
+         else
+           {
+             const char *name;
+             int reg;
+             unsigned int insn;
+             struct elf_link_hash_entry *sda = NULL;
 
 
-           if (sec == NULL || sec->output_section == NULL)
-             {
-               unresolved_reloc = true;
-               break;
-             }
+             if (sec == NULL || sec->output_section == NULL)
+               {
+                 unresolved_reloc = true;
+                 break;
+               }
 
 
-           name = bfd_section_name (sec->output_section);
-           if (strcmp (name, ".sdata") == 0
-               || strcmp (name, ".sbss") == 0)
-             {
-               reg = 13;
-               sda = htab->sdata[0].sym;
-             }
-           else if (strcmp (name, ".sdata2") == 0
-                    || strcmp (name, ".sbss2") == 0)
-             {
-               reg = 2;
-               sda = htab->sdata[1].sym;
-             }
-           else if (strcmp (name, ".PPC.EMB.sdata0") == 0
-                    || strcmp (name, ".PPC.EMB.sbss0") == 0)
-             {
-               reg = 0;
-             }
-           else
-             {
-               _bfd_error_handler
-                 /* xgettext:c-format */
-                 (_("%pB: the target (%s) of a %s relocation is "
-                    "in the wrong output section (%s)"),
-                  input_bfd,
-                  sym_name,
-                  howto->name,
-                  name);
+             name = bfd_section_name (sec->output_section);
+             if (strcmp (name, ".sdata") == 0
+                 || strcmp (name, ".sbss") == 0)
+               {
+                 reg = 13;
+                 sda = htab->sdata[0].sym;
+               }
+             else if (strcmp (name, ".sdata2") == 0
+                      || strcmp (name, ".sbss2") == 0)
+               {
+                 reg = 2;
+                 sda = htab->sdata[1].sym;
+               }
+             else if (strcmp (name, ".PPC.EMB.sdata0") == 0
+                      || strcmp (name, ".PPC.EMB.sbss0") == 0)
+               {
+                 reg = 0;
+               }
+             else
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB: the target (%s) of a %s relocation is "
+                      "in the wrong output section (%s)"),
+                    input_bfd,
+                    sym_name,
+                    howto->name,
+                    name);
+
+                 bfd_set_error (bfd_error_bad_value);
+                 ret = false;
+                 goto copy_reloc;
+               }
 
 
-               bfd_set_error (bfd_error_bad_value);
-               ret = false;
-               goto copy_reloc;
-             }
+             if (sda != NULL)
+               {
+                 if (!is_static_defined (sda))
+                   {
+                     unresolved_reloc = true;
+                     break;
+                   }
+                 addend -= SYM_VAL (sda);
+               }
 
 
-           if (sda != NULL)
-             {
-               if (!is_static_defined (sda))
-                 {
-                   unresolved_reloc = true;
-                   break;
-                 }
-               addend -= SYM_VAL (sda);
-             }
+             if (r_type == R_PPC_EMB_RELSDA)
+               break;
 
 
-           if (r_type == R_PPC_EMB_RELSDA)
-             break;
+             /* The PowerPC Embedded Application Binary Interface
+                version 1.0 insanely chose to specify R_PPC_EMB_SDA21
+                operating on a 24-bit field at r_offset.  GNU as and
+                GNU ld have always assumed R_PPC_EMB_SDA21 operates on
+                a 32-bit bit insn at r_offset.  Cope with object file
+                producers that possibly comply with the EABI in
+                generating an odd r_offset for big-endian objects.  */
+             if (r_type == R_PPC_EMB_SDA21)
+               rel->r_offset &= ~1;
 
 
-           /* The PowerPC Embedded Application Binary Interface
-              version 1.0 insanely chose to specify R_PPC_EMB_SDA21
-              operating on a 24-bit field at r_offset.  GNU as and
-              GNU ld have always assumed R_PPC_EMB_SDA21 operates on
-              a 32-bit bit insn at r_offset.  Cope with object file
-              producers that possibly comply with the EABI in
-              generating an odd r_offset for big-endian objects.  */
-           if (r_type == R_PPC_EMB_SDA21)
-             rel->r_offset &= ~1;
-
-           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))
-             {
-               relocation = relocation + addend;
-               addend = 0;
-
-               /* Force e_li insn, keeping RT from original insn.  */
-               insn &= 0x1f << 21;
-               insn |= 28u << 26;
-
-               /* We have an li20 field, bits 17..20, 11..15, 21..31.  */
-               /* Top 4 bits of value to 17..20.  */
-               insn |= (relocation & 0xf0000) >> 5;
-               /* Next 5 bits of the value to 11..15.  */
-               insn |= (relocation & 0xf800) << 5;
-               /* And the final 11 bits of the value to bits 21 to 31.  */
-               insn |= relocation & 0x7ff;
-
-               bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
-
-               if (r_type == R_PPC_VLE_SDA21
-                   && ((relocation + 0x80000) & 0xffffffff) > 0x100000)
-                 goto overflow;
-               goto copy_reloc;
-             }
-           /* Fill in register field.  */
-           insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
-           bfd_put_32 (input_bfd, insn, 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))
+               {
+                 relocation = relocation + addend;
+                 addend = 0;
+
+                 /* Force e_li insn, keeping RT from original insn.  */
+                 insn &= 0x1f << 21;
+                 insn |= 28u << 26;
+
+                 /* We have an li20 field, bits 17..20, 11..15, 21..31.  */
+                 /* Top 4 bits of value to 17..20.  */
+                 insn |= (relocation & 0xf0000) >> 5;
+                 /* Next 5 bits of the value to 11..15.  */
+                 insn |= (relocation & 0xf800) << 5;
+                 /* And the final 11 bits of the value to bits 21 to 31.  */
+                 insn |= relocation & 0x7ff;
+
+                 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+                 r = bfd_reloc_ok;
+                 if (r_type == R_PPC_VLE_SDA21
+                     && ((relocation + 0x80000) & 0xffffffff) > 0x100000)
+                   r = bfd_reloc_overflow;
+                 goto report_reloc;
+               }
+             /* Fill in register field.  */
+             insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
+             bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+           }
          break;
 
        case R_PPC_VLE_SDAREL_LO16A:
          break;
 
        case R_PPC_VLE_SDAREL_LO16A:
@@ -8625,95 +8699,113 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_VLE_SDAREL_HI16D:
        case R_PPC_VLE_SDAREL_HA16A:
        case R_PPC_VLE_SDAREL_HA16D:
        case R_PPC_VLE_SDAREL_HI16D:
        case R_PPC_VLE_SDAREL_HA16A:
        case R_PPC_VLE_SDAREL_HA16D:
-         {
-           bfd_vma value;
-           const char *name;
-           struct elf_link_hash_entry *sda = NULL;
-
-           if (sec == NULL || sec->output_section == NULL)
-             {
-               unresolved_reloc = true;
-               break;
-             }
-
-           name = bfd_section_name (sec->output_section);
-           if (strcmp (name, ".sdata") == 0
-               || strcmp (name, ".sbss") == 0)
-             sda = htab->sdata[0].sym;
-           else if (strcmp (name, ".sdata2") == 0
-                    || strcmp (name, ".sbss2") == 0)
-             sda = htab->sdata[1].sym;
-           else
-             {
-               _bfd_error_handler
-                 /* xgettext:c-format */
-                 (_("%pB: the target (%s) of a %s relocation is "
-                    "in the wrong output section (%s)"),
-                  input_bfd,
-                  sym_name,
-                  howto->name,
-                  name);
+         if (!offset_in_range (input_section, rel->r_offset, 4))
+           r = bfd_reloc_outofrange;
+         else
+           {
+             bfd_vma value;
+             const char *name;
+             struct elf_link_hash_entry *sda = NULL;
 
 
-               bfd_set_error (bfd_error_bad_value);
-               ret = false;
-               goto copy_reloc;
-             }
+             if (sec == NULL || sec->output_section == NULL)
+               {
+                 unresolved_reloc = true;
+                 break;
+               }
 
 
-           if (sda == NULL || !is_static_defined (sda))
-             {
-               unresolved_reloc = true;
-               break;
-             }
-           value = relocation + addend - SYM_VAL (sda);
+             name = bfd_section_name (sec->output_section);
+             if (strcmp (name, ".sdata") == 0
+                 || strcmp (name, ".sbss") == 0)
+               sda = htab->sdata[0].sym;
+             else if (strcmp (name, ".sdata2") == 0
+                      || strcmp (name, ".sbss2") == 0)
+               sda = htab->sdata[1].sym;
+             else
+               {
+                 _bfd_error_handler
+                   /* xgettext:c-format */
+                   (_("%pB: the target (%s) of a %s relocation is "
+                      "in the wrong output section (%s)"),
+                    input_bfd,
+                    sym_name,
+                    howto->name,
+                    name);
+
+                 bfd_set_error (bfd_error_bad_value);
+                 ret = false;
+                 goto copy_reloc;
+               }
 
 
-           if (r_type == R_PPC_VLE_SDAREL_LO16A)
-             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 (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 (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 (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 (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 (input_bfd, input_section, rel->r_offset,
-                                    contents + rel->r_offset, value,
-                                    split16d_type,
-                                    htab->params->vle_reloc_fixup);
-             }
-         }
-         goto copy_reloc;
+             if (sda == NULL || !is_static_defined (sda))
+               {
+                 unresolved_reloc = true;
+                 break;
+               }
+             value = relocation + addend - SYM_VAL (sda);
+
+             if (r_type == R_PPC_VLE_SDAREL_LO16A)
+               r = 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)
+               r = 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;
+                 r = 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;
+                 r = 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;
+                 r = 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;
+                 r = ppc_elf_vle_split16 (input_bfd, input_section,
+                                          rel->r_offset,
+                                          contents + rel->r_offset, value,
+                                          split16d_type,
+                                          htab->params->vle_reloc_fixup);
+               }
+             else
+               abort ();
+           }
+         goto report_reloc;
 
        case R_PPC_VLE_ADDR20:
 
        case R_PPC_VLE_ADDR20:
-         ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation);
-         goto copy_reloc;
+         if (!offset_in_range (input_section, rel->r_offset, 4))
+           r = bfd_reloc_outofrange;
+         else
+           {
+             ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset,
+                                  relocation);
+             r = bfd_reloc_ok;
+           }
+         goto report_reloc;
 
          /* Relocate against the beginning of the section.  */
        case R_PPC_SECTOFF:
 
          /* Relocate against the beginning of the section.  */
        case R_PPC_SECTOFF:
@@ -8765,7 +8857,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC_TPREL16_HA:
          break;
 
        case R_PPC_TPREL16_HA:
-         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+         if (htab->do_tls_opt
+             && relocation + addend + 0x8000 < 0x10000
+             && offset_in_range (input_section, rel->r_offset & ~3, 4))
+
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              bfd_put_32 (input_bfd, NOP, p);
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              bfd_put_32 (input_bfd, NOP, p);
@@ -8773,7 +8868,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
          break;
 
        case R_PPC_TPREL16_LO:
          break;
 
        case R_PPC_TPREL16_LO:
-         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+         if (htab->do_tls_opt
+             && relocation + addend + 0x8000 < 0x10000
+             && offset_in_range (input_section, rel->r_offset & ~3, 4))
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              unsigned int insn = bfd_get_32 (input_bfd, p);
            {
              bfd_byte *p = contents + (rel->r_offset & ~3);
              unsigned int insn = bfd_get_32 (input_bfd, p);
@@ -8792,13 +8889,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_PLTCALL:
          if (unresolved_reloc)
            {
        case R_PPC_PLTCALL:
          if (unresolved_reloc)
            {
-             bfd_byte *p = contents + rel->r_offset;
-             unsigned int insn = bfd_get_32 (input_bfd, p);
-             insn &= 1;
-             bfd_put_32 (input_bfd, B | insn, p);
-             unresolved_reloc = save_unresolved_reloc;
-             r_type = R_PPC_REL24;
-             howto = ppc_elf_howto_table[r_type];
+             if (offset_in_range (input_section, rel->r_offset, 4))
+               {
+                 bfd_byte *p = contents + rel->r_offset;
+                 unsigned int insn = bfd_get_32 (input_bfd, p);
+                 insn &= 1;
+                 bfd_put_32 (input_bfd, B | insn, p);
+                 unresolved_reloc = save_unresolved_reloc;
+                 r_type = R_PPC_REL24;
+                 howto = ppc_elf_howto_table[r_type];
+               }
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
@@ -8812,11 +8912,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_PLT16_LO:
          if (unresolved_reloc)
            {
        case R_PPC_PLT16_LO:
          if (unresolved_reloc)
            {
-             bfd_byte *p = contents + (rel->r_offset & ~3);
-             bfd_put_32 (input_bfd, NOP, p);
-             unresolved_reloc = false;
-             r_type = R_PPC_NONE;
-             howto = ppc_elf_howto_table[r_type];
+             if (offset_in_range (input_section, rel->r_offset & ~3, 4))
+               {
+                 bfd_byte *p = contents + (rel->r_offset & ~3);
+                 bfd_put_32 (input_bfd, NOP, p);
+                 unresolved_reloc = false;
+                 r_type = R_PPC_NONE;
+                 howto = ppc_elf_howto_table[r_type];
+               }
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
            }
          else if (htab->plt_type != PLT_NEW)
            info->callbacks->einfo
@@ -8878,36 +8981,37 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_GOT_DTPREL16_LO:
        case R_PPC_GOT_TPREL16:
        case R_PPC_GOT_TPREL16_LO:
        case R_PPC_GOT_DTPREL16_LO:
        case R_PPC_GOT_TPREL16:
        case R_PPC_GOT_TPREL16_LO:
-         {
-           /* The 32-bit ABI lacks proper relocations to deal with
-              certain 64-bit instructions.  Prevent damage to bits
-              that make up part of the insn opcode.  */
-           unsigned int insn, mask, lobit;
-
-           insn = bfd_get_32 (input_bfd,
-                              contents + rel->r_offset - d_offset);
-           mask = 0;
-           if (is_insn_ds_form (insn))
-             mask = 3;
-           else if (is_insn_dq_form (insn))
-             mask = 15;
-           else
-             break;
-           relocation += addend;
-           addend = insn & mask;
-           lobit = mask & relocation;
-           if (lobit != 0)
-             {
-               relocation ^= lobit;
-               info->callbacks->einfo
-                 /* xgettext:c-format */
-                 (_("%H: error: %s against `%s' not a multiple of %u\n"),
-                  input_bfd, input_section, rel->r_offset,
-                  howto->name, sym_name, mask + 1);
-               bfd_set_error (bfd_error_bad_value);
-               ret = false;
-             }
-         }
+         if (offset_in_range (input_section, rel->r_offset - d_offset, 4))
+           {
+             /* The 32-bit ABI lacks proper relocations to deal with
+                certain 64-bit instructions.  Prevent damage to bits
+                that make up part of the insn opcode.  */
+             unsigned int insn, mask, lobit;
+
+             insn = bfd_get_32 (input_bfd,
+                                contents + rel->r_offset - d_offset);
+             mask = 0;
+             if (is_insn_ds_form (insn))
+               mask = 3;
+             else if (is_insn_dq_form (insn))
+               mask = 15;
+             else
+               break;
+             relocation += addend;
+             addend = insn & mask;
+             lobit = mask & relocation;
+             if (lobit != 0)
+               {
+                 relocation ^= lobit;
+                 info->callbacks->einfo
+                   /* xgettext:c-format */
+                   (_("%H: error: %s against `%s' not a multiple of %u\n"),
+                    input_bfd, input_section, rel->r_offset,
+                    howto->name, sym_name, mask + 1);
+                 bfd_set_error (bfd_error_bad_value);
+                 ret = false;
+               }
+           }
          break;
        }
 
          break;
        }
 
@@ -8942,7 +9046,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
         have different reloc types.  */
       if (howto->complain_on_overflow != complain_overflow_dont
          && howto->dst_mask == 0xffff
         have different reloc types.  */
       if (howto->complain_on_overflow != complain_overflow_dont
          && howto->dst_mask == 0xffff
-         && (input_section->flags & SEC_CODE) != 0)
+         && (input_section->flags & SEC_CODE) != 0
+         && offset_in_range (input_section, rel->r_offset & ~3, 4))
        {
          enum complain_overflow complain = complain_overflow_signed;
 
        {
          enum complain_overflow complain = complain_overflow_signed;
 
@@ -8969,7 +9074,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
       if (r_type == R_PPC_REL16DX_HA)
        {
          /* Split field reloc isn't handled by _bfd_final_link_relocate.  */
       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)
+         if (offset_in_range (input_section, rel->r_offset, 4))
            r = bfd_reloc_outofrange;
          else
            {
            r = bfd_reloc_outofrange;
          else
            {
@@ -8991,11 +9096,11 @@ ppc_elf_relocate_section (bfd *output_bfd,
        r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
                                      rel->r_offset, relocation, addend);
 
        r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
                                      rel->r_offset, relocation, addend);
 
+    report_reloc:
       if (r != bfd_reloc_ok)
        {
          if (r == bfd_reloc_overflow)
            {
       if (r != bfd_reloc_ok)
        {
          if (r == bfd_reloc_overflow)
            {
-           overflow:
              /* On code like "if (foo) foo();" don't report overflow
                 on a branch to zero when foo is undefined.  */
              if (!warned
              /* On code like "if (foo) foo();" don't report overflow
                 on a branch to zero when foo is undefined.  */
              if (!warned
@@ -10273,7 +10378,6 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define ELF_MACHINE_CODE       EM_PPC
 #define ELF_MAXPAGESIZE                0x10000
 #define ELF_COMMONPAGESIZE     0x1000
 #define ELF_MACHINE_CODE       EM_PPC
 #define ELF_MAXPAGESIZE                0x10000
 #define ELF_COMMONPAGESIZE     0x1000
-#define ELF_RELROPAGESIZE      ELF_MAXPAGESIZE
 #define elf_info_to_howto      ppc_elf_info_to_howto
 
 #ifdef  EM_CYGNUS_POWERPC
 #define elf_info_to_howto      ppc_elf_info_to_howto
 
 #ifdef  EM_CYGNUS_POWERPC