bfd:
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index 257f7a5e6eeda14e634bdc89369218a0f70518a2..fefc7db0c1e7e6c90c3788a9550df4e9b2e33c74 100644 (file)
@@ -1,6 +1,6 @@
 /* 32-bit ELF support for ARM
    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009, 2010, 2011  Free Software Foundation, Inc.
+   2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #include <limits.h>
 
 #include "bfd.h"
+#include "bfd_stdint.h"
 #include "libiberty.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
+#include "elf-nacl.h"
 #include "elf-vxworks.h"
 #include "elf/arm.h"
 
@@ -1966,6 +1968,8 @@ elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
        return FALSE;
 
       case 124:                /* Linux/ARM elf_prpsinfo.  */
+       elf_tdata (abfd)->core_pid
+        = bfd_get_32 (abfd, note->descdata + 12);
        elf_tdata (abfd)->core_program
         = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
        elf_tdata (abfd)->core_command
@@ -1986,6 +1990,54 @@ elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
   return TRUE;
 }
 
+static char *
+elf32_arm_nabi_write_core_note (bfd *abfd, char *buf, int *bufsiz,
+                               int note_type, ...)
+{
+  switch (note_type)
+    {
+    default:
+      return NULL;
+
+    case NT_PRPSINFO:
+      {
+       char data[124];
+       va_list ap;
+
+       va_start (ap, note_type);
+       memset (data, 0, sizeof (data));
+       strncpy (data + 28, va_arg (ap, const char *), 16);
+       strncpy (data + 44, va_arg (ap, const char *), 80);
+       va_end (ap);
+
+       return elfcore_write_note (abfd, buf, bufsiz,
+                                  "CORE", note_type, data, sizeof (data));
+      }
+
+    case NT_PRSTATUS:
+      {
+       char data[148];
+       va_list ap;
+       long pid;
+       int cursig;
+       const void *greg;
+
+       va_start (ap, note_type);
+       memset (data, 0, sizeof (data));
+       pid = va_arg (ap, long);
+       bfd_put_32 (abfd, pid, data + 24);
+       cursig = va_arg (ap, int);
+       bfd_put_16 (abfd, cursig, data + 12);
+       greg = va_arg (ap, const void *);
+       memcpy (data + 72, greg, 72);
+       va_end (ap);
+
+       return elfcore_write_note (abfd, buf, bufsiz,
+                                  "CORE", note_type, data, sizeof (data));
+      }
+    }
+}
+
 #define TARGET_LITTLE_SYM               bfd_elf32_littlearm_vec
 #define TARGET_LITTLE_NAME              "elf32-littlearm"
 #define TARGET_BIG_SYM                  bfd_elf32_bigarm_vec
@@ -1993,6 +2045,7 @@ elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
 #define elf_backend_grok_prstatus      elf32_arm_nabi_grok_prstatus
 #define elf_backend_grok_psinfo                elf32_arm_nabi_grok_psinfo
+#define elf_backend_write_core_note    elf32_arm_nabi_write_core_note
 
 typedef unsigned long int insn32;
 typedef unsigned short int insn16;
@@ -2027,24 +2080,24 @@ typedef unsigned short int insn16;
 #define ELF_DYNAMIC_INTERPRETER     "/usr/lib/ld.so.1"
 
 static const unsigned long tls_trampoline [] =
-  {
-    0xe08e0000,                /* add r0, lr, r0 */
-    0xe5901004,                /* ldr r1, [r0,#4] */
-    0xe12fff11,                /* bx  r1 */
-  };
+{
+  0xe08e0000,          /* add r0, lr, r0 */
+  0xe5901004,          /* ldr r1, [r0,#4] */
+  0xe12fff11,          /* bx  r1 */
+};
 
 static const unsigned long dl_tlsdesc_lazy_trampoline [] =
-  {
-    0xe52d2004, /*     push    {r2}                    */
-    0xe59f200c, /*      ldr     r2, [pc, #3f - . - 8]  */
-    0xe59f100c, /*      ldr     r1, [pc, #4f - . - 8]  */
-    0xe79f2002, /* 1:   ldr     r2, [pc, r2]           */
-    0xe081100f, /* 2:   add     r1, pc                 */
-    0xe12fff12, /*      bx      r2                     */
-    0x00000014, /* 3:   .word  _GLOBAL_OFFSET_TABLE_ - 1b - 8
+{
+  0xe52d2004, /*       push    {r2}                    */
+  0xe59f200c, /*      ldr     r2, [pc, #3f - . - 8]    */
+  0xe59f100c, /*      ldr     r1, [pc, #4f - . - 8]    */
+  0xe79f2002, /* 1:   ldr     r2, [pc, r2]             */
+  0xe081100f, /* 2:   add     r1, pc                   */
+  0xe12fff12, /*      bx      r2                       */
+  0x00000014, /* 3:   .word  _GLOBAL_OFFSET_TABLE_ - 1b - 8
                                + dl_tlsdesc_lazy_resolver(GOT)   */
-    0x00000018, /* 4:   .word  _GLOBAL_OFFSET_TABLE_ - 2b - 8 */ 
-  };
+  0x00000018, /* 4:   .word  _GLOBAL_OFFSET_TABLE_ - 2b - 8 */
+};
 
 #ifdef FOUR_WORD_PLT
 
@@ -2053,22 +2106,22 @@ static const unsigned long dl_tlsdesc_lazy_trampoline [] =
    called before the relocation has been set up calls the dynamic
    linker first.  */
 static const bfd_vma elf32_arm_plt0_entry [] =
-  {
-    0xe52de004,                /* str   lr, [sp, #-4]! */
-    0xe59fe010,                /* ldr   lr, [pc, #16]  */
-    0xe08fe00e,                /* add   lr, pc, lr     */
-    0xe5bef008,                /* ldr   pc, [lr, #8]!  */
-  };
+{
+  0xe52de004,          /* str   lr, [sp, #-4]! */
+  0xe59fe010,          /* ldr   lr, [pc, #16]  */
+  0xe08fe00e,          /* add   lr, pc, lr     */
+  0xe5bef008,          /* ldr   pc, [lr, #8]!  */
+};
 
 /* Subsequent entries in a procedure linkage table look like
    this.  */
 static const bfd_vma elf32_arm_plt_entry [] =
-  {
-    0xe28fc600,                /* add   ip, pc, #NN    */
-    0xe28cca00,                /* add   ip, ip, #NN    */
-    0xe5bcf000,                /* ldr   pc, [ip, #NN]! */
-    0x00000000,                /* unused               */
-  };
+{
+  0xe28fc600,          /* add   ip, pc, #NN    */
+  0xe28cca00,          /* add   ip, ip, #NN    */
+  0xe5bcf000,          /* ldr   pc, [ip, #NN]! */
+  0x00000000,          /* unused               */
+};
 
 #else
 
@@ -2077,72 +2130,111 @@ static const bfd_vma elf32_arm_plt_entry [] =
    called before the relocation has been set up calls the dynamic
    linker first.  */
 static const bfd_vma elf32_arm_plt0_entry [] =
-  {
-    0xe52de004,                /* str   lr, [sp, #-4]! */
-    0xe59fe004,                /* ldr   lr, [pc, #4]   */
-    0xe08fe00e,                /* add   lr, pc, lr     */
-    0xe5bef008,                /* ldr   pc, [lr, #8]!  */
-    0x00000000,                /* &GOT[0] - .          */
-  };
+{
+  0xe52de004,          /* str   lr, [sp, #-4]! */
+  0xe59fe004,          /* ldr   lr, [pc, #4]   */
+  0xe08fe00e,          /* add   lr, pc, lr     */
+  0xe5bef008,          /* ldr   pc, [lr, #8]!  */
+  0x00000000,          /* &GOT[0] - .          */
+};
 
 /* Subsequent entries in a procedure linkage table look like
    this.  */
 static const bfd_vma elf32_arm_plt_entry [] =
-  {
-    0xe28fc600,                /* add   ip, pc, #0xNN00000 */
-    0xe28cca00,                /* add   ip, ip, #0xNN000   */
-    0xe5bcf000,                /* ldr   pc, [ip, #0xNNN]!  */
-  };
+{
+  0xe28fc600,          /* add   ip, pc, #0xNN00000 */
+  0xe28cca00,          /* add   ip, ip, #0xNN000   */
+  0xe5bcf000,          /* ldr   pc, [ip, #0xNNN]!  */
+};
 
 #endif
 
 /* The format of the first entry in the procedure linkage table
    for a VxWorks executable.  */
 static const bfd_vma elf32_arm_vxworks_exec_plt0_entry[] =
-  {
-    0xe52dc008,                /* str    ip,[sp,#-8]!                  */
-    0xe59fc000,         /* ldr    ip,[pc]                      */
-    0xe59cf008,         /* ldr    pc,[ip,#8]                   */
-    0x00000000,         /* .long  _GLOBAL_OFFSET_TABLE_                */
-  };
+{
+  0xe52dc008,          /* str    ip,[sp,#-8]!                  */
+  0xe59fc000,          /* ldr    ip,[pc]                       */
+  0xe59cf008,          /* ldr    pc,[ip,#8]                    */
+  0x00000000,          /* .long  _GLOBAL_OFFSET_TABLE_         */
+};
 
 /* The format of subsequent entries in a VxWorks executable.  */
 static const bfd_vma elf32_arm_vxworks_exec_plt_entry[] =
-  {
-    0xe59fc000,         /* ldr    ip,[pc]                      */
-    0xe59cf000,         /* ldr    pc,[ip]                      */
-    0x00000000,         /* .long  @got                         */
-    0xe59fc000,         /* ldr    ip,[pc]                      */
-    0xea000000,         /* b      _PLT                         */
-    0x00000000,         /* .long  @pltindex*sizeof(Elf32_Rela) */
-  };
+{
+  0xe59fc000,         /* ldr    ip,[pc]                        */
+  0xe59cf000,         /* ldr    pc,[ip]                        */
+  0x00000000,         /* .long  @got                           */
+  0xe59fc000,         /* ldr    ip,[pc]                        */
+  0xea000000,         /* b      _PLT                           */
+  0x00000000,         /* .long  @pltindex*sizeof(Elf32_Rela)   */
+};
 
 /* The format of entries in a VxWorks shared library.  */
 static const bfd_vma elf32_arm_vxworks_shared_plt_entry[] =
-  {
-    0xe59fc000,         /* ldr    ip,[pc]                      */
-    0xe79cf009,         /* ldr    pc,[ip,r9]                   */
-    0x00000000,         /* .long  @got                         */
-    0xe59fc000,         /* ldr    ip,[pc]                      */
-    0xe599f008,         /* ldr    pc,[r9,#8]                   */
-    0x00000000,         /* .long  @pltindex*sizeof(Elf32_Rela) */
-  };
+{
+  0xe59fc000,         /* ldr    ip,[pc]                        */
+  0xe79cf009,         /* ldr    pc,[ip,r9]                     */
+  0x00000000,         /* .long  @got                           */
+  0xe59fc000,         /* ldr    ip,[pc]                        */
+  0xe599f008,         /* ldr    pc,[r9,#8]                     */
+  0x00000000,         /* .long  @pltindex*sizeof(Elf32_Rela)   */
+};
 
 /* An initial stub used if the PLT entry is referenced from Thumb code.  */
 #define PLT_THUMB_STUB_SIZE 4
 static const bfd_vma elf32_arm_plt_thumb_stub [] =
-  {
-    0x4778,            /* bx pc */
-    0x46c0             /* nop   */
-  };
+{
+  0x4778,              /* bx pc */
+  0x46c0               /* nop   */
+};
 
 /* The entries in a PLT when using a DLL-based target with multiple
    address spaces.  */
 static const bfd_vma elf32_arm_symbian_plt_entry [] =
