| 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
|
|
|