Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2354)

Unified Diff: bfd/elf32-arm.c

Issue 11969036: Merge GDB 7.5.1 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@master
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « bfd/elf32-am33lin.c ('k') | bfd/elf32-avr.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: bfd/elf32-arm.c
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 31ea8610dd21f5d0367912548a523347559ec827..bc1f19532cde4d5a48f7c88430ccdf8a7931cd3a 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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.
@@ -23,9 +23,11 @@
#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"
@@ -1988,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
@@ -1995,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;
@@ -2029,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
@@ -2055,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
@@ -2079,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)
@@ -2154,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
@@ -2173,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. */
@@ -2329,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
@@ -2364,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
@@ -2405,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 */
@@ -2420,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
};
@@ -2573,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;
@@ -2587,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;
@@ -2602,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;
@@ -2625,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;
@@ -2686,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
@@ -2701,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) \
@@ -2829,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;
@@ -2853,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;
@@ -3149,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);
@@ -3157,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;
@@ -3205,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)
{
@@ -3359,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;
@@ -3527,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
@@ -3811,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 *
@@ -3849,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;
}
@@ -3920,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);
@@ -3928,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:
@@ -3974,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. */
}
@@ -4512,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;
@@ -4947,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)
@@ -4979,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)
{
@@ -5524,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 */
@@ -5554,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;
}
@@ -5563,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);
@@ -5619,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);
@@ -5695,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);
@@ -5786,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);
@@ -5893,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))
@@ -5963,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)
@@ -6583,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;
@@ -6918,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);
@@ -7108,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);
@@ -7162,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);
@@ -7197,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);
@@ -7354,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
@@ -7514,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
@@ -7654,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;
@@ -7721,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);
@@ -7767,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)
@@ -7779,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;
@@ -9200,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);
@@ -9243,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;
@@ -9261,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)
{
@@ -9387,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;
@@ -9402,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))
{
@@ -9438,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);
@@ -9479,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"),
@@ -9488,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
@@ -9514,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);
@@ -10222,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
@@ -10331,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)
{
@@ -10387,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)))
{
@@ -10399,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,
@@ -10495,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;
@@ -10557,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).
@@ -10565,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,
@@ -10585,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
@@ -10655,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))
@@ -10713,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);
@@ -10734,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;
@@ -10807,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
@@ -10816,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;
}
@@ -11219,6 +11408,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. */
@@ -11660,29 +11889,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:
@@ -11694,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;
}
@@ -12074,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--;
@@ -12168,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++)
{
@@ -12240,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;
}
@@ -12436,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++;
@@ -12797,13 +13031,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
@@ -12813,18 +13040,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;
}
@@ -13014,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. */
@@ -13023,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))
@@ -13266,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;
@@ -13478,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))
@@ -13589,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)
@@ -13664,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;
@@ -13765,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];
@@ -13798,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)
{
@@ -14007,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);
@@ -14045,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);
@@ -14062,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)
@@ -14235,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;
@@ -14270,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.
@@ -14324,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;
@@ -14392,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
@@ -14504,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 *,
@@ -14522,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;
@@ -14559,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);
@@ -14582,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);
@@ -14599,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);
@@ -14650,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))
@@ -14689,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;
@@ -14703,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;
}
@@ -14768,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;
};
@@ -15022,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,
@@ -15040,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;
@@ -15070,7 +15327,7 @@ elf32_arm_write_section (bfd *output_bfd,
}
break;
}
-
+
edit_node = edit_node->next;
}
}
@@ -15360,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
@@ -15414,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
« no previous file with comments | « bfd/elf32-am33lin.c ('k') | bfd/elf32-avr.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698