blob: bc1f19532cde4d5a48f7c88430ccdf8a7931cd3a [file] [log] [blame]
/* 32-bit ELF support for ARM
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "sysdep.h"
#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"
/* Return the relocation section associated with NAME. HTAB is the
bfd's elf32_arm_link_hash_entry. */
#define RELOC_SECTION(HTAB, NAME) \
((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)
/* Return size of a relocation entry. HTAB is the bfd's
elf32_arm_link_hash_entry. */
#define RELOC_SIZE(HTAB) \
((HTAB)->use_rel \
? sizeof (Elf32_External_Rel) \
: sizeof (Elf32_External_Rela))
/* Return function to swap relocations in. HTAB is the bfd's
elf32_arm_link_hash_entry. */
#define SWAP_RELOC_IN(HTAB) \
((HTAB)->use_rel \
? bfd_elf32_swap_reloc_in \
: bfd_elf32_swap_reloca_in)
/* Return function to swap relocations out. HTAB is the bfd's
elf32_arm_link_hash_entry. */
#define SWAP_RELOC_OUT(HTAB) \
((HTAB)->use_rel \
? bfd_elf32_swap_reloc_out \
: bfd_elf32_swap_reloca_out)
#define elf_info_to_howto 0
#define elf_info_to_howto_rel elf32_arm_info_to_howto
#define ARM_ELF_ABI_VERSION 0
#define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM
static bfd_boolean elf32_arm_write_section (bfd *output_bfd,
struct bfd_link_info *link_info,
asection *sec,
bfd_byte *contents);
/* Note: code such as elf32_arm_reloc_type_lookup expect to use e.g.
R_ARM_PC24 as an index into this, and find the R_ARM_PC24 HOWTO
in that slot. */
static reloc_howto_type elf32_arm_howto_table_1[] =
{
/* No relocation. */
HOWTO (R_ARM_NONE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_NONE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_PC24, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_PC24", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* 32 bit absolute */
HOWTO (R_ARM_ABS32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS32", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* standard 32bit pc-relative reloc */
HOWTO (R_ARM_REL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_REL32", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* 8 bit absolute - R_ARM_LDR_PC_G0 in AAELF */
HOWTO (R_ARM_LDR_PC_G0, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_PC_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* 16 bit absolute */
HOWTO (R_ARM_ABS16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS16", /* name */
FALSE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* 12 bit absolute */
HOWTO (R_ARM_ABS12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS12", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_ABS5, /* type */
6, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
5, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_ABS5", /* name */
FALSE, /* partial_inplace */
0x000007e0, /* src_mask */
0x000007e0, /* dst_mask */
FALSE), /* pcrel_offset */
/* 8 bit absolute */
HOWTO (R_ARM_ABS8, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS8", /* name */
FALSE, /* partial_inplace */
0x000000ff, /* src_mask */
0x000000ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_SBREL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_SBREL32", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_CALL, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_CALL", /* name */
FALSE, /* partial_inplace */
0x07ff2fff, /* src_mask */
0x07ff2fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_PC8, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_PC8", /* name */
FALSE, /* partial_inplace */
0x000000ff, /* src_mask */
0x000000ff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_BREL_ADJ, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_BREL_ADJ", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_DESC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_DESC", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_SWI8, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_SWI8", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
FALSE), /* pcrel_offset */
/* BLX instruction for the ARM. */
HOWTO (R_ARM_XPC25, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_XPC25", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* BLX instruction for the Thumb. */
HOWTO (R_ARM_THM_XPC22, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_XPC22", /* name */
FALSE, /* partial_inplace */
0x07ff2fff, /* src_mask */
0x07ff2fff, /* dst_mask */
TRUE), /* pcrel_offset */
/* Dynamic TLS relocations. */
HOWTO (R_ARM_TLS_DTPMOD32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_DTPMOD32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_DTPOFF32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_DTPOFF32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_TPOFF32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_TPOFF32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Relocs used in ARM Linux */
HOWTO (R_ARM_COPY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_COPY", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GLOB_DAT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GLOB_DAT", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_JUMP_SLOT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_JUMP_SLOT", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_RELATIVE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_RELATIVE", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GOTOFF32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOTOFF32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GOTPC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOTPC", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_GOT32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOT32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_PLT32, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_PLT32", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_CALL, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_CALL", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_JUMP24, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_JUMP24", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_JUMP24, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_JUMP24", /* name */
FALSE, /* partial_inplace */
0x07ff2fff, /* src_mask */
0x07ff2fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_BASE_ABS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_BASE_ABS", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PCREL7_0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PCREL_7_0", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PCREL15_8, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
TRUE, /* pc_relative */
8, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PCREL_15_8",/* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PCREL23_15, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
TRUE, /* pc_relative */
16, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PCREL_23_15",/* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_SBREL_11_0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_SBREL_11_0",/* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SBREL_19_12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
FALSE, /* pc_relative */
12, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SBREL_19_12",/* name */
FALSE, /* partial_inplace */
0x000ff000, /* src_mask */
0x000ff000, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SBREL_27_20, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
FALSE, /* pc_relative */
20, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SBREL_27_20",/* name */
FALSE, /* partial_inplace */
0x0ff00000, /* src_mask */
0x0ff00000, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TARGET1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TARGET1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_ROSEGREL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ROSEGREL32", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_V4BX, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_V4BX", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TARGET2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TARGET2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_PREL31, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
31, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_PREL31", /* name */
FALSE, /* partial_inplace */
0x7fffffff, /* src_mask */
0x7fffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_MOVW_ABS_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVW_ABS_NC", /* name */
FALSE, /* partial_inplace */
0x000f0fff, /* src_mask */
0x000f0fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_MOVT_ABS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVT_ABS", /* name */
FALSE, /* partial_inplace */
0x000f0fff, /* src_mask */
0x000f0fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_MOVW_PREL_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVW_PREL_NC", /* name */
FALSE, /* partial_inplace */
0x000f0fff, /* src_mask */
0x000f0fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_MOVT_PREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVT_PREL", /* name */
FALSE, /* partial_inplace */
0x000f0fff, /* src_mask */
0x000f0fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVW_ABS_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVW_ABS_NC",/* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVT_ABS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVT_ABS", /* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVW_PREL_NC,/* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVW_PREL_NC",/* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVT_PREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVT_PREL", /* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_JUMP19, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
19, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_JUMP19", /* name */
FALSE, /* partial_inplace */
0x043f2fff, /* src_mask */
0x043f2fff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_JUMP6, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
6, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_JUMP6", /* name */
FALSE, /* partial_inplace */
0x02f8, /* src_mask */
0x02f8, /* dst_mask */
TRUE), /* pcrel_offset */
/* These are declared as 13-bit signed relocations because we can
address -4095 .. 4095(base) by altering ADDW to SUBW or vice
versa. */
HOWTO (R_ARM_THM_ALU_PREL_11_0,/* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
13, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_ALU_PREL_11_0",/* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_PC12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
13, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_PC12", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ABS32_NOI, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ABS32_NOI", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_REL32_NOI, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_REL32_NOI", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Group relocations. */
HOWTO (R_ARM_ALU_PC_G0_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PC_G0_NC", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PC_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PC_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PC_G1_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PC_G1_NC", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PC_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PC_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_PC_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_PC_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_PC_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_PC_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_PC_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_PC_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_PC_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_PC_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_PC_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_PC_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_PC_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_PC_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_PC_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_PC_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_PC_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_PC_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_PC_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_PC_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SB_G0_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SB_G0_NC", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SB_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SB_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SB_G1_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SB_G1_NC", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SB_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SB_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_ALU_SB_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_ALU_SB_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_SB_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_SB_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_SB_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_SB_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDR_SB_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDR_SB_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_SB_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_SB_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_SB_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_SB_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDRS_SB_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDRS_SB_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_SB_G0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_SB_G0", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_SB_G1, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_SB_G1", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_LDC_SB_G2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_LDC_SB_G2", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* End of group relocations. */
HOWTO (R_ARM_MOVW_BREL_NC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVW_BREL_NC", /* name */
FALSE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_MOVT_BREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVT_BREL", /* name */
FALSE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_MOVW_BREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_MOVW_BREL", /* name */
FALSE, /* partial_inplace */
0x0000ffff, /* src_mask */
0x0000ffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVW_BREL_NC,/* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVW_BREL_NC",/* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVT_BREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVT_BREL", /* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_MOVW_BREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_MOVW_BREL", /* name */
FALSE, /* partial_inplace */
0x040f70ff, /* src_mask */
0x040f70ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_GOTDESC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
NULL, /* special_function */
"R_ARM_TLS_GOTDESC", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_CALL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_CALL", /* name */
FALSE, /* partial_inplace */
0x00ffffff, /* src_mask */
0x00ffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_DESCSEQ, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_DESCSEQ", /* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_TLS_CALL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
24, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_TLS_CALL", /* name */
FALSE, /* partial_inplace */
0x07ff07ff, /* src_mask */
0x07ff07ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_PLT32_ABS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_PLT32_ABS", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GOT_ABS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOT_ABS", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GOT_PREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOT_PREL", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_GOT_BREL12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOT_BREL12", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_GOTOFF12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOTOFF12", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
EMPTY_HOWTO (R_ARM_GOTRELAX), /* reserved for future GOT-load optimizations */
/* GNU extension to record C++ vtable member usage */
HOWTO (R_ARM_GNU_VTENTRY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
_bfd_elf_rel_vtable_reloc_fn, /* special_function */
"R_ARM_GNU_VTENTRY", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
/* GNU extension to record C++ vtable hierarchy */
HOWTO (R_ARM_GNU_VTINHERIT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
NULL, /* special_function */
"R_ARM_GNU_VTINHERIT", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_THM_JUMP11, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
11, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_JUMP11", /* name */
FALSE, /* partial_inplace */
0x000007ff, /* src_mask */
0x000007ff, /* dst_mask */
TRUE), /* pcrel_offset */
HOWTO (R_ARM_THM_JUMP8, /* type */
1, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
TRUE, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_JUMP8", /* name */
FALSE, /* partial_inplace */
0x000000ff, /* src_mask */
0x000000ff, /* dst_mask */
TRUE), /* pcrel_offset */
/* TLS relocations */
HOWTO (R_ARM_TLS_GD32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
NULL, /* special_function */
"R_ARM_TLS_GD32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LDM32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LDM32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LDO32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LDO32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_IE32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
NULL, /* special_function */
"R_ARM_TLS_IE32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LE32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LE32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LDO12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LDO12", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_LE12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LE12", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_TLS_IE12GP, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_IE12GP", /* name */
FALSE, /* partial_inplace */
0x00000fff, /* src_mask */
0x00000fff, /* dst_mask */
FALSE), /* pcrel_offset */
/* 112-127 private relocations. */
EMPTY_HOWTO (112),
EMPTY_HOWTO (113),
EMPTY_HOWTO (114),
EMPTY_HOWTO (115),
EMPTY_HOWTO (116),
EMPTY_HOWTO (117),
EMPTY_HOWTO (118),
EMPTY_HOWTO (119),
EMPTY_HOWTO (120),
EMPTY_HOWTO (121),
EMPTY_HOWTO (122),
EMPTY_HOWTO (123),
EMPTY_HOWTO (124),
EMPTY_HOWTO (125),
EMPTY_HOWTO (126),
EMPTY_HOWTO (127),
/* R_ARM_ME_TOO, obsolete. */
EMPTY_HOWTO (128),
HOWTO (R_ARM_THM_TLS_DESCSEQ, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_THM_TLS_DESCSEQ",/* name */
FALSE, /* partial_inplace */
0x00000000, /* src_mask */
0x00000000, /* dst_mask */
FALSE), /* pcrel_offset */
};
/* 160 onwards: */
static reloc_howto_type elf32_arm_howto_table_2[1] =
{
HOWTO (R_ARM_IRELATIVE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_IRELATIVE", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE) /* pcrel_offset */
};
/* 249-255 extended, currently unused, relocations: */
static reloc_howto_type elf32_arm_howto_table_3[4] =
{
HOWTO (R_ARM_RREL32, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_RREL32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_RABS32, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_RABS32", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_RPC24, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_RPC24", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_ARM_RBASE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_RBASE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
FALSE) /* pcrel_offset */
};
static reloc_howto_type *
elf32_arm_howto_from_type (unsigned int r_type)
{
if (r_type < ARRAY_SIZE (elf32_arm_howto_table_1))
return &elf32_arm_howto_table_1[r_type];
if (r_type == R_ARM_IRELATIVE)
return &elf32_arm_howto_table_2[r_type - R_ARM_IRELATIVE];
if (r_type >= R_ARM_RREL32
&& r_type < R_ARM_RREL32 + ARRAY_SIZE (elf32_arm_howto_table_3))
return &elf32_arm_howto_table_3[r_type - R_ARM_RREL32];
return NULL;
}
static void
elf32_arm_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc,
Elf_Internal_Rela * elf_reloc)
{
unsigned int r_type;
r_type = ELF32_R_TYPE (elf_reloc->r_info);
bfd_reloc->howto = elf32_arm_howto_from_type (r_type);
}
struct elf32_arm_reloc_map
{
bfd_reloc_code_real_type bfd_reloc_val;
unsigned char elf_reloc_val;
};
/* All entries in this list must also be present in elf32_arm_howto_table. */
static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{
{BFD_RELOC_NONE, R_ARM_NONE},
{BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24},
{BFD_RELOC_ARM_PCREL_CALL, R_ARM_CALL},
{BFD_RELOC_ARM_PCREL_JUMP, R_ARM_JUMP24},
{BFD_RELOC_ARM_PCREL_BLX, R_ARM_XPC25},
{BFD_RELOC_THUMB_PCREL_BLX, R_ARM_THM_XPC22},
{BFD_RELOC_32, R_ARM_ABS32},
{BFD_RELOC_32_PCREL, R_ARM_REL32},
{BFD_RELOC_8, R_ARM_ABS8},
{BFD_RELOC_16, R_ARM_ABS16},
{BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12},
{BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5},
{BFD_RELOC_THUMB_PCREL_BRANCH25, R_ARM_THM_JUMP24},
{BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_CALL},
{BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_JUMP11},
{BFD_RELOC_THUMB_PCREL_BRANCH20, R_ARM_THM_JUMP19},
{BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_JUMP8},
{BFD_RELOC_THUMB_PCREL_BRANCH7, R_ARM_THM_JUMP6},
{BFD_RELOC_ARM_GLOB_DAT, R_ARM_GLOB_DAT},
{BFD_RELOC_ARM_JUMP_SLOT, R_ARM_JUMP_SLOT},
{BFD_RELOC_ARM_RELATIVE, R_ARM_RELATIVE},
{BFD_RELOC_ARM_GOTOFF, R_ARM_GOTOFF32},
{BFD_RELOC_ARM_GOTPC, R_ARM_GOTPC},
{BFD_RELOC_ARM_GOT_PREL, R_ARM_GOT_PREL},
{BFD_RELOC_ARM_GOT32, R_ARM_GOT32},
{BFD_RELOC_ARM_PLT32, R_ARM_PLT32},
{BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1},
{BFD_RELOC_ARM_ROSEGREL32, R_ARM_ROSEGREL32},
{BFD_RELOC_ARM_SBREL32, R_ARM_SBREL32},
{BFD_RELOC_ARM_PREL31, R_ARM_PREL31},
{BFD_RELOC_ARM_TARGET2, R_ARM_TARGET2},
{BFD_RELOC_ARM_PLT32, R_ARM_PLT32},
{BFD_RELOC_ARM_TLS_GOTDESC, R_ARM_TLS_GOTDESC},
{BFD_RELOC_ARM_TLS_CALL, R_ARM_TLS_CALL},
{BFD_RELOC_ARM_THM_TLS_CALL, R_ARM_THM_TLS_CALL},
{BFD_RELOC_ARM_TLS_DESCSEQ, R_ARM_TLS_DESCSEQ},
{BFD_RELOC_ARM_THM_TLS_DESCSEQ, R_ARM_THM_TLS_DESCSEQ},
{BFD_RELOC_ARM_TLS_DESC, R_ARM_TLS_DESC},
{BFD_RELOC_ARM_TLS_GD32, R_ARM_TLS_GD32},
{BFD_RELOC_ARM_TLS_LDO32, R_ARM_TLS_LDO32},
{BFD_RELOC_ARM_TLS_LDM32, R_ARM_TLS_LDM32},
{BFD_RELOC_ARM_TLS_DTPMOD32, R_ARM_TLS_DTPMOD32},
{BFD_RELOC_ARM_TLS_DTPOFF32, R_ARM_TLS_DTPOFF32},
{BFD_RELOC_ARM_TLS_TPOFF32, R_ARM_TLS_TPOFF32},
{BFD_RELOC_ARM_TLS_IE32, R_ARM_TLS_IE32},
{BFD_RELOC_ARM_TLS_LE32, R_ARM_TLS_LE32},
{BFD_RELOC_ARM_IRELATIVE, R_ARM_IRELATIVE},
{BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT},
{BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY},
{BFD_RELOC_ARM_MOVW, R_ARM_MOVW_ABS_NC},
{BFD_RELOC_ARM_MOVT, R_ARM_MOVT_ABS},
{BFD_RELOC_ARM_MOVW_PCREL, R_ARM_MOVW_PREL_NC},
{BFD_RELOC_ARM_MOVT_PCREL, R_ARM_MOVT_PREL},
{BFD_RELOC_ARM_THUMB_MOVW, R_ARM_THM_MOVW_ABS_NC},
{BFD_RELOC_ARM_THUMB_MOVT, R_ARM_THM_MOVT_ABS},
{BFD_RELOC_ARM_THUMB_MOVW_PCREL, R_ARM_THM_MOVW_PREL_NC},
{BFD_RELOC_ARM_THUMB_MOVT_PCREL, R_ARM_THM_MOVT_PREL},
{BFD_RELOC_ARM_ALU_PC_G0_NC, R_ARM_ALU_PC_G0_NC},
{BFD_RELOC_ARM_ALU_PC_G0, R_ARM_ALU_PC_G0},
{BFD_RELOC_ARM_ALU_PC_G1_NC, R_ARM_ALU_PC_G1_NC},
{BFD_RELOC_ARM_ALU_PC_G1, R_ARM_ALU_PC_G1},
{BFD_RELOC_ARM_ALU_PC_G2, R_ARM_ALU_PC_G2},
{BFD_RELOC_ARM_LDR_PC_G0, R_ARM_LDR_PC_G0},
{BFD_RELOC_ARM_LDR_PC_G1, R_ARM_LDR_PC_G1},
{BFD_RELOC_ARM_LDR_PC_G2, R_ARM_LDR_PC_G2},
{BFD_RELOC_ARM_LDRS_PC_G0, R_ARM_LDRS_PC_G0},
{BFD_RELOC_ARM_LDRS_PC_G1, R_ARM_LDRS_PC_G1},
{BFD_RELOC_ARM_LDRS_PC_G2, R_ARM_LDRS_PC_G2},
{BFD_RELOC_ARM_LDC_PC_G0, R_ARM_LDC_PC_G0},
{BFD_RELOC_ARM_LDC_PC_G1, R_ARM_LDC_PC_G1},
{BFD_RELOC_ARM_LDC_PC_G2, R_ARM_LDC_PC_G2},
{BFD_RELOC_ARM_ALU_SB_G0_NC, R_ARM_ALU_SB_G0_NC},
{BFD_RELOC_ARM_ALU_SB_G0, R_ARM_ALU_SB_G0},
{BFD_RELOC_ARM_ALU_SB_G1_NC, R_ARM_ALU_SB_G1_NC},
{BFD_RELOC_ARM_ALU_SB_G1, R_ARM_ALU_SB_G1},
{BFD_RELOC_ARM_ALU_SB_G2, R_ARM_ALU_SB_G2},
{BFD_RELOC_ARM_LDR_SB_G0, R_ARM_LDR_SB_G0},
{BFD_RELOC_ARM_LDR_SB_G1, R_ARM_LDR_SB_G1},
{BFD_RELOC_ARM_LDR_SB_G2, R_ARM_LDR_SB_G2},
{BFD_RELOC_ARM_LDRS_SB_G0, R_ARM_LDRS_SB_G0},
{BFD_RELOC_ARM_LDRS_SB_G1, R_ARM_LDRS_SB_G1},
{BFD_RELOC_ARM_LDRS_SB_G2, R_ARM_LDRS_SB_G2},
{BFD_RELOC_ARM_LDC_SB_G0, R_ARM_LDC_SB_G0},
{BFD_RELOC_ARM_LDC_SB_G1, R_ARM_LDC_SB_G1},
{BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2},
{BFD_RELOC_ARM_V4BX, R_ARM_V4BX}
};
static reloc_howto_type *
elf32_arm_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type code)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE (elf32_arm_reloc_map); i ++)
if (elf32_arm_reloc_map[i].bfd_reloc_val == code)
return elf32_arm_howto_from_type (elf32_arm_reloc_map[i].elf_reloc_val);
return NULL;
}
static reloc_howto_type *
elf32_arm_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
const char *r_name)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE (elf32_arm_howto_table_1); i++)
if (elf32_arm_howto_table_1[i].name != NULL
&& strcasecmp (elf32_arm_howto_table_1[i].name, r_name) == 0)
return &elf32_arm_howto_table_1[i];
for (i = 0; i < ARRAY_SIZE (elf32_arm_howto_table_2); i++)
if (elf32_arm_howto_table_2[i].name != NULL
&& strcasecmp (elf32_arm_howto_table_2[i].name, r_name) == 0)
return &elf32_arm_howto_table_2[i];
for (i = 0; i < ARRAY_SIZE (elf32_arm_howto_table_3); i++)
if (elf32_arm_howto_table_3[i].name != NULL
&& strcasecmp (elf32_arm_howto_table_3[i].name, r_name) == 0)
return &elf32_arm_howto_table_3[i];
return NULL;
}
/* Support for core dump NOTE sections. */
static bfd_boolean
elf32_arm_nabi_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
int offset;
size_t size;
switch (note->descsz)
{
default:
return FALSE;
case 148: /* Linux/ARM 32-bit. */
/* pr_cursig */
elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
size = 72;
break;
}
/* Make a ".reg/999" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
size, note->descpos + offset);
}
static bfd_boolean
elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
switch (note->descsz)
{
default:
return FALSE;
case 124: /* Linux/ARM elf_prpsinfo. */
elf_tdata (abfd)->core_pid
= bfd_get_32 (abfd, note->descdata + 12);
elf_tdata (abfd)->core_program
= _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
elf_tdata (abfd)->core_command
= _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
}
/* Note that for some reason, a spurious space is tacked
onto the end of the args in some (at least one anyway)
implementations, so strip it off if it exists. */
{
char *command = elf_tdata (abfd)->core_command;
int n = strlen (command);
if (0 < n && command[n - 1] == ' ')
command[n - 1] = '\0';
}
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
#define TARGET_BIG_NAME "elf32-bigarm"
#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;
/* In lieu of proper flags, assume all EABIv4 or later objects are
interworkable. */
#define INTERWORK_FLAG(abfd) \
(EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) >= EF_ARM_EABI_VER4 \
|| (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK) \
|| ((abfd)->flags & BFD_LINKER_CREATED))
/* The linker script knows the section names for placement.
The entry_names are used to do simple name mangling on the stubs.
Given a function name, and its type, the stub can be found. The
name can be changed. The only requirement is the %s be present. */
#define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
#define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
#define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
#define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
#define VFP11_ERRATUM_VENEER_SECTION_NAME ".vfp11_veneer"
#define VFP11_ERRATUM_VENEER_ENTRY_NAME "__vfp11_veneer_%x"
#define ARM_BX_GLUE_SECTION_NAME ".v4_bx"
#define ARM_BX_GLUE_ENTRY_NAME "__bx_r%d"
#define STUB_ENTRY_NAME "__%s_veneer"
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#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 */
};
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
+ dl_tlsdesc_lazy_resolver(GOT) */
0x00000018, /* 4: .word _GLOBAL_OFFSET_TABLE_ - 2b - 8 */
};
#ifdef FOUR_WORD_PLT
/* 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_plt0_entry [] =
{
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 */
};
#else
/* 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_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] - . */
};
/* 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]! */
};
#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_ */
};
/* 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) */
};
/* 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) */
};
/* 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 */
};
/* 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) */
};
/* 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)
#define THM_MAX_FWD_BRANCH_OFFSET ((1 << 22) -2 + 4)
#define THM_MAX_BWD_BRANCH_OFFSET (-(1 << 22) + 4)
#define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
enum stub_insn_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
is inserted in arm_build_one_stub(). */
#define THUMB16_BCOND_INSN(X) {(X), THUMB16_TYPE, R_ARM_NONE, 1}
#define THUMB32_INSN(X) {(X), THUMB32_TYPE, R_ARM_NONE, 0}
#define THUMB32_B_INSN(X, Z) {(X), THUMB32_TYPE, R_ARM_THM_JUMP24, (Z)}
#define ARM_INSN(X) {(X), ARM_TYPE, R_ARM_NONE, 0}
#define ARM_REL_INSN(X, Z) {(X), ARM_TYPE, R_ARM_JUMP24, (Z)}
#define DATA_WORD(X,Y,Z) {(X), DATA_TYPE, (Y), (Z)}
typedef struct
{
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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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/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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* 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) */
};
/* Cortex-A8 erratum-workaround stubs. */
/* Stub used for conditional branches (which may be beyond +/-1MB away, so we
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. */
};
/* 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. */
};
static const insn_sequence elf32_arm_stub_a8_veneer_bl[] =
{
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. */
};
/* For each section group there can be a specially created linker section
to hold the stubs for that group. The name of the stub section is based
upon the name of another section within that group with the suffix below
applied.
PR 13049: STUB_SUFFIX used to be ".stub", but this allowed the user to
create what appeared to be a linker stub section when it actually
contained user code/data. For example, consider this fragment:
const char * stubborn_problems[] = { "np" };
If this is compiled with "-fPIC -fdata-sections" then gcc produces a
section called:
.data.rel.local.stubborn_problems
This then causes problems in arm32_arm_build_stubs() as it triggers:
// Ignore non-stub sections.
if (!strstr (stub_sec->name, STUB_SUFFIX))
continue;
And so the section would be ignored instead of being processed. Hence
the change in definition of STUB_SUFFIX to a name that cannot be a valid
C identifier. */
#define STUB_SUFFIX ".__stub"
/* One entry per long/short branch stub defined above. */
#define DEF_STUBS \
DEF_STUB(long_branch_any_any) \
DEF_STUB(long_branch_v4t_arm_thumb) \
DEF_STUB(long_branch_thumb_only) \
DEF_STUB(long_branch_v4t_thumb_thumb) \
DEF_STUB(long_branch_v4t_thumb_arm) \
DEF_STUB(short_branch_v4t_thumb_arm) \
DEF_STUB(long_branch_any_arm_pic) \
DEF_STUB(long_branch_any_thumb_pic) \
DEF_STUB(long_branch_v4t_thumb_thumb_pic) \
DEF_STUB(long_branch_v4t_arm_thumb_pic) \
DEF_STUB(long_branch_v4t_thumb_arm_pic) \
DEF_STUB(long_branch_thumb_only_pic) \
DEF_STUB(long_branch_any_tls_pic) \
DEF_STUB(long_branch_v4t_thumb_tls_pic) \
DEF_STUB(a8_veneer_b_cond) \
DEF_STUB(a8_veneer_b) \
DEF_STUB(a8_veneer_bl) \
DEF_STUB(a8_veneer_blx)
#define DEF_STUB(x) arm_stub_##x,
enum elf32_arm_stub_type
{
arm_stub_none,
DEF_STUBS
/* Note the first a8_veneer type */
arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond
};
#undef DEF_STUB
typedef struct
{
const insn_sequence* template_sequence;
int template_size;
} stub_def;
#define DEF_STUB(x) {elf32_arm_stub_##x, ARRAY_SIZE(elf32_arm_stub_##x)},
static const stub_def stub_definitions[] =
{
{NULL, 0},
DEF_STUBS
};
struct elf32_arm_stub_hash_entry
{
/* Base hash table entry structure. */
struct bfd_hash_entry root;
/* The stub section. */
asection *stub_sec;
/* Offset within stub_sec of the beginning of this stub. */
bfd_vma stub_offset;
/* Given the symbol's value and its section we can determine its final
value when building the stubs (so the stub knows where to jump). */
bfd_vma target_value;
asection *target_section;
/* Offset to apply to relocation referencing target_value. */
bfd_vma target_addend;
/* The instruction which caused this stub to be generated (only valid for
Cortex-A8 erratum workaround stubs at present). */
unsigned long orig_insn;
/* The stub type. */
enum elf32_arm_stub_type stub_type;
/* Its encoding size in bytes. */
int stub_size;
/* Its template. */
const insn_sequence *stub_template;
/* The size of the template (number of entries). */
int stub_template_size;
/* The symbol table entry, if any, that this was derived from. */
struct elf32_arm_link_hash_entry *h;
/* Type of branch. */
enum arm_st_branch_type branch_type;
/* Where this stub is being called from, or, in the case of combined
stub sections, the first input section in the group. */
asection *id_sec;
/* The name for the local symbol at the start of this stub. The
stub name in the hash table has to be unique; this does not, so
it can be friendlier. */
char *output_name;
};
/* Used to build a map of a section. This is required for mixed-endian
code/data. */
typedef struct elf32_elf_section_map
{
bfd_vma vma;
char type;
}
elf32_arm_section_map;
/* Information about a VFP11 erratum veneer, or a branch to such a veneer. */
typedef enum
{
VFP11_ERRATUM_BRANCH_TO_ARM_VENEER,
VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER,
VFP11_ERRATUM_ARM_VENEER,
VFP11_ERRATUM_THUMB_VENEER
}
elf32_vfp11_erratum_type;
typedef struct elf32_vfp11_erratum_list
{
struct elf32_vfp11_erratum_list *next;
bfd_vma vma;
union
{
struct
{
struct elf32_vfp11_erratum_list *veneer;
unsigned int vfp_insn;
} b;
struct
{
struct elf32_vfp11_erratum_list *branch;
unsigned int id;
} v;
} u;
elf32_vfp11_erratum_type type;
}
elf32_vfp11_erratum_list;
typedef enum
{
DELETE_EXIDX_ENTRY,
INSERT_EXIDX_CANTUNWIND_AT_END
}
arm_unwind_edit_type;
/* A (sorted) list of edits to apply to an unwind table. */
typedef struct arm_unwind_table_edit
{
arm_unwind_edit_type type;
/* Note: we sometimes want to insert an unwind entry corresponding to a
section different from the one we're currently writing out, so record the
(text) section this edit relates to here. */
asection *linked_section;
unsigned int index;
struct arm_unwind_table_edit *next;
}
arm_unwind_table_edit;
typedef struct _arm_elf_section_data
{
/* Information about mapping symbols. */
struct bfd_elf_section_data elf;
unsigned int mapcount;
unsigned int mapsize;
elf32_arm_section_map *map;
/* Information about CPU errata. */
unsigned int erratumcount;
elf32_vfp11_erratum_list *erratumlist;
/* Information about unwind tables. */
union
{
/* Unwind info attached to a text section. */
struct
{
asection *arm_exidx_sec;
} text;
/* Unwind info attached to an .ARM.exidx section. */
struct
{
arm_unwind_table_edit *unwind_edit_list;
arm_unwind_table_edit *unwind_edit_tail;
} exidx;
} u;
}
_arm_elf_section_data;
#define elf32_arm_section_data(sec) \
((_arm_elf_section_data *) elf_section_data (sec))
/* A fix which might be required for Cortex-A8 Thumb-2 branch/TLB erratum.
These fixes are subject to a relaxation procedure (in elf32_arm_size_stubs),
so may be created multiple times: we use an array of these entries whilst
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
{
bfd *input_bfd;
asection *section;
bfd_vma offset;
bfd_vma addend;
unsigned long orig_insn;
char *stub_name;
enum elf32_arm_stub_type stub_type;
enum arm_st_branch_type branch_type;
};
/* A table of relocs applied to branches which might trigger Cortex-A8
erratum. */
struct a8_erratum_reloc
{
bfd_vma from;
bfd_vma destination;
struct elf32_arm_link_hash_entry *hash;
const char *sym_name;
unsigned int r_type;
enum arm_st_branch_type branch_type;
bfd_boolean non_a8_stub;
};
/* The size of the thread control block. */
#define TCB_SIZE 8
/* ARM-specific information about a PLT entry, over and above the usual
gotplt_union. */
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;
/* Some references from Thumb code may be eliminated by BL->BLX
conversion, so record them separately. */
bfd_signed_vma maybe_thumb_refcount;
/* How many of the recorded PLT accesses were from non-call relocations.
This information is useful when deciding whether anything takes the
address of an STT_GNU_IFUNC PLT. A value of 0 means that all
non-call references to the function should resolve directly to the
real runtime target. */
unsigned int noncall_refcount;
/* Since PLT entries have variable size if the Thumb prologue is
used, we need to record the index into .got.plt instead of
recomputing it from the PLT offset. */
bfd_signed_vma got_offset;
};
/* Information about an .iplt entry for a local STT_GNU_IFUNC symbol. */
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;
/* The information that is usually found in the ARM-specific part of
the hash table entry. */
struct arm_plt_info arm;
/* A list of all potential dynamic relocations against this symbol. */
struct elf_dyn_relocs *dyn_relocs;
};
struct elf_arm_obj_tdata
{
struct elf_obj_tdata root;
/* tls_type for each local got entry. */
char *local_got_tls_type;
/* GOTPLT entries for TLS descriptors. */
bfd_vma *local_tlsdesc_gotent;
/* Information for local symbols that need entries in .iplt. */
struct arm_local_iplt_info **local_iplt;
/* Zero to warn when linking objects with incompatible enum sizes. */
int no_enum_size_warning;
/* Zero to warn when linking objects with incompatible wchar_t sizes. */
int no_wchar_size_warning;
};
#define elf_arm_tdata(bfd) \
((struct elf_arm_obj_tdata *) (bfd)->tdata.any)
#define elf32_arm_local_got_tls_type(bfd) \
(elf_arm_tdata (bfd)->local_got_tls_type)
#define elf32_arm_local_tlsdesc_gotent(bfd) \
(elf_arm_tdata (bfd)->local_tlsdesc_gotent)
#define elf32_arm_local_iplt(bfd) \
(elf_arm_tdata (bfd)->local_iplt)
#define is_arm_elf(bfd) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
&& elf_tdata (bfd) != NULL \
&& elf_object_id (bfd) == ARM_ELF_DATA)
static bfd_boolean
elf32_arm_mkobject (bfd *abfd)
{
return bfd_elf_allocate_object (abfd, sizeof (struct elf_arm_obj_tdata),
ARM_ELF_DATA);
}
#define elf32_arm_hash_entry(ent) ((struct elf32_arm_link_hash_entry *)(ent))
/* Arm ELF linker hash entry. */
struct elf32_arm_link_hash_entry
{
struct elf_link_hash_entry root;
/* Track dynamic relocs copied for this symbol. */
struct elf_dyn_relocs *dyn_relocs;
/* ARM-specific PLT information. */
struct arm_plt_info plt;
#define GOT_UNKNOWN 0
#define GOT_NORMAL 1
#define GOT_TLS_GD 2
#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;
/* True if the symbol's PLT entry is in .iplt rather than .plt. */
unsigned int is_iplt : 1;
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;
/* 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
symbol. */
struct elf32_arm_stub_hash_entry *stub_cache;
};
/* Traverse an arm ELF linker hash table. */
#define elf32_arm_link_hash_traverse(table, func, info) \
(elf_link_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \
(info)))
/* Get the ARM elf linker hash table from a link_info structure. */
#define elf32_arm_hash_table(info) \
(elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \
== ARM_ELF_DATA ? ((struct elf32_arm_link_hash_table *) ((info)->hash)) : NULL)
#define arm_stub_hash_lookup(table, string, create, copy) \
((struct elf32_arm_stub_hash_entry *) \
bfd_hash_lookup ((table), (string), (create), (copy)))
/* Array to keep track of which stub sections have been created, and
information on stub grouping. */
struct map_stub
{
/* This is the section to which stubs in the group will be
attached. */
asection *link_sec;
/* The stub section. */
asection *stub_sec;
};
#define elf32_arm_compute_jump_table_size(htab) \
((htab)->next_tls_desc_index * 4)
/* ARM ELF linker hash table. */
struct elf32_arm_link_hash_table
{
/* The main hash table. */
struct elf_link_hash_table root;
/* The size in bytes of the section containing the Thumb-to-ARM glue. */
bfd_size_type thumb_glue_size;
/* The size in bytes of the section containing the ARM-to-Thumb glue. */
bfd_size_type arm_glue_size;
/* The size in bytes of section containing the ARMv4 BX veneers. */
bfd_size_type bx_glue_size;
/* Offsets of ARMv4 BX veneers. Bit1 set if present, and Bit0 set when
veneer has been populated. */
bfd_vma bx_glue_offset[15];
/* The size in bytes of the section containing glue for VFP11 erratum
veneers. */
bfd_size_type vfp11_erratum_glue_size;
/* A table of fix locations for Cortex-A8 Thumb-2 branch/TLB erratum. This
holds Cortex-A8 erratum fix locations between elf32_arm_size_stubs() and
elf32_arm_write_section(). */
struct a8_erratum_fix *a8_erratum_fixes;
unsigned int num_a8_erratum_fixes;
/* An arbitrary input BFD chosen to hold the glue sections. */
bfd * bfd_of_glue_owner;
/* Nonzero to output a BE8 image. */
int byteswap_code;
/* Zero if R_ARM_TARGET1 means R_ARM_ABS32.
Nonzero if R_ARM_TARGET1 means R_ARM_REL32. */
int target1_is_rel;
/* The relocation to use for R_ARM_TARGET2 relocations. */
int target2_reloc;
/* 0 = Ignore R_ARM_V4BX.
1 = Convert BX to MOV PC.
2 = Generate v4 interworing stubs. */
int fix_v4bx;
/* Whether we should fix the Cortex-A8 Thumb-2 branch/TLB erratum. */
int fix_cortex_a8;
/* Whether we should fix the ARM1176 BLX immediate issue. */
int fix_arm1176;
/* Nonzero if the ARM/Thumb BLX instructions are available for use. */
int use_blx;
/* What sort of code sequences we should look for which may trigger the
VFP11 denorm erratum. */
bfd_arm_vfp11_fix vfp11_fix;
/* Global counter for the number of fixes we have emitted. */
int num_v