-  {
-    0xe51ff004,         /* ldr   pc, [pc, #-4] */
-    0x00000000,         /* dcd   R_ARM_GLOB_DAT(X) */
-  };
+{
+  0xe51ff004,         /* ldr   pc, [pc, #-4] */
+  0x00000000,         /* dcd   R_ARM_GLOB_DAT(X) */
+};
+
+/* The first entry in a procedure linkage table looks like
+   this.  It is set up so that any shared library function that is
+   called before the relocation has been set up calls the dynamic
+   linker first.  */
+static const bfd_vma elf32_arm_nacl_plt0_entry [] =
+{
+  /* First bundle: */
+  0xe300c000,          /* movw ip, #:lower16:&GOT[2]-.+8       */
+  0xe340c000,          /* movt ip, #:upper16:&GOT[2]-.+8       */
+  0xe08cc00f,          /* add  ip, ip, pc                      */
+  0xe52dc008,          /* str  ip, [sp, #-8]!                  */
+  /* Second bundle: */
+  0xe7dfcf1f,  /* bfc  ip, #30, #2                     */
+  0xe59cc000,  /* ldr  ip, [ip]                        */
+  0xe3ccc13f,          /* bic  ip, ip, #0xc000000f             */
+  0xe12fff1c,  /* bx   ip                              */
+  /* Third bundle: */
+  0xe320f000,  /* nop                                  */
+  0xe320f000,  /* nop                                  */
+  0xe320f000,  /* nop                                  */
+  /* .Lplt_tail: */
+  0xe50dc004,          /* str  ip, [sp, #-4]                   */
+  /* Fourth bundle: */
+  0xe7dfcf1f,          /* bfc  ip, #30, #2                     */
+  0xe59cc000,  /* ldr  ip, [ip]                        */
+  0xe3ccc13f,          /* bic  ip, ip, #0xc000000f             */
+  0xe12fff1c,  /* bx   ip                              */
+};
+#define ARM_NACL_PLT_TAIL_OFFSET       (11 * 4)
+
+/* Subsequent entries in a procedure linkage table look like this.  */
+static const bfd_vma elf32_arm_nacl_plt_entry [] =
+{
+  0xe300c000,          /* movw ip, #:lower16:&GOT[n]-.+8       */
+  0xe340c000,          /* movt ip, #:upper16:&GOT[n]-.+8       */
+  0xe08cc00f,          /* add  ip, ip, pc                      */
+  0xea000000,          /* b    .Lplt_tail                      */
+};
 
 #define ARM_MAX_FWD_BRANCH_OFFSET  ((((1 << 23) - 1) << 2) + 8)
 #define ARM_MAX_BWD_BRANCH_OFFSET  ((-((1 << 23) << 2)) + 8)
@@ -2152,12 +2244,12 @@ static const bfd_vma elf32_arm_symbian_plt_entry [] =
 #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
 
 enum stub_insn_type
-  {
-    THUMB16_TYPE = 1,
-    THUMB32_TYPE,
-    ARM_TYPE,
-    DATA_TYPE
-  };
+{
+  THUMB16_TYPE = 1,
+  THUMB32_TYPE,
+  ARM_TYPE,
+  DATA_TYPE
+};
 
 #define THUMB16_INSN(X)                {(X), THUMB16_TYPE, R_ARM_NONE, 0}
 /* A bit of a hack.  A Thumb conditional branch, in which the proper condition
@@ -2171,154 +2263,154 @@ enum stub_insn_type
 
 typedef struct
 {
-  bfd_vma data;
-  enum stub_insn_type type;
-  unsigned int r_type;
-  int reloc_addend;
+  bfd_vma              data;
+  enum stub_insn_type  type;
+  unsigned int         r_type;
+  int                  reloc_addend;
 }  insn_sequence;
 
 /* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
    to reach the stub if necessary.  */
 static const insn_sequence elf32_arm_stub_long_branch_any_any[] =
-  {
-    ARM_INSN(0xe51ff004),            /* ldr   pc, [pc, #-4] */
-    DATA_WORD(0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
-  };
+{
+  ARM_INSN (0xe51ff004),            /* ldr   pc, [pc, #-4] */
+  DATA_WORD (0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
+};
 
 /* V4T Arm -> Thumb long branch stub. Used on V4T where blx is not
    available.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb[] =
-  {
-    ARM_INSN(0xe59fc000),            /* ldr   ip, [pc, #0] */
-    ARM_INSN(0xe12fff1c),            /* bx    ip */
-    DATA_WORD(0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
-  };
+{
+  ARM_INSN (0xe59fc000),            /* ldr   ip, [pc, #0] */
+  ARM_INSN (0xe12fff1c),            /* bx    ip */
+  DATA_WORD (0, R_ARM_ABS32, 0),    /* dcd   R_ARM_ABS32(X) */
+};
 
 /* Thumb -> Thumb long branch stub. Used on M-profile architectures.  */
 static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
-  {
-    THUMB16_INSN(0xb401),             /* push {r0} */
-    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
-    THUMB16_INSN(0x4684),             /* mov  ip, r0 */
-    THUMB16_INSN(0xbc01),             /* pop  {r0} */
-    THUMB16_INSN(0x4760),             /* bx   ip */
-    THUMB16_INSN(0xbf00),             /* nop */
-    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
-  };
+{
+  THUMB16_INSN (0xb401),             /* push {r0} */
+  THUMB16_INSN (0x4802),             /* ldr  r0, [pc, #8] */
+  THUMB16_INSN (0x4684),             /* mov  ip, r0 */
+  THUMB16_INSN (0xbc01),             /* pop  {r0} */
+  THUMB16_INSN (0x4760),             /* bx   ip */
+  THUMB16_INSN (0xbf00),             /* nop */
+  DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
+};
 
 /* V4T Thumb -> Thumb long branch stub. Using the stack is not
    allowed.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
-  {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop */
-    ARM_INSN(0xe59fc000),             /* ldr  ip, [pc, #0] */
-    ARM_INSN(0xe12fff1c),             /* bx   ip */
-    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
-  };
+{
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop */
+  ARM_INSN (0xe59fc000),             /* ldr  ip, [pc, #0] */
+  ARM_INSN (0xe12fff1c),             /* bx   ip */
+  DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd  R_ARM_ABS32(X) */
+};
 
 /* V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
    available.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
-  {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop   */
-    ARM_INSN(0xe51ff004),             /* ldr   pc, [pc, #-4] */
-    DATA_WORD(0, R_ARM_ABS32, 0),     /* dcd   R_ARM_ABS32(X) */
-  };
+{
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop   */
+  ARM_INSN (0xe51ff004),             /* ldr   pc, [pc, #-4] */
+  DATA_WORD (0, R_ARM_ABS32, 0),     /* dcd   R_ARM_ABS32(X) */
+};
 
 /* V4T Thumb -> ARM short branch stub. Shorter variant of the above
    one, when the destination is close enough.  */
 static const insn_sequence elf32_arm_stub_short_branch_v4t_thumb_arm[] =
-  {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop   */
-    ARM_REL_INSN(0xea000000, -8),     /* b    (X-8) */
-  };
+{
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop   */
+  ARM_REL_INSN (0xea000000, -8),     /* b    (X-8) */
+};
 
 /* ARM/Thumb -> ARM long branch stub, PIC.  On V5T and above, use
    blx to reach the stub if necessary.  */
 static const insn_sequence elf32_arm_stub_long_branch_any_arm_pic[] =
