daily update
[deliverable/binutils-gdb.git] / bfd / elf32-arm.c
index 8721f949b0369a01e676918d9d37c796468ce066..bc1f19532cde4d5a48f7c88430ccdf8a7931cd3a 100644 (file)
 #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"
 
@@ -2078,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
 
@@ -2104,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
 
@@ -2128,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)
@@ -2203,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
@@ -2222,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.  */
@@ -2378,32 +2419,32 @@ 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
@@ -2413,7 +2454,7 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
    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
@@ -2454,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 */
@@ -2469,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
 };
@@ -2622,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;
@@ -2636,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;
@@ -2651,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;
@@ -2674,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;
@@ -2735,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
@@ -2750,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)                        \
@@ -2878,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;
 
@@ -2902,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;
@@ -3198,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);
@@ -3206,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;
@@ -3254,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)
     {
@@ -3408,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;
@@ -3576,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
@@ -3860,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 *
@@ -3898,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;
 }
 
@@ -3969,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);
@@ -3977,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:
@@ -4023,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.  */
     }
@@ -4561,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;
 
@@ -4996,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)
@@ -5028,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)
                    {
@@ -5573,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  */
 
@@ -5603,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;
        }
@@ -5612,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);
@@ -5668,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);
@@ -5744,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);
@@ -5835,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);
@@ -5942,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))
@@ -6012,7 +6064,7 @@ check_use_blx (struct elf32_arm_link_hash_table *globals)
 {
   int cpu_arch;
 
-  cpu_arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, 
+  cpu_arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC,
                                       Tag_CPU_arch);
 
   if (globals->fix_arm1176)
@@ -6632,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;
@@ -6967,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);
@@ -7157,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);
@@ -7211,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);
@@ -7246,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);
@@ -7403,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
@@ -7563,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
@@ -7703,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;
@@ -7770,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);
@@ -7816,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)
@@ -7828,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;
@@ -9249,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);
 
@@ -9292,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;
@@ -9310,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)
              {
@@ -9436,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;
@@ -9451,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))
                  {
@@ -9487,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);
@@ -9528,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"),
@@ -9537,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
@@ -9563,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);
@@ -10271,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
@@ -10380,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)
        {
@@ -10436,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)))
        {
@@ -10448,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,
@@ -10544,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;
@@ -10606,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).
@@ -10614,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,
@@ -10634,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
@@ -10704,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))
@@ -10762,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);
 
@@ -10783,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;
 
@@ -10856,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
@@ -10865,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;
 }
 
@@ -11776,7 +11916,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;
                }
@@ -12156,8 +12296,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--;
@@ -12250,7 +12401,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++)
     {
@@ -12322,14 +12473,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;
                }
 
@@ -12518,7 +12669,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++;
@@ -12888,7 +13040,7 @@ 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
@@ -12899,7 +13051,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
     {
       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;
     }
@@ -13089,7 +13241,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.  */
@@ -13098,7 +13250,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))
@@ -13341,7 +13493,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;
@@ -13553,10 +13705,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))
@@ -13664,9 +13816,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)
@@ -13739,7 +13891,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;
@@ -13840,7 +13992,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];
@@ -13873,7 +14025,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)
     {
@@ -14082,6 +14234,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);
@@ -14120,7 +14291,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);
 
@@ -14137,13 +14308,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)
@@ -14310,7 +14481,7 @@ get_arm_elf_section_data (asection * sec)
 
 typedef struct
 {
-  void *finfo;
+  void *flaginfo;
   struct bfd_link_info *info;
   asection *sec;
   int sec_shndx;
@@ -14345,7 +14516,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.
@@ -14399,6 +14570,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;
@@ -14467,7 +14643,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
@@ -14579,7 +14755,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 *,
@@ -14597,7 +14773,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;
 
@@ -14634,8 +14810,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);
@@ -14657,8 +14833,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);
@@ -14674,8 +14850,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);
@@ -14725,6 +14901,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))
@@ -14764,7 +14945,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;
@@ -14778,9 +14959,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;
 }
 
@@ -14843,23 +15024,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;
 };
@@ -15097,7 +15279,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,
@@ -15115,7 +15297,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;
@@ -15145,7 +15327,7 @@ elf32_arm_write_section (bfd *output_bfd,
                      }
                      break;
                    }
-                 
+
                  edit_node = edit_node->next;
                }
            }
@@ -15435,7 +15617,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
@@ -15489,11 +15671,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.057776 seconds and 4 git commands to generate.