-  {
-    ARM_INSN(0xe59fc000),             /* ldr   ip, [pc] */
-    ARM_INSN(0xe08ff00c),             /* add   pc, pc, ip */
-    DATA_WORD(0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
-  };
+{
+  ARM_INSN (0xe59fc000),             /* ldr   ip, [pc] */
+  ARM_INSN (0xe08ff00c),             /* add   pc, pc, ip */
+  DATA_WORD (0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
+};
 
 /* ARM/Thumb -> Thumb long branch stub, PIC.  On V5T and above, use
    blx to reach the stub if necessary.  We can not add into pc;
    it is not guaranteed to mode switch (different in ARMv6 and
    ARMv7).  */
 static const insn_sequence elf32_arm_stub_long_branch_any_thumb_pic[] =
-  {
-    ARM_INSN(0xe59fc004),             /* ldr   ip, [pc, #4] */
-    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
-    ARM_INSN(0xe12fff1c),             /* bx    ip */
-    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
-  };
+{
+  ARM_INSN (0xe59fc004),             /* ldr   ip, [pc, #4] */
+  ARM_INSN (0xe08fc00c),             /* add   ip, pc, ip */
+  ARM_INSN (0xe12fff1c),             /* bx    ip */
+  DATA_WORD (0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
+};
 
 /* V4T ARM -> ARM long branch stub, PIC.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
-  {
-    ARM_INSN(0xe59fc004),             /* ldr   ip, [pc, #4] */
-    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
-    ARM_INSN(0xe12fff1c),             /* bx    ip */
-    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
-  };
+{
+  ARM_INSN (0xe59fc004),             /* ldr   ip, [pc, #4] */
+  ARM_INSN (0xe08fc00c),             /* add   ip, pc, ip */
+  ARM_INSN (0xe12fff1c),             /* bx    ip */
+  DATA_WORD (0, R_ARM_REL32, 0),     /* dcd   R_ARM_REL32(X) */
+};
 
 /* V4T Thumb -> ARM long branch stub, PIC.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
-  {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop  */
-    ARM_INSN(0xe59fc000),             /* ldr  ip, [pc, #0] */
-    ARM_INSN(0xe08cf00f),             /* add  pc, ip, pc */
-    DATA_WORD(0, R_ARM_REL32, -4),     /* dcd  R_ARM_REL32(X) */
-  };
+{
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop  */
+  ARM_INSN (0xe59fc000),             /* ldr  ip, [pc, #0] */
+  ARM_INSN (0xe08cf00f),             /* add  pc, ip, pc */
+  DATA_WORD (0, R_ARM_REL32, -4),     /* dcd  R_ARM_REL32(X) */
+};
 
 /* Thumb -> Thumb long branch stub, PIC. Used on M-profile
    architectures.  */
 static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
-  {
-    THUMB16_INSN(0xb401),             /* push {r0} */
-    THUMB16_INSN(0x4802),             /* ldr  r0, [pc, #8] */
-    THUMB16_INSN(0x46fc),             /* mov  ip, pc */
-    THUMB16_INSN(0x4484),             /* add  ip, r0 */
-    THUMB16_INSN(0xbc01),             /* pop  {r0} */
-    THUMB16_INSN(0x4760),             /* bx   ip */
-    DATA_WORD(0, R_ARM_REL32, 4),     /* dcd  R_ARM_REL32(X) */
-  };
+{
+  THUMB16_INSN (0xb401),             /* push {r0} */
+  THUMB16_INSN (0x4802),             /* ldr  r0, [pc, #8] */
+  THUMB16_INSN (0x46fc),             /* mov  ip, pc */
+  THUMB16_INSN (0x4484),             /* add  ip, r0 */
+  THUMB16_INSN (0xbc01),             /* pop  {r0} */
+  THUMB16_INSN (0x4760),             /* bx   ip */
+  DATA_WORD (0, R_ARM_REL32, 4),     /* dcd  R_ARM_REL32(X) */
+};
 
 /* V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not
    allowed.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
-  {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop */
-    ARM_INSN(0xe59fc004),             /* ldr  ip, [pc, #4] */
-    ARM_INSN(0xe08fc00c),             /* add   ip, pc, ip */
-    ARM_INSN(0xe12fff1c),             /* bx   ip */
-    DATA_WORD(0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
-  };
+{
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop */
+  ARM_INSN (0xe59fc004),             /* ldr  ip, [pc, #4] */
+  ARM_INSN (0xe08fc00c),             /* add   ip, pc, ip */
+  ARM_INSN (0xe12fff1c),             /* bx   ip */
+  DATA_WORD (0, R_ARM_REL32, 0),     /* dcd  R_ARM_REL32(X) */
+};
 
 /* Thumb2/ARM -> TLS trampoline.  Lowest common denominator, which is a
    long PIC stub.  We can use r1 as a scratch -- and cannot use ip.  */
 static const insn_sequence elf32_arm_stub_long_branch_any_tls_pic[] =
 {
-    ARM_INSN(0xe59f1000),             /* ldr   r1, [pc] */
-    ARM_INSN(0xe08ff001),             /* add   pc, pc, r1 */
-    DATA_WORD(0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
+  ARM_INSN (0xe59f1000),             /* ldr   r1, [pc] */
+  ARM_INSN (0xe08ff001),             /* add   pc, pc, r1 */
+  DATA_WORD (0, R_ARM_REL32, -4),    /* dcd   R_ARM_REL32(X-4) */
 };
 
 /* V4T Thumb -> TLS trampoline.  lowest common denominator, which is a
    long PIC stub.  We can use r1 as a scratch -- and cannot use ip.  */
 static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
 {
-    THUMB16_INSN(0x4778),             /* bx   pc */
-    THUMB16_INSN(0x46c0),             /* nop */
-    ARM_INSN(0xe59f1000),             /* ldr  r1, [pc, #0] */
-    ARM_INSN(0xe081f00f),             /* add  pc, r1, pc */
-    DATA_WORD(0, R_ARM_REL32, -4),    /* dcd  R_ARM_REL32(X) */
+  THUMB16_INSN (0x4778),             /* bx   pc */
+  THUMB16_INSN (0x46c0),             /* nop */
+  ARM_INSN (0xe59f1000),             /* ldr  r1, [pc, #0] */
+  ARM_INSN (0xe081f00f),             /* add  pc, r1, pc */
+  DATA_WORD (0, R_ARM_REL32, -4),    /* dcd  R_ARM_REL32(X) */
 };
 
 /* Cortex-A8 erratum-workaround stubs.  */
@@ -2327,36 +2419,59 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] =
    can't use a conditional branch to reach this stub).  */
 
 static const insn_sequence elf32_arm_stub_a8_veneer_b_cond[] =
-  {
-    THUMB16_BCOND_INSN(0xd001),         /* b<cond>.n true.  */
-    THUMB32_B_INSN(0xf000b800, -4),     /* b.w insn_after_original_branch.  */
-    THUMB32_B_INSN(0xf000b800, -4)      /* true: b.w original_branch_dest.  */
-  };
+{
+  THUMB16_BCOND_INSN (0xd001),         /* b<cond>.n true.  */
+  THUMB32_B_INSN (0xf000b800, -4),     /* b.w insn_after_original_branch.  */
+  THUMB32_B_INSN (0xf000b800, -4)      /* true: b.w original_branch_dest.  */
+};
 
 /* Stub used for b.w and bl.w instructions.  */
 
 static const insn_sequence elf32_arm_stub_a8_veneer_b[] =
-  {
-    THUMB32_B_INSN(0xf000b800, -4)     /* b.w original_branch_dest.  */
-  };
+{
+  THUMB32_B_INSN (0xf000b800, -4)      /* b.w original_branch_dest.  */
+};
 
 static const insn_sequence elf32_arm_stub_a8_veneer_bl[] =
-  {
-    THUMB32_B_INSN(0xf000b800, -4)     /* b.w original_branch_dest.  */
-  };
+{
+  THUMB32_B_INSN (0xf000b800, -4)      /* b.w original_branch_dest.  */
+};
 
 /* Stub used for Thumb-2 blx.w instructions.  We modified the original blx.w
    instruction (which switches to ARM mode) to point to this stub.  Jump to the
    real destination using an ARM-mode branch.  */
 
 static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
-  {
-    ARM_REL_INSN(0xea000000, -8)       /* b original_branch_dest.  */
-  };
+{
+  ARM_REL_INSN (0xea000000, -8)        /* b original_branch_dest.  */
+};
+
+/* For each section group there can be a specially created linker section
+   to hold the stubs for that group.  The name of the stub section is based
+   upon the name of another section within that group with the suffix below
+   applied.
+
+   PR 13049: STUB_SUFFIX used to be ".stub", but this allowed the user to
+   create what appeared to be a linker stub section when it actually
+   contained user code/data.  For example, consider this fragment:
+
+     const char * stubborn_problems[] = { "np" };
+
+   If this is compiled with "-fPIC -fdata-sections" then gcc produces a
+   section called:
+
+     .data.rel.local.stubborn_problems
+
+   This then causes problems in arm32_arm_build_stubs() as it triggers:
+
+      // Ignore non-stub sections.
+      if (!strstr (stub_sec->name, STUB_SUFFIX))
+       continue;
 
-/* Section name for stubs is the associated section name plus this
-   string.  */
-#define STUB_SUFFIX ".stub"
+   And so the section would be ignored instead of being processed.  Hence
+   the change in definition of STUB_SUFFIX to a name that cannot be a valid
+   C identifier.  */
+#define STUB_SUFFIX ".__stub"
 
 /* One entry per long/short branch stub defined above.  */
 #define DEF_STUBS \
@@ -2380,7 +2495,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
   DEF_STUB(a8_veneer_blx)
 
 #define DEF_STUB(x) arm_stub_##x,
-enum elf32_arm_stub_type {
+enum elf32_arm_stub_type
+{
   arm_stub_none,
   DEF_STUBS
   /* Note the first a8_veneer type */
@@ -2395,7 +2511,8 @@ typedef struct
 } stub_def;
 
 #define DEF_STUB(x) {elf32_arm_stub_##x, ARRAY_SIZE(elf32_arm_stub_##x)},
-static const stub_def stub_definitions[] = {
+static const stub_def stub_definitions[] =
+{
   {NULL, 0},
   DEF_STUBS
 };
@@ -2548,7 +2665,8 @@ _arm_elf_section_data;
    relaxing which we can refresh easily, then create stubs for each potentially
    erratum-triggering instruction once we've settled on a solution.  */
 
-struct a8_erratum_fix {
+struct a8_erratum_fix
+{
   bfd *input_bfd;
   asection *section;
   bfd_vma offset;
@@ -2562,7 +2680,8 @@ struct a8_erratum_fix {
 /* A table of relocs applied to branches which might trigger Cortex-A8
    erratum.  */
 
-struct a8_erratum_reloc {
+struct a8_erratum_reloc
+{
   bfd_vma from;
   bfd_vma destination;
   struct elf32_arm_link_hash_entry *hash;
@@ -2577,7 +2696,8 @@ struct a8_erratum_reloc {
 
 /* ARM-specific information about a PLT entry, over and above the usual
    gotplt_union.  */
-struct arm_plt_info {
+struct arm_plt_info
+{
   /* We reference count Thumb references to a PLT entry separately,
      so that we can emit the Thumb trampoline only if needed.  */
   bfd_signed_vma thumb_refcount;
@@ -2600,7 +2720,8 @@ struct arm_plt_info {
 };
 
 /* Information about an .iplt entry for a local STT_GNU_IFUNC symbol.  */
-struct arm_local_iplt_info {
+struct arm_local_iplt_info
+{
   /* The information that is usually found in the generic ELF part of
      the hash table entry.  */
   union gotplt_union root;
@@ -2661,14 +2782,14 @@ elf32_arm_mkobject (bfd *abfd)
 
 /* Arm ELF linker hash entry.  */
 struct elf32_arm_link_hash_entry
-  {
-    struct elf_link_hash_entry root;
+{
+  struct elf_link_hash_entry root;
 
-    /* Track dynamic relocs copied for this symbol.  */
-    struct elf_dyn_relocs *dyn_relocs;
+  /* Track dynamic relocs copied for this symbol.  */
+  struct elf_dyn_relocs *dyn_relocs;
 
-    /* ARM-specific PLT information.  */
-    struct arm_plt_info plt;
+  /* ARM-specific PLT information.  */
+  struct arm_plt_info plt;
 
 #define GOT_UNKNOWN    0
 #define GOT_NORMAL     1
@@ -2676,25 +2797,25 @@ struct elf32_arm_link_hash_entry
 #define GOT_TLS_IE     4
 #define GOT_TLS_GDESC  8
 #define GOT_TLS_GD_ANY_P(type) ((type & GOT_TLS_GD) || (type & GOT_TLS_GDESC))
-    unsigned int tls_type : 8;
+  unsigned int tls_type : 8;
 
-    /* True if the symbol's PLT entry is in .iplt rather than .plt.  */
-    unsigned int is_iplt : 1;
+  /* True if the symbol's PLT entry is in .iplt rather than .plt.  */
+  unsigned int is_iplt : 1;
 
-    unsigned int unused : 23;
+  unsigned int unused : 23;
 
-    /* Offset of the GOTPLT entry reserved for the TLS descriptor,
-       starting at the end of the jump table.  */
-    bfd_vma tlsdesc_got;
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 
-    /* The symbol marking the real symbol location for exported thumb
-       symbols with Arm stubs.  */
-    struct elf_link_hash_entry *export_glue;
+  /* The symbol marking the real symbol location for exported thumb
+     symbols with Arm stubs.  */
+  struct elf_link_hash_entry *export_glue;
 
-   /* A pointer to the most recently used stub hash entry against this
+  /* A pointer to the most recently used stub hash entry against this
      symbol.  */
-    struct elf32_arm_stub_hash_entry *stub_cache;
-  };
+  struct elf32_arm_stub_hash_entry *stub_cache;
+};
 
 /* Traverse an arm ELF linker hash table.  */
 #define elf32_arm_link_hash_traverse(table, func, info)                        \
@@ -2776,6 +2897,9 @@ struct elf32_arm_link_hash_table
   /* Whether we should fix the Cortex-A8 Thumb-2 branch/TLB erratum.  */
   int fix_cortex_a8;
 
+  /* Whether we should fix the ARM1176 BLX immediate issue.  */
+  int fix_arm1176;
+
   /* Nonzero if the ARM/Thumb BLX instructions are available for use.  */
   int use_blx;
 
@@ -2801,6 +2925,9 @@ struct elf32_arm_link_hash_table
   /* True if the target system is Symbian OS.  */
   int symbian_p;
 
+  /* True if the target system is Native Client.  */
+  int nacl_p;
+
   /* True if the target uses REL relocations.  */
   int use_rel;
 
@@ -2825,7 +2952,7 @@ struct elf32_arm_link_hash_table
 
   /* The offset into sgot of the GOT entry used by the PLT entry
      above.  */
-  bfd_vma dt_tlsdesc_got;    
+  bfd_vma dt_tlsdesc_got;
 
   /* Offset in .plt section of tls_arm_trampoline.  */
   bfd_vma tls_trampoline;
@@ -3121,7 +3248,7 @@ create_ifunc_sections (struct bfd_link_info *info)
   bfd *dynobj;
   asection *s;
   flagword flags;
-  
+
   htab = elf32_arm_hash_table (info);
   dynobj = htab->root.dynobj;
   bed = get_elf_backend_data (dynobj);
@@ -3129,27 +3256,28 @@ create_ifunc_sections (struct bfd_link_info *info)
 
   if (htab->root.iplt == NULL)
     {
-      s = bfd_make_section_with_flags (dynobj, ".iplt",
-                                      flags | SEC_READONLY | SEC_CODE);
+      s = bfd_make_section_anyway_with_flags (dynobj, ".iplt",
+                                             flags | SEC_READONLY | SEC_CODE);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+         || !bfd_set_section_alignment (dynobj, s, bed->plt_alignment))
        return FALSE;
       htab->root.iplt = s;
     }
 
   if (htab->root.irelplt == NULL)
     {
-      s = bfd_make_section_with_flags (dynobj, RELOC_SECTION (htab, ".iplt"),
-                                      flags | SEC_READONLY);
+      s = bfd_make_section_anyway_with_flags (dynobj,
+                                             RELOC_SECTION (htab, ".iplt"),
+                                             flags | SEC_READONLY);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
        return FALSE;
       htab->root.irelplt = s;
     }
 
   if (htab->root.igotplt == NULL)
     {
-      s = bfd_make_section_with_flags (dynobj, ".igot.plt", flags);
+      s = bfd_make_section_anyway_with_flags (dynobj, ".igot.plt", flags);
       if (s == NULL
          || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
        return FALSE;
@@ -3177,10 +3305,10 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
-  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj,
-                                            RELOC_SECTION (htab, ".bss"));
+    htab->srelbss = bfd_get_linker_section (dynobj,
+                                           RELOC_SECTION (htab, ".bss"));
 
   if (htab->vxworks_p)
     {
@@ -3315,6 +3443,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
   ret->vfp11_erratum_glue_size = 0;
   ret->num_vfp11_fixes = 0;
   ret->fix_cortex_a8 = 0;
+  ret->fix_arm1176 = 0;
   ret->bfd_of_glue_owner = NULL;
   ret->byteswap_code = 0;
   ret->target1_is_rel = 0;
@@ -3330,6 +3459,7 @@ elf32_arm_link_hash_table_create (bfd *abfd)
   ret->use_blx = 0;
   ret->vxworks_p = 0;
   ret->symbian_p = 0;
+  ret->nacl_p = 0;
   ret->use_rel = 1;
   ret->sym_cache.abfd = NULL;
   ret->obfd = abfd;
@@ -3498,7 +3628,7 @@ arm_type_of_stub (struct bfd_link_info *info,
       else
        splt = globals->root.splt;
       if (splt != NULL)
-       {       
+       {
          use_plt = 1;
 
          /* Note when dealing with PLT entries: the main PLT stub is in
@@ -3553,7 +3683,7 @@ arm_type_of_stub (struct bfd_link_info *info,
                  stub_type = (info->shared | globals->pic_veneer)
                    /* PIC stubs.  */
                    ? ((globals->use_blx
-                       && (r_type ==R_ARM_THM_CALL))
+                       && (r_type == R_ARM_THM_CALL))
                       /* V5T and above. Stub starts with ARM code, so
                          we must be able to switch mode before
                          reaching it, which is only possible for 'bl'
@@ -3564,7 +3694,7 @@ arm_type_of_stub (struct bfd_link_info *info,
 
                    /* non-PIC stubs.  */
                    : ((globals->use_blx
-                       && (r_type ==R_ARM_THM_CALL))
+                       && (r_type == R_ARM_THM_CALL))
                       /* V5T and above.  */
                       ? arm_stub_long_branch_any_any
                       /* V4T.  */
@@ -3782,7 +3912,7 @@ elf32_arm_get_stub_entry (const asection *input_section,
 }
 
 /* Find or create a stub section.  Returns a pointer to the stub section, and
-   the section to which the stub section will be attached (in *LINK_SEC_P). 
+   the section to which the stub section will be attached (in *LINK_SEC_P).
    LINK_SEC_P may be NULL.  */
 
 static asection *
@@ -3793,7 +3923,9 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section,
   asection *stub_sec;
 
   link_sec = htab->stub_group[section->id].link_sec;
+  BFD_ASSERT (link_sec != NULL);
   stub_sec = htab->stub_group[section->id].stub_sec;
+
   if (stub_sec == NULL)
     {
       stub_sec = htab->stub_group[link_sec->id].stub_sec;
@@ -3818,10 +3950,10 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section,
        }
       htab->stub_group[section->id].stub_sec = stub_sec;
     }
-  
+
   if (link_sec_p)
     *link_sec_p = link_sec;
-  
+
   return stub_sec;
 }
 
@@ -3889,7 +4021,7 @@ put_thumb_insn (struct elf32_arm_link_hash_table * htab,
    model, return the new reloc type.  */
 
 static unsigned
-elf32_arm_tls_transition (struct bfd_link_info *info, int r_type, 
+elf32_arm_tls_transition (struct bfd_link_info *info, int r_type,
                          struct elf_link_hash_entry *h)
 {
   int is_local = (h == NULL);
@@ -3897,7 +4029,7 @@ elf32_arm_tls_transition (struct bfd_link_info *info, int r_type,
   if (info->shared || (h && h->root.type == bfd_link_hash_undefweak))
     return r_type;
 
-  /* We do not support relaxations for Old TLS models.  */ 
+  /* We do not support relaxations for Old TLS models.  */
   switch (r_type)
     {
     case R_ARM_TLS_GOTDESC:
@@ -3943,7 +4075,7 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
     case arm_stub_long_branch_v4t_thumb_tls_pic:
     case arm_stub_a8_veneer_blx:
       return 4;
-    
+
     default:
       abort ();  /* Should be unreachable.  */
     }
@@ -4481,7 +4613,7 @@ cortex_a8_erratum_scan (bfd *input_bfd,
       if (elf_section_type (section) != SHT_PROGBITS
           || (elf_section_flags (section) & SHF_EXECINSTR) == 0
           || (section->flags & SEC_EXCLUDE) != 0
-          || (section->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+          || (section->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
           || (section->output_section == bfd_abs_section_ptr))
         continue;
 
@@ -4916,13 +5048,13 @@ elf32_arm_size_stubs (bfd *output_bfd,
                        free (internal_relocs);
                      goto error_ret_free_local;
                    }
-                 
+
                  hash = NULL;
                  if (r_indx >= symtab_hdr->sh_info)
                    hash = elf32_arm_hash_entry
                      (elf_sym_hashes (input_bfd)
                       [r_indx - symtab_hdr->sh_info]);
-                 
+
                  /* Only look for stubs on branch instructions, or
                     non-relaxed TLSCALL  */
                  if ((r_type != (unsigned int) R_ARM_CALL)
@@ -4948,7 +5080,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                  sym_value = 0;
                  destination = 0;
                  sym_name = NULL;
-                 
+
                  if (r_type == (unsigned int) R_ARM_TLS_CALL
                      || r_type == (unsigned int) R_ARM_THM_TLS_CALL)
                    {
@@ -5493,9 +5625,9 @@ static const insn32 a2t3p_bx_r12_insn = 0xe12fff1c;
      .arm                               mov  lr, pc
      b func                             bx   r6
                                         .arm
-                                   ;; back_to_thumb       
+                                   ;; back_to_thumb
                                        ldmia r13! {r6, lr}
-                                       bx    lr           
+                                       bx    lr
                                     __func_addr:
                                         .word        func  */
 
@@ -5523,7 +5655,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na
       /* Do not include empty glue sections in the output.  */
       if (abfd != NULL)
        {
-         s = bfd_get_section_by_name (abfd, name);
+         s = bfd_get_linker_section (abfd, name);
          if (s != NULL)
            s->flags |= SEC_EXCLUDE;
        }
@@ -5532,7 +5664,7 @@ arm_allocate_glue_section_space (bfd * abfd, bfd_size_type size, const char * na
 
   BFD_ASSERT (abfd != NULL);
 
-  s = bfd_get_section_by_name (abfd, name);
+  s = bfd_get_linker_section (abfd, name);
   BFD_ASSERT (s != NULL);
 
   contents = (bfd_byte *) bfd_alloc (abfd, size);
@@ -5588,7 +5720,7 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
   BFD_ASSERT (globals != NULL);
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
-  s = bfd_get_section_by_name
+  s = bfd_get_linker_section
     (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
 
   BFD_ASSERT (s != NULL);
@@ -5664,7 +5796,7 @@ record_arm_bx_glue (struct bfd_link_info * link_info, int reg)
   if (globals->bx_glue_offset[reg])
     return;
 
-  s = bfd_get_section_by_name
+  s = bfd_get_linker_section
     (globals->bfd_of_glue_owner, ARM_BX_GLUE_SECTION_NAME);
 
   BFD_ASSERT (s != NULL);
@@ -5755,7 +5887,7 @@ record_vfp11_erratum_veneer (struct bfd_link_info *link_info,
   BFD_ASSERT (hash_table != NULL);
   BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL);
 
-  s = bfd_get_section_by_name
+  s = bfd_get_linker_section
     (hash_table->bfd_of_glue_owner, VFP11_ERRATUM_VENEER_SECTION_NAME);
 
   sec_data = elf32_arm_section_data (s);
@@ -5862,12 +5994,12 @@ arm_make_glue_section (bfd * abfd, const char * name)
 {
   asection * sec;
 
-  sec = bfd_get_section_by_name (abfd, name);
+  sec = bfd_get_linker_section (abfd, name);
   if (sec != NULL)
     /* Already made.  */
     return TRUE;
 
-  sec = bfd_make_section_with_flags (abfd, name, ARM_GLUE_SECTION_FLAGS);
+  sec = bfd_make_section_anyway_with_flags (abfd, name, ARM_GLUE_SECTION_FLAGS);
 
   if (sec == NULL
       || !bfd_set_section_alignment (abfd, sec, 2))
@@ -5930,9 +6062,21 @@ bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info)
 static void
 check_use_blx (struct elf32_arm_link_hash_table *globals)
 {
-  if (bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
-                               Tag_CPU_arch) > 2)
-    globals->use_blx = 1;
+  int cpu_arch;
+
+  cpu_arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
+                                      Tag_CPU_arch);
+
+  if (globals->fix_arm1176)
+    {
+      if (cpu_arch == TAG_CPU_ARCH_V6T2 || cpu_arch > TAG_CPU_ARCH_V6K)
+       globals->use_blx = 1;
+    }
+  else
+    {
+      if (cpu_arch > TAG_CPU_ARCH_V4T)
+       globals->use_blx = 1;
+    }
 }
 
 bfd_boolean
@@ -6540,7 +6684,7 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
       if (elf_section_type (sec) != SHT_PROGBITS
           || (elf_section_flags (sec) & SHF_EXECINSTR) == 0
           || (sec->flags & SEC_EXCLUDE) != 0
-         || sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS
+         || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS
          || sec->output_section == bfd_abs_section_ptr
           || strcmp (sec->name, VFP11_ERRATUM_VENEER_SECTION_NAME) == 0)
         continue;
@@ -6786,7 +6930,8 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
                                 int use_blx,
                                  bfd_arm_vfp11_fix vfp11_fix,
                                 int no_enum_warn, int no_wchar_warn,
-                                int pic_veneer, int fix_cortex_a8)
+                                int pic_veneer, int fix_cortex_a8,
+                                int fix_arm1176)
 {
   struct elf32_arm_link_hash_table *globals;
 
@@ -6811,6 +6956,7 @@ bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd,
   globals->vfp11_fix = vfp11_fix;
   globals->pic_veneer = pic_veneer;
   globals->fix_cortex_a8 = fix_cortex_a8;
+  globals->fix_arm1176 = fix_arm1176;
 
   BFD_ASSERT (is_arm_elf (output_bfd));
   elf_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
@@ -6873,8 +7019,8 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
 
   my_offset = myh->root.u.def.value;
 
-  s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
-                              THUMB2ARM_GLUE_SECTION_NAME);
+  s = bfd_get_linker_section (globals->bfd_of_glue_owner,
+                             THUMB2ARM_GLUE_SECTION_NAME);
 
   BFD_ASSERT (s != NULL);
   BFD_ASSERT (s->contents != NULL);
@@ -6888,7 +7034,7 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
        {
          (*_bfd_error_handler)
            (_("%B(%s): warning: interworking not enabled.\n"
-              "  first occurrence: %B: thumb call to arm"),
+              "  first occurrence: %B: Thumb call to ARM"),
             sym_sec->owner, input_bfd, name);
 
          return FALSE;
@@ -7063,8 +7209,8 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
   BFD_ASSERT (globals != NULL);
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
-  s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
-                              ARM2THUMB_GLUE_SECTION_NAME);
+  s = bfd_get_linker_section (globals->bfd_of_glue_owner,
+                             ARM2THUMB_GLUE_SECTION_NAME);
   BFD_ASSERT (s != NULL);
   BFD_ASSERT (s->contents != NULL);
   BFD_ASSERT (s->output_section != NULL);
@@ -7117,8 +7263,8 @@ elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf)
   BFD_ASSERT (globals != NULL);
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
-  s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
-                              ARM2THUMB_GLUE_SECTION_NAME);
+  s = bfd_get_linker_section (globals->bfd_of_glue_owner,
+                             ARM2THUMB_GLUE_SECTION_NAME);
   BFD_ASSERT (s != NULL);
   BFD_ASSERT (s->contents != NULL);
   BFD_ASSERT (s->output_section != NULL);
@@ -7152,8 +7298,8 @@ elf32_arm_bx_glue (struct bfd_link_info * info, int reg)
   BFD_ASSERT (globals != NULL);
   BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
 
-  s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
-                              ARM_BX_GLUE_SECTION_NAME);
+  s = bfd_get_linker_section (globals->bfd_of_glue_owner,
+                             ARM_BX_GLUE_SECTION_NAME);
   BFD_ASSERT (s != NULL);
   BFD_ASSERT (s->contents != NULL);
   BFD_ASSERT (s->output_section != NULL);
@@ -7309,6 +7455,18 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info,
     }
 }
 
+static bfd_vma
+arm_movw_immediate (bfd_vma value)
+{
+  return (value & 0x00000fff) | ((value & 0x0000f000) << 4);
+}
+
+static bfd_vma
+arm_movt_immediate (bfd_vma value)
+{
+  return ((value & 0x0fff0000) >> 16) | ((value & 0xf0000000) >> 12);
+}
+
 /* Fill in a PLT entry and its associated GOT slot.  If DYNINDX == -1,
    the entry lives in .iplt and resolves to (*SYM_VALUE)().
    Otherwise, DYNINDX is the index of the symbol in the dynamic
@@ -7469,6 +7627,45 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
          rel.r_addend = 0;
          SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
        }
+      else if (htab->nacl_p)
+       {
+         /* Calculate the displacement between the PLT slot and the
+            common tail that's part of the special initial PLT slot.  */
+         int32_t tail_displacement
+           = ((splt->output_section->vma + splt->output_offset
+               + ARM_NACL_PLT_TAIL_OFFSET)
+              - (plt_address + htab->plt_entry_size + 4));
+         BFD_ASSERT ((tail_displacement & 3) == 0);
+         tail_displacement >>= 2;
+
+         BFD_ASSERT ((tail_displacement & 0xff000000) == 0
+                     || (-tail_displacement & 0xff000000) == 0);
+
+         /* Calculate the displacement between the PLT slot and the entry
+            in the GOT.  The offset accounts for the value produced by
+            adding to pc in the penultimate instruction of the PLT stub.  */
+         got_displacement = (got_address
+                              - (plt_address + htab->plt_entry_size));
+
+         /* NaCl does not support interworking at all.  */
+         BFD_ASSERT (!elf32_arm_plt_needs_thumb_stub_p (info, arm_plt));
+
+         put_arm_insn (htab, output_bfd,
+                       elf32_arm_nacl_plt_entry[0]
+                       | arm_movw_immediate (got_displacement),
+                       ptr + 0);
+         put_arm_insn (htab, output_bfd,
+                       elf32_arm_nacl_plt_entry[1]
+                       | arm_movt_immediate (got_displacement),
+                       ptr + 4);
+         put_arm_insn (htab, output_bfd,
+                       elf32_arm_nacl_plt_entry[2],
+                       ptr + 8);
+         put_arm_insn (htab, output_bfd,
+                       elf32_arm_nacl_plt_entry[3]
+                       | (tail_displacement & 0x00ffffff),
+                       ptr + 12);
+       }
       else
        {
          /* Calculate the displacement between the PLT slot and the
@@ -7609,18 +7806,18 @@ elf32_arm_abs12_reloc (bfd *abfd, void *data, bfd_vma value)
    the pre-relaxed code.  It would be nice if the relocs were updated
    to match the optimization.   */
 
-static bfd_reloc_status_type 
+static bfd_reloc_status_type
 elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
-                    bfd *input_bfd, asection *input_sec, bfd_byte *contents, 
+                    bfd *input_bfd, asection *input_sec, bfd_byte *contents,
                     Elf_Internal_Rela *rel, unsigned long is_local)
 {
   unsigned long insn;
-  
+
   switch (ELF32_R_TYPE (rel->r_info))
     {
     default:
       return bfd_reloc_notsupported;
-      
+
     case R_ARM_TLS_GOTDESC:
       if (is_local)
        insn = 0;
@@ -7676,7 +7873,7 @@ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
          return bfd_reloc_notsupported;
        }
       break;
-      
+
     case R_ARM_TLS_DESCSEQ:
       /* arm insn.  */
       insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
@@ -7722,7 +7919,7 @@ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
       insn = is_local ? 0xe1a00000 : 0xe79f0000;
       bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
       break;
-      
+
     case R_ARM_THM_TLS_CALL:
       /* GD->IE relaxation */
       if (!is_local)
@@ -7734,7 +7931,7 @@ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals,
       else
        /* nop; nop */
        insn = 0xbf00bf00;
-       
+
       bfd_put_16 (input_bfd, insn >> 16, contents + rel->r_offset);
       bfd_put_16 (input_bfd, insn & 0xffff, contents + rel->r_offset + 2);
       break;
@@ -8202,15 +8399,19 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                {
                  /* The target is out of reach, so redirect the
                     branch to the local stub for this function.  */
-
                  stub_entry = elf32_arm_get_stub_entry (input_section,
                                                         sym_sec, h,
                                                         rel, globals,
                                                         stub_type);
-                 if (stub_entry != NULL)
-                   value = (stub_entry->stub_offset
-                            + stub_entry->stub_sec->output_offset
-                            + stub_entry->stub_sec->output_section->vma);
+                 {
+                   if (stub_entry != NULL)
+                     value = (stub_entry->stub_offset
+                              + stub_entry->stub_sec->output_offset
+                              + stub_entry->stub_sec->output_section->vma);
+
+                   if (plt_offset != (bfd_vma) -1)
+                     *unresolved_reloc_p = FALSE;
+                 }
                }
              else
                {
@@ -8635,9 +8836,14 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                                                       rel, globals,
                                                       stub_type);
                if (stub_entry != NULL)
-                 value = (stub_entry->stub_offset
-                          + stub_entry->stub_sec->output_offset
-                          + stub_entry->stub_sec->output_section->vma);
+                 {
+                   value = (stub_entry->stub_offset
+                            + stub_entry->stub_sec->output_offset
+                            + stub_entry->stub_sec->output_section->vma);
+
+                   if (plt_offset != (bfd_vma) -1)
+                     *unresolved_reloc_p = FALSE;
+                 }
 
                /* If this call becomes a call to Arm, force BLX.  */
                if (globals->use_blx && (r_type == R_ARM_THM_CALL))
@@ -9146,9 +9352,9 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
          }
 
        /* Linker relaxations happens from one of the
-          R_ARM_{GOTDESC,CALL,DESCSEQ} relocations to IE or LE.  */ 
+          R_ARM_{GOTDESC,CALL,DESCSEQ} relocations to IE or LE.  */
        if (ELF32_R_TYPE(rel->r_info) != r_type)
-         tls_type = GOT_TLS_IE; 
+         tls_type = GOT_TLS_IE;
 
        BFD_ASSERT (tls_type != GOT_UNKNOWN);
 
@@ -9189,7 +9395,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                                   + globals->root.sgotplt->output_offset
                                   + offplt
                                   + globals->sgotplt_jump_table_size);
-               
+
                outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DESC);
                sreloc = globals->root.srelplt;
                loc = sreloc->contents;
@@ -9207,13 +9413,13 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                            !h ? value - elf_hash_table (info)->tls_sec->vma
                            : info->flags & DF_BIND_NOW ? 0
                            : 0x80000000 | ELF32_R_SYM (outrel.r_info),
-                           globals->root.sgotplt->contents + offplt +
-                           globals->sgotplt_jump_table_size);
-               
+                           globals->root.sgotplt->contents + offplt
+                           globals->sgotplt_jump_table_size);
+
                /* Second word in the relocation is always zero.  */
                bfd_put_32 (output_bfd, 0,
-                           globals->root.sgotplt->contents + offplt +
-                           globals->sgotplt_jump_table_size + 4);
+                           globals->root.sgotplt->contents + offplt
+                           globals->sgotplt_jump_table_size + 4);
              }
            if (tls_type & GOT_TLS_GD)
              {
@@ -9333,9 +9539,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            if (ELF32_R_TYPE(rel->r_info) == R_ARM_TLS_CALL)
              {
                unsigned long inst;
-               
-               offset -= (input_section->output_section->vma +
-                          input_section->output_offset + rel->r_offset + 8);
+
+               offset -= (input_section->output_section->vma
+                          + input_section->output_offset
+                          + rel->r_offset + 8);
 
                inst = offset >> 2;
                inst &= 0x00ffffff;
@@ -9348,10 +9555,10 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                unsigned upper_insn, lower_insn;
                unsigned neg;
 
-               offset -= (input_section->output_section->vma + 
-                          input_section->output_offset
+               offset -= (input_section->output_section->vma
+                          input_section->output_offset
                           + rel->r_offset + 4);
-           
+
                if (stub_type != arm_stub_none
                    && arm_stub_is_thumb (stub_type))
                  {
@@ -9384,11 +9591,11 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
          {
            unsigned long data, insn;
            unsigned thumb;
-           
+
            data = bfd_get_32 (input_bfd, hit_data);
            thumb = data & 1;
            data &= ~1u;
-           
+
            if (thumb)
              {
                insn = bfd_get_16 (input_bfd, contents + rel->r_offset - data);
@@ -9425,7 +9632,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                  case 0xe0:    /* add */
                    value = -8;
                    break;
-                   
+
                  default:
                    (*_bfd_error_handler)
                      (_("%B(%A+0x%lx):unexpected ARM instruction '0x%x' referenced by TLS_GOTDESC"),
@@ -9434,7 +9641,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
                    return bfd_reloc_notsupported;
                  }
              }
+
            value += ((globals->root.sgotplt->output_section->vma
                       + globals->root.sgotplt->output_offset + off)
                      - (input_section->output_section->vma
@@ -9460,7 +9667,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
            (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"),
             input_bfd, input_section,
             (long) rel->r_offset, howto->name);
-         return (bfd_reloc_status_type) FALSE;
+         return bfd_reloc_notsupported;
        }
       else
        value = tpoff (info, value);
@@ -10168,7 +10375,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
                   rel->r_offset, TRUE))
                return FALSE;
            }
-         
+
          if (globals->use_rel)
            {
              relocation = (sec->output_section->vma
@@ -10277,9 +10484,9 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
          sym_type = h->type;
        }
 
-      if (sec != NULL && elf_discarded_section (sec))
+      if (sec != NULL && discarded_section (sec))
        RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, relend, howto, contents);
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
        {
@@ -10333,7 +10540,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
          both in relaxed and non-relaxed cases */
      if ((elf32_arm_tls_transition (info, r_type, h) != (unsigned)r_type)
         || (IS_ARM_TLS_GNU_RELOC (r_type)
-            && !((h ? elf32_arm_hash_entry (h)->tls_type : 
+            && !((h ? elf32_arm_hash_entry (h)->tls_type :
                   elf32_arm_local_got_tls_type (input_bfd)[r_symndx])
                  & GOT_TLS_GDESC)))
        {
@@ -10345,7 +10552,7 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
        }
      else
        r = bfd_reloc_continue;
-     
+
      if (r == bfd_reloc_continue)
        r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
                                          input_section, contents, rel,
@@ -10359,7 +10566,9 @@ elf32_arm_relocate_section (bfd *                  output_bfd,
         not process them.  */
       if (unresolved_reloc
           && !((input_section->flags & SEC_DEBUGGING) != 0
-               && h->def_dynamic))
+               && h->def_dynamic)
+         && _bfd_elf_section_offset (output_bfd, info, input_section,
+                                     rel->r_offset) != (bfd_vma) -1)
        {
          (*_bfd_error_handler)
            (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
@@ -10439,11 +10648,11 @@ add_unwind_table_edit (arm_unwind_table_edit **head,
 {
   arm_unwind_table_edit *new_edit = (arm_unwind_table_edit *)
       xmalloc (sizeof (arm_unwind_table_edit));
-  
+
   new_edit->type = type;
   new_edit->linked_section = linked_section;
   new_edit->index = tindex;
-  
+
   if (tindex > 0)
     {
       new_edit->next = NULL;
@@ -10501,7 +10710,7 @@ insert_cantunwind_after(asection *text_sec, asection *exidx_sec)
 
 /* Scan .ARM.exidx tables, and create a list describing edits which should be
    made to those tables, such that:
-   
+
      1. Regions without unwind data are marked with EXIDX_CANTUNWIND entries.
      2. Duplicate entries are merged together (EXIDX_CANTUNWIND, or unwind
         codes which have been inlined into the index).
@@ -10509,8 +10718,7 @@ insert_cantunwind_after(asection *text_sec, asection *exidx_sec)
    If MERGE_EXIDX_ENTRIES is false, duplicate entries are not merged.
 
    The edits are applied when the tables are written
-   (in elf32_arm_write_section).
-*/
+   (in elf32_arm_write_section).  */
 
 bfd_boolean
 elf32_arm_fix_exidx_coverage (asection **text_section_order,
@@ -10529,15 +10737,15 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
   for (inp = info->input_bfds; inp != NULL; inp = inp->link_next)
     {
       asection *sec;
-      
+
       for (sec = inp->sections; sec != NULL; sec = sec->next)
         {
          struct bfd_elf_section_data *elf_sec = elf_section_data (sec);
          Elf_Internal_Shdr *hdr = &elf_sec->this_hdr;
-         
+
          if (!hdr || hdr->sh_type != SHT_ARM_EXIDX)
            continue;
-         
+
          if (elf_sec->linked_to)
            {
              Elf_Internal_Shdr *linked_hdr
@@ -10599,13 +10807,13 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
       hdr = &elf_section_data (exidx_sec)->this_hdr;
       if (hdr->sh_type != SHT_ARM_EXIDX)
         continue;
-      
+
       exidx_arm_data = get_arm_elf_section_data (exidx_sec);
       if (exidx_arm_data == NULL)
         continue;
-      
+
       ibfd = exidx_sec->owner;
-         
+
       if (hdr->contents != NULL)
        contents = hdr->contents;
       else if (! bfd_malloc_and_get_section (ibfd, exidx_sec, &contents))
@@ -10657,7 +10865,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order,
       /* Record edits to be applied later (in elf32_arm_write_section).  */
       exidx_arm_data->u.exidx.unwind_edit_list = unwind_edit_head;
       exidx_arm_data->u.exidx.unwind_edit_tail = unwind_edit_tail;
-         
+
       if (deleted_exidx_bytes > 0)
        adjust_exidx_size(exidx_sec, -deleted_exidx_bytes);
 
@@ -10678,7 +10886,7 @@ elf32_arm_output_glue_section (struct bfd_link_info *info, bfd *obfd,
 {
   asection *sec, *osec;
 
-  sec = bfd_get_section_by_name (ibfd, name);
+  sec = bfd_get_linker_section (ibfd, name);
   if (sec == NULL || (sec->flags & SEC_EXCLUDE) != 0)
     return TRUE;
 
@@ -10751,6 +10959,43 @@ elf32_arm_final_link (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 
+/* Return a best guess for the machine number based on the attributes.  */
+
+static unsigned int
+bfd_arm_get_mach_from_attributes (bfd * abfd)
+{
+  int arch = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_CPU_arch);
+
+  switch (arch)
+    {
+    case TAG_CPU_ARCH_V4: return bfd_mach_arm_4;
+    case TAG_CPU_ARCH_V4T: return bfd_mach_arm_4T;
+    case TAG_CPU_ARCH_V5T: return bfd_mach_arm_5T;
+
+    case TAG_CPU_ARCH_V5TE:
+      {
+       char * name;
+
+       BFD_ASSERT (Tag_CPU_name < NUM_KNOWN_OBJ_ATTRIBUTES);
+       name = elf_known_obj_attributes (abfd) [OBJ_ATTR_PROC][Tag_CPU_name].s;
+
+       if (name)
+         {
+           if (strcmp (name, "IWMMXT2") == 0)
+             return bfd_mach_arm_iWMMXt2;
+
+           if (strcmp (name, "IWMMXT") == 0)
+             return bfd_mach_arm_iWMMXt;
+         }
+
+       return bfd_mach_arm_5TE;
+      }
+
+    default:
+      return bfd_mach_arm_unknown;
+    }
+}
+
 /* Set the right machine number.  */
 
 static bfd_boolean
@@ -10760,15 +11005,15 @@ elf32_arm_object_p (bfd *abfd)
 
   mach = bfd_arm_get_mach_from_notes (abfd, ARM_NOTE_SECTION);
 
-  if (mach != bfd_mach_arm_unknown)
-    bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
-
-  else if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
-    bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
-
-  else
-    bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
+  if (mach == bfd_mach_arm_unknown)
+    {
+      if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
+       mach = bfd_mach_arm_ep9312;
+      else
+       mach = bfd_arm_get_mach_from_attributes (abfd);
+    }
 
+  bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach);
   return TRUE;
 }
 
@@ -11082,6 +11327,24 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       T(V7E_M),  /* V6S_M.  */
       T(V7E_M)   /* V7E_M.  */
     };
+  const int v8[] =
+    {
+      T(V8),           /* PRE_V4.  */
+      T(V8),           /* V4.  */
+      T(V8),           /* V4T.  */
+      T(V8),           /* V5T.  */
+      T(V8),           /* V5TE.  */
+      T(V8),           /* V5TEJ.  */
+      T(V8),           /* V6.  */
+      T(V8),           /* V6KZ.  */
+      T(V8),           /* V6T2.  */
+      T(V8),           /* V6K.  */
+      T(V8),           /* V7.  */
+      T(V8),           /* V6_M.  */
+      T(V8),           /* V6S_M.  */
+      T(V8),           /* V7E_M.  */
+      T(V8)            /* V8.  */
+    };
   const int v4t_plus_v6_m[] =
     {
       -1,              /* PRE_V4.  */
@@ -11098,6 +11361,7 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       T(V6_M),         /* V6_M.  */
       T(V6S_M),                /* V6S_M.  */
       T(V7E_M),                /* V7E_M.  */
+      T(V8),           /* V8.  */
       T(V4T_PLUS_V6_M) /* V4T plus V6_M.  */
     };
   const int *comb[] =
@@ -11108,6 +11372,7 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
       v6_m,
       v6s_m,
       v7e_m,
+      v8,
       /* Pseudo-architecture.  */
       v4t_plus_v6_m
     };
@@ -11163,6 +11428,46 @@ tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
 #undef T
 }
 
+/* Query attributes object to see if integer divide instructions may be
+   present in an object.  */
+static bfd_boolean
+elf32_arm_attributes_accept_div (const obj_attribute *attr)
+{
+  int arch = attr[Tag_CPU_arch].i;
+  int profile = attr[Tag_CPU_arch_profile].i;
+
+  switch (attr[Tag_DIV_use].i)
+    {
+    case 0:
+      /* Integer divide allowed if instruction contained in archetecture.  */
+      if (arch == TAG_CPU_ARCH_V7 && (profile == 'R' || profile == 'M'))
+       return TRUE;
+      else if (arch >= TAG_CPU_ARCH_V7E_M)
+       return TRUE;
+      else
+       return FALSE;
+
+    case 1:
+      /* Integer divide explicitly prohibited.  */
+      return FALSE;
+
+    default:
+      /* Unrecognised case - treat as allowing divide everywhere.  */
+    case 2:
+      /* Integer divide allowed in ARM state.  */
+      return TRUE;
+    }
+}
+
+/* Query attributes object to see if integer divide instructions are
+   forbidden to be in the object.  This is not the inverse of
+   elf32_arm_attributes_accept_div.  */
+static bfd_boolean
+elf32_arm_attributes_forbid_div (const obj_attribute *attr)
+{
+  return attr[Tag_DIV_use].i == 1;
+}
+
 /* Merge EABI object attributes from IBFD into OBFD.  Raise an error if there
    are conflicting attributes.  */
 
@@ -11269,7 +11574,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                "ARM v6K",
                "ARM v7",
                "ARM v6-M",
-               "ARM v6S-M"
+               "ARM v6S-M",
+               "ARM v8"
            };
 
            /* Merge Tag_CPU_arch and Tag_also_compatible_with.  */
@@ -11414,11 +11720,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                 when it's 0.  It might mean absence of FP hardware if
                 Tag_FP_arch is zero, otherwise it is effectively SP + DP.  */
 
+#define VFP_VERSION_COUNT 8
              static const struct
              {
                  int ver;
                  int regs;
-             } vfp_versions[7] =
+             } vfp_versions[VFP_VERSION_COUNT] =
                {
                  {0, 0},
                  {1, 16},
@@ -11426,7 +11733,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                  {3, 32},
                  {3, 16},
                  {4, 32},
-                 {4, 16}
+                 {4, 16},
+                 {8, 32}
                };
              int ver;
              int regs;
@@ -11466,9 +11774,10 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
 
              /* Now we can handle Tag_FP_arch.  */
 
-             /* Values greater than 6 aren't defined, so just pick the
-                biggest */
-             if (in_attr[i].i > 6 && in_attr[i].i > out_attr[i].i)
+             /* Values of VFP_VERSION_COUNT or more aren't defined, so just
+                pick the biggest.  */
+             if (in_attr[i].i >= VFP_VERSION_COUNT
+                 && in_attr[i].i > out_attr[i].i)
                {
                  out_attr[i] = in_attr[i];
                  break;
@@ -11483,7 +11792,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                regs = vfp_versions[out_attr[i].i].regs;
              /* This assumes all possible supersets are also a valid
                 options.  */
-             for (newval = 6; newval > 0; newval--)
+             for (newval = VFP_VERSION_COUNT - 1; newval > 0; newval--)
                {
                  if (regs == vfp_versions[newval].regs
                      && ver == vfp_versions[newval].ver)
@@ -11495,7 +11804,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
        case Tag_PCS_config:
          if (out_attr[i].i == 0)
            out_attr[i].i = in_attr[i].i;
-         else if (in_attr[i].i != 0 && out_attr[i].i != 0)
+         else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i)
            {
              /* It's sometimes ok to mix different configs, so this is only
                 a warning.  */
@@ -11604,29 +11913,22 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
          break;
 
        case Tag_DIV_use:
-         /* This tag is set to zero if we can use UDIV and SDIV in Thumb
-            mode on a v7-M or v7-R CPU; to one if we can not use UDIV or
-            SDIV at all; and to two if we can use UDIV or SDIV on a v7-A
-            CPU.  We will merge as follows: If the input attribute's value
-            is one then the output attribute's value remains unchanged.  If
-            the input attribute's value is zero or two then if the output
-            attribute's value is one the output value is set to the input
-            value, otherwise the output value must be the same as the
-            inputs.  */ 
-         if (in_attr[i].i != 1 && out_attr[i].i != 1) 
-           { 
-             if (in_attr[i].i != out_attr[i].i)
-               {
-                 _bfd_error_handler
-                   (_("DIV usage mismatch between %B and %B"),
-                    ibfd, obfd); 
-                 result = FALSE;
-               }
-           } 
-
-         if (in_attr[i].i != 1)
-           out_attr[i].i = in_attr[i].i; 
-         
+         /* A value of zero on input means that the divide instruction may
+            be used if available in the base architecture as specified via
+            Tag_CPU_arch and Tag_CPU_arch_profile.  A value of 1 means that
+            the user did not want divide instructions.  A value of 2
+            explicitly means that divide instructions were allowed in ARM
+            and Thumb state.  */
+         if (in_attr[i].i == out_attr[i].i)
+           /* Do nothing.  */ ;
+         else if (elf32_arm_attributes_forbid_div (in_attr)
+                  && !elf32_arm_attributes_accept_div (out_attr))
+           out_attr[i].i = 1;
+         else if (elf32_arm_attributes_forbid_div (out_attr)
+                  && elf32_arm_attributes_accept_div (in_attr))
+           out_attr[i].i = in_attr[i].i;
+         else if (in_attr[i].i == 2)
+           out_attr[i].i = in_attr[i].i;
          break;
 
        case Tag_MPextension_use_legacy:
@@ -11638,7 +11940,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
                {
                  _bfd_error_handler
                    (_("%B has has both the current and legacy "
-                      "Tag_MPextension_use attributes"), 
+                      "Tag_MPextension_use attributes"),
                     ibfd);
                  result = FALSE;
                }
@@ -11808,6 +12110,15 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr)
 
     case EF_ARM_EABI_VER5:
       fprintf (file, _(" [Version5 EABI]"));
+
+      if (flags & EF_ARM_ABI_FLOAT_SOFT)
+       fprintf (file, _(" [soft-float ABI]"));
+
+      if (flags & EF_ARM_ABI_FLOAT_HARD)
+       fprintf (file, _(" [hard-float ABI]"));
+
+      flags &= ~(EF_ARM_ABI_FLOAT_SOFT | EF_ARM_ABI_FLOAT_HARD);
+
     eabi:
       if (flags & EF_ARM_BE8)
        fprintf (file, _(" [BE8]"));
@@ -12018,8 +12329,19 @@ elf32_arm_gc_sweep_hook (bfd *                     abfd,
       if (may_need_local_target_p
          && elf32_arm_get_plt_info (abfd, eh, r_symndx, &root_plt, &arm_plt))
        {
-         BFD_ASSERT (root_plt->refcount > 0);
-         root_plt->refcount -= 1;
+         /* If PLT refcount book-keeping is wrong and too low, we'll
+            see a zero value (going to -1) for the root PLT reference
+            count.  */
+         if (root_plt->refcount >= 0)
+           {
+             BFD_ASSERT (root_plt->refcount != 0);
+             root_plt->refcount -= 1;
+           }
+         else
+           /* A value of -1 means the symbol has become local, forced
+              or seeing a hidden definition.  Any other negative value
+              is an error.  */
+           BFD_ASSERT (root_plt->refcount == -1);
 
          if (!call_reloc_p)
            arm_plt->noncall_refcount--;
@@ -12112,7 +12434,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
   symtab_hdr = & elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
   nsyms = NUM_SHDR_ENTRIES (symtab_hdr);
-  
+
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -12184,14 +12506,14 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
              switch (r_type)
                {
                case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break;
-                 
+
                case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break;
-                 
+
                case R_ARM_TLS_GOTDESC:
                case R_ARM_TLS_CALL: case R_ARM_THM_TLS_CALL:
                case R_ARM_TLS_DESCSEQ: case R_ARM_THM_TLS_DESCSEQ:
                  tls_type = GOT_TLS_GDESC; break;
-                 
+
                default: tls_type = GOT_NORMAL; break;
                }
 
@@ -12380,7 +12702,8 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
          /* If the symbol is a function that doesn't bind locally,
             this relocation will need a PLT entry.  */
-         root_plt->refcount += 1;
+         if (root_plt->refcount != -1)
+           root_plt->refcount += 1;
 
          if (!call_reloc_p)
            arm_plt->noncall_refcount++;
@@ -12593,9 +12916,10 @@ elf32_arm_find_nearest_line (bfd *          abfd,
 
   /* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it.  */
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
+                                     section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
+                                    line_ptr, NULL, 0,
                                     & elf_tdata (abfd)->dwarf2_find_line_info))
     {
       if (!*functionname_ptr)
@@ -12740,13 +13064,6 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
   if (info->shared || globals->root.is_relocatable_executable)
     return TRUE;
 
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                            h->root.root.string);
-      return TRUE;
-    }
-
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -12756,18 +13073,18 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
      determine the address it must put in the global offset table, so
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
-  s = bfd_get_section_by_name (dynobj, ".dynbss");
+  s = bfd_get_linker_section (dynobj, ".dynbss");
   BFD_ASSERT (s != NULL);
 
   /* We must generate a R_ARM_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rel(a).bss section we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       asection *srel;
 
-      srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (globals, ".bss"));
+      srel = bfd_get_linker_section (dynobj, RELOC_SECTION (globals, ".bss"));
       elf32_arm_allocate_dynrelocs (info, srel, 1);
       h->needs_copy = 1;
     }
@@ -12957,7 +13274,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
              if (tls_type & GOT_TLS_GD)
                elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
 
-             if (tls_type & GOT_TLS_GDESC) 
+             if (tls_type & GOT_TLS_GDESC)
                {
                  elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1);
                  /* GDESC needs a trampoline to jump to.  */
@@ -12966,7 +13283,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
 
              /* Only GD needs it.  GDESC just emits one relocation per
                 2 entries.  */
-             if ((tls_type & GOT_TLS_GD) && indx != 0)  
+             if ((tls_type & GOT_TLS_GD) && indx != 0)
                elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
            }
          else if (!SYMBOL_REFERENCES_LOCAL (info, h))
@@ -13209,7 +13526,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
       /* Set the contents of the .interp section to the interpreter.  */
       if (info->executable)
        {
-         s = bfd_get_section_by_name (dynobj, ".interp");
+         s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
          s->size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -13421,10 +13738,10 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
     {
       if (htab->root.splt->size == 0)
        htab->root.splt->size += htab->plt_header_size;
-      
+
       htab->tls_trampoline = htab->root.splt->size;
       htab->root.splt->size += htab->plt_entry_size;
-      
+
       /* If we're not using lazy TLS relocations, don't generate the
          PLT and GOT entries they require.  */
       if (!(info->flags & DF_BIND_NOW))
@@ -13532,9 +13849,9 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
            return FALSE;
 
          if (htab->dt_tlsdesc_plt &&
-               (!add_dynamic_entry (DT_TLSDESC_PLT,0) 
+               (!add_dynamic_entry (DT_TLSDESC_PLT,0)
                 || !add_dynamic_entry (DT_TLSDESC_GOT,0)))
-           return FALSE; 
+           return FALSE;
        }
 
       if (relocs)
@@ -13607,7 +13924,7 @@ elf32_arm_always_size_sections (bfd *output_bfd,
                 tls_sec, 0, NULL, FALSE,
                 bed->collect, &bh)))
            return FALSE;
-         
+
          tlsbase->type = STT_TLS;
           tlsbase = (struct elf_link_hash_entry *)bh;
           tlsbase->def_regular = 1;
@@ -13695,7 +14012,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  On VxWorks,
      the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it is relative
      to the ".got" section.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+  if (h == htab->root.hdynamic
       || (!htab->vxworks_p && h == htab->root.hgot))
     sym->st_shndx = SHN_ABS;
 
@@ -13708,7 +14025,7 @@ arm_put_trampoline (struct elf32_arm_link_hash_table *htab, bfd *output_bfd,
                    const unsigned long *template, unsigned count)
 {
   unsigned ix;
-  
+
   for (ix = 0; ix != count; ix++)
     {
       unsigned long insn = template[ix];
@@ -13741,7 +14058,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
      Catch this here so that we do not seg-fault later on.  */
   if (sgot != NULL && bfd_is_abs_section (sgot->output_section))
     return FALSE;
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
@@ -13799,7 +14116,14 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
              name = RELOC_SECTION (htab, ".plt");
            get_vma:
              s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
+             if (s == NULL)
+               {
+                 /* PR ld/14397: Issue an error message if a required section is missing.  */
+                 (*_bfd_error_handler)
+                   (_("error: required section '%s' not found in the linker script"), name);
+                 bfd_set_error (bfd_error_invalid_operation);
+                 return FALSE;
+               }
              if (!htab->symbian_p)
                dyn.d_un.d_ptr = s->vma;
              else
@@ -13950,6 +14274,25 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
              SWAP_RELOC_OUT (htab) (output_bfd, &rel,
                                     htab->srelplt2->contents);
            }
+         else if (htab->nacl_p)
+           {
+             unsigned int i;
+
+             got_displacement = got_address + 8 - (plt_address + 16);
+
+             put_arm_insn (htab, output_bfd,
+                           elf32_arm_nacl_plt0_entry[0]
+                           | arm_movw_immediate (got_displacement),
+                           splt->contents + 0);
+             put_arm_insn (htab, output_bfd,
+                           elf32_arm_nacl_plt0_entry[1]
+                           | arm_movt_immediate (got_displacement),
+                           splt->contents + 4);
+             for (i = 2; i < ARRAY_SIZE (elf32_arm_nacl_plt0_entry); ++i)
+               put_arm_insn (htab, output_bfd,
+                             elf32_arm_nacl_plt0_entry[i],
+                             splt->contents + (i * 4));
+           }
          else
            {
              got_displacement = got_address - (plt_address + 16);
@@ -13988,7 +14331,7 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
          bfd_vma plt_address
            = splt->output_section->vma + splt->output_offset;
 
-         arm_put_trampoline (htab, output_bfd, 
+         arm_put_trampoline (htab, output_bfd,
                              splt->contents + htab->dt_tlsdesc_plt,
                              dl_tlsdesc_lazy_trampoline, 6);
 
@@ -14005,13 +14348,13 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info
 
       if (htab->tls_trampoline)
        {
-         arm_put_trampoline (htab, output_bfd, 
+         arm_put_trampoline (htab, output_bfd,
                              splt->contents + htab->tls_trampoline,
                              tls_trampoline, 3);
 #ifdef FOUR_WORD_PLT
          bfd_put_32 (output_bfd, 0x00000000,
                      splt->contents + htab->tls_trampoline + 12);
-#endif 
+#endif
        }
 
       if (htab->vxworks_p && !info->shared && htab->root.splt->size > 0)
@@ -14083,6 +14426,16 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT
       if (globals != NULL && globals->byteswap_code)
        i_ehdrp->e_flags |= EF_ARM_BE8;
     }
+
+  if (EF_ARM_EABI_VERSION (i_ehdrp->e_flags) == EF_ARM_EABI_VER5
+      && ((i_ehdrp->e_type == ET_DYN) || (i_ehdrp->e_type == ET_EXEC)))
+    {
+      int abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_ABI_VFP_args);
+      if (abi)
+       i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_HARD;
+      else
+       i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_SOFT;
+    }
 }
 
 static enum elf_reloc_type_class
@@ -14101,17 +14454,6 @@ elf32_arm_reloc_type_class (const Elf_Internal_Rela *rela)
     }
 }
 
-/* Set the right machine number for an Arm ELF file.  */
-
-static bfd_boolean
-elf32_arm_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
-{
-  if (hdr->sh_type == SHT_NOTE)
-    *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
-
-  return TRUE;
-}
-
 static void
 elf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
 {
@@ -14189,7 +14531,7 @@ get_arm_elf_section_data (asection * sec)
 
 typedef struct
 {
-  void *finfo;
+  void *flaginfo;
   struct bfd_link_info *info;
   asection *sec;
   int sec_shndx;
@@ -14224,7 +14566,7 @@ elf32_arm_output_map_sym (output_arch_syminfo *osi,
   sym.st_shndx = osi->sec_shndx;
   sym.st_target_internal = 0;
   elf32_arm_section_map_add (osi->sec, names[type][1], offset);
-  return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1;
+  return osi->func (osi->flaginfo, names[type], &sym, osi->sec, NULL) == 1;
 }
 
 /* Output mapping symbols for the PLT entry described by ROOT_PLT and ARM_PLT.
@@ -14278,6 +14620,11 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi,
       if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 20))
        return FALSE;
     }
+  else if (htab->nacl_p)
+    {
+      if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
+       return FALSE;
+    }
   else
     {
       bfd_boolean thumb_stub_p;
@@ -14346,7 +14693,7 @@ elf32_arm_output_stub_sym (output_arch_syminfo *osi, const char *name,
   sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
   sym.st_shndx = osi->sec_shndx;
   sym.st_target_internal = 0;
-  return osi->func (osi->finfo, name, &sym, osi->sec, NULL) == 1;
+  return osi->func (osi->flaginfo, name, &sym, osi->sec, NULL) == 1;
 }
 
 static bfd_boolean
@@ -14458,7 +14805,7 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
 static bfd_boolean
 elf32_arm_output_arch_local_syms (bfd *output_bfd,
                                  struct bfd_link_info *info,
-                                 void *finfo,
+                                 void *flaginfo,
                                  int (*func) (void *, const char *,
                                               Elf_Internal_Sym *,
                                               asection *,
@@ -14476,7 +14823,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
 
   check_use_blx (htab);
 
-  osi.finfo = finfo;
+  osi.flaginfo = flaginfo;
   osi.info = info;
   osi.func = func;
 
@@ -14499,7 +14846,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
                   == SEC_HAS_CONTENTS
                && get_arm_elf_section_data (osi.sec) != NULL
                && get_arm_elf_section_data (osi.sec)->mapcount == 0
-               && osi.sec->size > 0)
+               && osi.sec->size > 0
+               && (osi.sec->flags & SEC_EXCLUDE) == 0)
              {
                osi.sec_shndx = _bfd_elf_section_from_bfd_section
                  (output_bfd, osi.sec->output_section);
@@ -14512,8 +14860,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
   /* ARM->Thumb glue.  */
   if (htab->arm_glue_size > 0)
     {
-      osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner,
-                                        ARM2THUMB_GLUE_SECTION_NAME);
+      osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner,
+                                       ARM2THUMB_GLUE_SECTION_NAME);
 
       osi.sec_shndx = _bfd_elf_section_from_bfd_section
          (output_bfd, osi.sec->output_section);
@@ -14535,8 +14883,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
   /* Thumb->ARM glue.  */
   if (htab->thumb_glue_size > 0)
     {
-      osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner,
-                                        THUMB2ARM_GLUE_SECTION_NAME);
+      osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner,
+                                       THUMB2ARM_GLUE_SECTION_NAME);
 
       osi.sec_shndx = _bfd_elf_section_from_bfd_section
          (output_bfd, osi.sec->output_section);
@@ -14552,8 +14900,8 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
   /* ARMv4 BX veneers.  */
   if (htab->bx_glue_size > 0)
     {
-      osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner,
-                                        ARM_BX_GLUE_SECTION_NAME);
+      osi.sec = bfd_get_linker_section (htab->bfd_of_glue_owner,
+                                       ARM_BX_GLUE_SECTION_NAME);
 
       osi.sec_shndx = _bfd_elf_section_from_bfd_section
          (output_bfd, osi.sec->output_section);
@@ -14603,6 +14951,11 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
                return FALSE;
            }
        }
+      else if (htab->nacl_p)
+       {
+         if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
+           return FALSE;
+       }
       else if (!htab->symbian_p)
        {
          if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
@@ -14642,7 +14995,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
       /* Mapping symbols for the lazy tls trampoline.  */
       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, htab->dt_tlsdesc_plt))
        return FALSE;
-       
+
       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
                                     htab->dt_tlsdesc_plt + 24))
        return FALSE;
@@ -14656,9 +15009,9 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd,
       if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA,
                                     htab->tls_trampoline + 12))
        return FALSE;
-#endif 
+#endif
     }
-  
+
   return TRUE;
 }
 
@@ -14721,23 +15074,24 @@ copy_exidx_entry (bfd *output_bfd, bfd_byte *to, bfd_byte *from, bfd_vma offset)
 {
   unsigned long first_word = bfd_get_32 (output_bfd, from);
   unsigned long second_word = bfd_get_32 (output_bfd, from + 4);
-  
+
   /* High bit of first word is supposed to be zero.  */
   if ((first_word & 0x80000000ul) == 0)
     first_word = offset_prel31 (first_word, offset);
-  
+
   /* If the high bit of the first word is clear, and the bit pattern is not 0x1
      (EXIDX_CANTUNWIND), this is an offset to an .ARM.extab entry.  */
   if ((second_word != 0x1) && ((second_word & 0x80000000ul) == 0))
     second_word = offset_prel31 (second_word, offset);
-  
+
   bfd_put_32 (output_bfd, first_word, to);
   bfd_put_32 (output_bfd, second_word, to + 4);
 }
 
 /* Data for make_branch_to_a8_stub().  */
 
-struct a8_branch_to_stub_data {
+struct a8_branch_to_stub_data
+{
   asection *writing_section;
   bfd_byte *contents;
 };
@@ -14975,7 +15329,7 @@ elf32_arm_write_section (bfd *output_bfd,
          if (edit_node)
            {
              unsigned int edit_index = edit_node->index;
-             
+
              if (in_index < edit_index && in_index * 8 < input_size)
                {
                  copy_exidx_entry (output_bfd, edited_contents + out_index * 8,
@@ -14993,7 +15347,7 @@ elf32_arm_write_section (bfd *output_bfd,
                      in_index++;
                      add_to_offsets += 8;
                      break;
-                   
+
                    case INSERT_EXIDX_CANTUNWIND_AT_END:
                      {
                        asection *text_sec = edit_node->linked_section;
@@ -15023,7 +15377,7 @@ elf32_arm_write_section (bfd *output_bfd,
                      }
                      break;
                    }
-                 
+
                  edit_node = edit_node->next;
                }
            }
@@ -15313,7 +15667,7 @@ const struct elf_size_info elf32_arm_size_info =
 #define bfd_elf32_bfd_link_hash_table_create    elf32_arm_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_free      elf32_arm_hash_table_free
 #define bfd_elf32_bfd_reloc_type_lookup                elf32_arm_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_name_lookup        elf32_arm_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup                elf32_arm_reloc_name_lookup
 #define bfd_elf32_find_nearest_line            elf32_arm_find_nearest_line
 #define bfd_elf32_find_inliner_info            elf32_arm_find_inliner_info
 #define bfd_elf32_new_section_hook             elf32_arm_new_section_hook
@@ -15337,7 +15691,6 @@ const struct elf_size_info elf32_arm_size_info =
 #define elf_backend_post_process_headers       elf32_arm_post_process_headers
 #define elf_backend_reloc_type_class           elf32_arm_reloc_type_class
 #define elf_backend_object_p                   elf32_arm_object_p
-#define elf_backend_section_flags              elf32_arm_section_flags
 #define elf_backend_fake_sections              elf32_arm_fake_sections
 #define elf_backend_section_from_shdr                  elf32_arm_section_from_shdr
 #define elf_backend_final_write_processing      elf32_arm_final_write_processing
@@ -15368,11 +15721,78 @@ const struct elf_size_info elf32_arm_size_info =
 #define elf_backend_obj_attrs_arg_type         elf32_arm_obj_attrs_arg_type
 #undef  elf_backend_obj_attrs_section_type
 #define elf_backend_obj_attrs_section_type     SHT_ARM_ATTRIBUTES
-#define elf_backend_obj_attrs_order    elf32_arm_obj_attrs_order
-#define elf_backend_obj_attrs_handle_unknown elf32_arm_obj_attrs_handle_unknown
+#define elf_backend_obj_attrs_order            elf32_arm_obj_attrs_order
+#define elf_backend_obj_attrs_handle_unknown   elf32_arm_obj_attrs_handle_unknown
+
+#include "elf32-target.h"
+
+/* Native Client targets.  */
+
+#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM              bfd_elf32_littlearm_nacl_vec
+#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME             "elf32-littlearm-nacl"
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM                 bfd_elf32_bigarm_nacl_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME                        "elf32-bigarm-nacl"
+
+/* Like elf32_arm_link_hash_table_create -- but overrides
+   appropriately for NaCl.  */
+
+static struct bfd_link_hash_table *
+elf32_arm_nacl_link_hash_table_create (bfd *abfd)
+{
+  struct bfd_link_hash_table *ret;
+
+  ret = elf32_arm_link_hash_table_create (abfd);
+  if (ret)
+    {
+      struct elf32_arm_link_hash_table *htab
+       = (struct elf32_arm_link_hash_table *) ret;
+
+      htab->nacl_p = 1;
+
+      htab->plt_header_size = 4 * ARRAY_SIZE (elf32_arm_nacl_plt0_entry);
+      htab->plt_entry_size = 4 * ARRAY_SIZE (elf32_arm_nacl_plt_entry);
+    }
+  return ret;
+}
+
+/* Since NaCl doesn't use the ARM-specific unwind format, we don't
+   really need to use elf32_arm_modify_segment_map.  But we do it
+   anyway just to reduce gratuitous differences with the stock ARM backend.  */
+
+static bfd_boolean
+elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
+{
+  return (elf32_arm_modify_segment_map (abfd, info)
+         && nacl_modify_segment_map (abfd, info));
+}
+
+#undef elf32_bed
+#define elf32_bed                      elf32_arm_nacl_bed
+#undef  bfd_elf32_bfd_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_create   \
+  elf32_arm_nacl_link_hash_table_create
+#undef elf_backend_plt_alignment
+#define elf_backend_plt_alignment      4
+#undef elf_backend_modify_segment_map
+#define        elf_backend_modify_segment_map          elf32_arm_nacl_modify_segment_map
+#undef elf_backend_modify_program_headers
+#define        elf_backend_modify_program_headers      nacl_modify_program_headers
+
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE                        0x10000
 
 #include "elf32-target.h"
 
+/* Reset to defaults.  */
+#undef elf_backend_plt_alignment
+#undef elf_backend_modify_segment_map
+#define elf_backend_modify_segment_map         elf32_arm_modify_segment_map
+#undef elf_backend_modify_program_headers
+
 /* VxWorks Targets.  */
 
 #undef  TARGET_LITTLE_SYM
This page took 0.109527 seconds and 4 git commands to generate.