blob: 7441ee2cc38a9ac08d228a67bb077a07de63bfab [file] [log] [blame]
/* 32-bit ELF support for ARM
Copyright (C) 1998-2024 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 "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-nacl.h"
#include "elf-vxworks.h"
#include "elf/arm.h"
#include "elf32-arm.h"
#include "cpu-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 NULL
#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
/* The Adjusted Place, as defined by AAELF. */
#define Pa(X) ((X) & 0xfffffffc)
static bool 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, /* 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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
1, /* size */
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 */
2, /* size */
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 */
4, /* size */
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 */
2, /* size */
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 */
1, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
2, /* size */
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 */
2, /* size */
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 */
4, /* size */
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, /* 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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
2, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* 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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
2, /* size */
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 */
2, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
NULL, /* 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 */
4, /* size */
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 */
4, /* size */
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 */
4, /* size */
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 */
2, /* size */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* 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 */
EMPTY_HOWTO (130),
EMPTY_HOWTO (131),
HOWTO (R_ARM_THM_ALU_ABS_G0_NC,/* type. */
0, /* rightshift. */
2, /* size. */
16, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_bitfield,/* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_ALU_ABS_G0_NC",/* name. */
false, /* partial_inplace. */
0x00000000, /* src_mask. */
0x00000000, /* dst_mask. */
false), /* pcrel_offset. */
HOWTO (R_ARM_THM_ALU_ABS_G1_NC,/* type. */
0, /* rightshift. */
2, /* size. */
16, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_bitfield,/* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_ALU_ABS_G1_NC",/* name. */
false, /* partial_inplace. */
0x00000000, /* src_mask. */
0x00000000, /* dst_mask. */
false), /* pcrel_offset. */
HOWTO (R_ARM_THM_ALU_ABS_G2_NC,/* type. */
0, /* rightshift. */
2, /* size. */
16, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_bitfield,/* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_ALU_ABS_G2_NC",/* name. */
false, /* partial_inplace. */
0x00000000, /* src_mask. */
0x00000000, /* dst_mask. */
false), /* pcrel_offset. */
HOWTO (R_ARM_THM_ALU_ABS_G3_NC,/* type. */
0, /* rightshift. */
2, /* size. */
16, /* bitsize. */
false, /* pc_relative. */
0, /* bitpos. */
complain_overflow_bitfield,/* complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_ALU_ABS_G3_NC",/* name. */
false, /* partial_inplace. */
0x00000000, /* src_mask. */
0x00000000, /* dst_mask. */
false), /* pcrel_offset. */
/* Relocations for Armv8.1-M Mainline. */
HOWTO (R_ARM_THM_BF16, /* type. */
0, /* rightshift. */
2, /* size. */
16, /* bitsize. */
true, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont,/* do not complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_BF16", /* name. */
false, /* partial_inplace. */
0x001f0ffe, /* src_mask. */
0x001f0ffe, /* dst_mask. */
true), /* pcrel_offset. */
HOWTO (R_ARM_THM_BF12, /* type. */
0, /* rightshift. */
2, /* size. */
12, /* bitsize. */
true, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont,/* do not complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_BF12", /* name. */
false, /* partial_inplace. */
0x00010ffe, /* src_mask. */
0x00010ffe, /* dst_mask. */
true), /* pcrel_offset. */
HOWTO (R_ARM_THM_BF18, /* type. */
0, /* rightshift. */
2, /* size. */
18, /* bitsize. */
true, /* pc_relative. */
0, /* bitpos. */
complain_overflow_dont,/* do not complain_on_overflow. */
bfd_elf_generic_reloc, /* special_function. */
"R_ARM_THM_BF18", /* name. */
false, /* partial_inplace. */
0x007f0ffe, /* src_mask. */
0x007f0ffe, /* dst_mask. */
true), /* pcrel_offset. */
};
/* 160 onwards: */
static reloc_howto_type elf32_arm_howto_table_2[8] =
{
HOWTO (R_ARM_IRELATIVE, /* type */
0, /* rightshift */
4, /* size */
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 */
HOWTO (R_ARM_GOTFUNCDESC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOTFUNCDESC", /* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_GOTOFFFUNCDESC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_GOTOFFFUNCDESC",/* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_FUNCDESC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_FUNCDESC", /* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_FUNCDESC_VALUE, /* type */
0, /* rightshift */
4, /* size */
64, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_FUNCDESC_VALUE",/* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_TLS_GD32_FDPIC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_GD32_FDPIC",/* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_TLS_LDM32_FDPIC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_LDM32_FDPIC",/* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
HOWTO (R_ARM_TLS_IE32_FDPIC, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_ARM_TLS_IE32_FDPIC",/* name */
false, /* partial_inplace */
0, /* 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, /* 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, /* 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, /* 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, /* 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
&& r_type < R_ARM_IRELATIVE + ARRAY_SIZE (elf32_arm_howto_table_2))
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 bool
elf32_arm_info_to_howto (bfd * abfd, arelent * bfd_reloc,
Elf_Internal_Rela * elf_reloc)
{
unsigned int r_type;
r_type = ELF32_R_TYPE (elf_reloc->r_info);
if ((bfd_reloc->howto = elf32_arm_howto_from_type (r_type)) == NULL)
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
return false;
}
return true;
}
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_ARM_GOTFUNCDESC, R_ARM_GOTFUNCDESC},
{BFD_RELOC_ARM_GOTOFFFUNCDESC, R_ARM_GOTOFFFUNCDESC},
{BFD_RELOC_ARM_FUNCDESC, R_ARM_FUNCDESC},
{BFD_RELOC_ARM_FUNCDESC_VALUE, R_ARM_FUNCDESC_VALUE},
{BFD_RELOC_ARM_TLS_GD32_FDPIC, R_ARM_TLS_GD32_FDPIC},
{BFD_RELOC_ARM_TLS_LDM32_FDPIC, R_ARM_TLS_LDM32_FDPIC},
{BFD_RELOC_ARM_TLS_IE32_FDPIC, R_ARM_TLS_IE32_FDPIC},
{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},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, R_ARM_THM_ALU_ABS_G3_NC},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, R_ARM_THM_ALU_ABS_G2_NC},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, R_ARM_THM_ALU_ABS_G1_NC},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC},
{BFD_RELOC_ARM_THUMB_BF17, R_ARM_THM_BF16},
{BFD_RELOC_ARM_THUMB_BF13, R_ARM_THM_BF12},
{BFD_RELOC_ARM_THUMB_BF19, R_ARM_THM_BF18}
};
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 bool
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 bool
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] ATTRIBUTE_NONSTRING;
va_list ap;
va_start (ap, note_type);
memset (data, 0, sizeof (data));
strncpy (data + 28, va_arg (ap, const char *), 16);
#if GCC_VERSION == 8000 || GCC_VERSION == 8001
DIAGNOSTIC_PUSH;
/* GCC 8.0 and 8.1 warn about 80 equals destination size with
-Wstringop-truncation:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85643
*/
DIAGNOSTIC_IGNORE_STRINGOP_TRUNCATION;
#endif
strncpy (data + 44, va_arg (ap, const char *), 80);
#if GCC_VERSION == 8000 || GCC_VERSION == 8001
DIAGNOSTIC_POP;
#endif
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 arm_elf32_le_vec
#define TARGET_LITTLE_NAME "elf32-littlearm"
#define TARGET_BIG_SYM arm_elf32_be_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 STM32L4XX_ERRATUM_VENEER_SECTION_NAME ".text.stm32l4xx_veneer"
#define STM32L4XX_ERRATUM_VENEER_ENTRY_NAME "__stm32l4xx_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"
#define CMSE_PREFIX "__acle_se_"
#define CMSE_STUB_NAME ".gnu.sgstubs"
/* The name of the dynamic interpreter. This is put in the .interp
section. */
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
/* FDPIC default stack size. */
#define DEFAULT_STACK_SIZE 0x8000
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 */
};
/* NOTE: [Thumb nop sequence]
When adding code that transitions from Thumb to Arm the instruction that
should be used for the alignment padding should be 0xe7fd (b .-2) instead of
a nop for performance reasons. */
/* ARM FDPIC PLT entry. */
/* The last 5 words contain PLT lazy fragment code and data. */
static const bfd_vma elf32_arm_fdpic_plt_entry [] =
{
0xe59fc008, /* ldr r12, .L1 */
0xe08cc009, /* add r12, r12, r9 */
0xe59c9004, /* ldr r9, [r12, #4] */
0xe59cf000, /* ldr pc, [r12] */
0x00000000, /* L1. .word foo(GOTOFFFUNCDESC) */
0x00000000, /* L1. .word foo(funcdesc_value_reloc_offset) */
0xe51fc00c, /* ldr r12, [pc, #-12] */
0xe92d1000, /* push {r12} */
0xe599c004, /* ldr r12, [r9, #4] */
0xe599f000, /* ldr pc, [r9] */
};
/* Thumb FDPIC PLT entry. */
/* The last 5 words contain PLT lazy fragment code and data. */
static const bfd_vma elf32_arm_fdpic_thumb_plt_entry [] =
{
0xc00cf8df, /* ldr.w r12, .L1 */
0x0c09eb0c, /* add.w r12, r12, r9 */
0x9004f8dc, /* ldr.w r9, [r12, #4] */
0xf000f8dc, /* ldr.w pc, [r12] */
0x00000000, /* .L1 .word foo(GOTOFFFUNCDESC) */
0x00000000, /* .L2 .word foo(funcdesc_value_reloc_offset) */
0xc008f85f, /* ldr.w r12, .L2 */
0xcd04f84d, /* push {r12} */
0xc004f8d9, /* ldr.w r12, [r9, #4] */
0xf000f8d9, /* ldr.w pc, [r9] */
};
#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 /* not 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]! */
0xe59fe004, /* ldr lr, [pc, #4] */
0xe08fe00e, /* add lr, pc, lr */
0xe5bef008, /* ldr pc, [lr, #8]! */
0x00000000, /* &GOT[0] - . */
};
/* By default subsequent entries in a procedure linkage table look like
this. Offsets that don't fit into 28 bits will cause link error. */
static const bfd_vma elf32_arm_plt_entry_short [] =
{
0xe28fc600, /* add ip, pc, #0xNN00000 */
0xe28cca00, /* add ip, ip, #0xNN000 */
0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */
};
/* When explicitly asked, we'll use this "long" entry format
which can cope with arbitrary displacements. */
static const bfd_vma elf32_arm_plt_entry_long [] =
{
0xe28fc200, /* add ip, pc, #0xN0000000 */
0xe28cc600, /* add ip, ip, #0xNN00000 */
0xe28cca00, /* add ip, ip, #0xNN000 */
0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */
};
static bool elf32_arm_use_long_plt_entry = false;
#endif /* not 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_thumb2_plt0_entry [] =
{
/* NOTE: As this is a mixture of 16-bit and 32-bit instructions,
an instruction maybe encoded to one or two array elements. */
0xf8dfb500, /* push {lr} */
0x44fee008, /* ldr.w lr, [pc, #8] */
/* add lr, pc */
0xff08f85e, /* ldr.w pc, [lr, #8]! */
0x00000000, /* &GOT[0] - . */
};
/* Subsequent entries in a procedure linkage table for thumb only target
look like this. */
static const bfd_vma elf32_thumb2_plt_entry [] =
{
/* NOTE: As this is a mixture of 16-bit and 32-bit instructions,
an instruction maybe encoded to one or two array elements. */
0x0c00f240, /* movw ip, #0xNNNN */
0x0c00f2c0, /* movt ip, #0xNNNN */
0xf8dc44fc, /* add ip, pc */
0xe7fcf000 /* ldr.w pc, [ip] */
/* b .-4 */
};
/* 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 */
0xe7fd /* b .-2 */
};
/* 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: */
0xe3ccc103, /* bic ip, ip, #0xc0000000 */
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: */
0xe3ccc103, /* bic ip, ip, #0xc0000000 */
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 */
};
/* PR 28924:
There was a bug due to too high values of THM_MAX_FWD_BRANCH_OFFSET and
THM2_MAX_FWD_BRANCH_OFFSET. The first macro concerns the case when Thumb-2
is not available, and second macro when Thumb-2 is available. Among other
things, they affect the range of branches represented as BLX instructions
in Encoding T2 defined in Section A8.8.25 of the ARM Architecture
Reference Manual ARMv7-A and ARMv7-R edition issue C.d. Such branches are
specified there to have a maximum forward offset that is a multiple of 4.
Previously, the respective values defined here were multiples of 2 but not
4 and they are included in comments for reference. */
#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) - 4 + 4)
/* #def 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) - 4) + 4)
/* #def THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4) */
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
#define THM2_MAX_FWD_COND_BRANCH_OFFSET (((1 << 20) -2) + 4)
#define THM2_MAX_BWD_COND_BRANCH_OFFSET (-(1 << 20) + 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_MOVT(X) {(X), THUMB32_TYPE, R_ARM_THM_MOVT_ABS, 0}
#define THUMB32_MOVW(X) {(X), THUMB32_TYPE, R_ARM_THM_MOVW_ABS_NC, 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;
/* See note [Thumb nop sequence] when adding a veneer. */
/* 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) */
};
/* Thumb -> Thumb long branch stub in thumb2 encoding. Used on armv7. */
static const insn_sequence elf32_arm_stub_long_branch_thumb2_only[] =
{
THUMB32_INSN (0xf85ff000), /* ldr.w pc, [pc, #-0] */
DATA_WORD (0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(x) */
};
/* Thumb -> Thumb long branch stub. Used for PureCode sections on Thumb2
M-profile architectures. */
static const insn_sequence elf32_arm_stub_long_branch_thumb2_only_pure[] =
{
THUMB32_MOVW (0xf2400c00), /* mov.w ip, R_ARM_MOVW_ABS_NC */
THUMB32_MOVT (0xf2c00c00), /* movt ip, R_ARM_MOVT_ABS << 16 */
THUMB16_INSN (0x4760), /* bx ip */
};
/* 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 (0xe7fd), /* b .-2 */
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 (0xe7fd), /* b .-2 */
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 (0xe7fd), /* b .-2 */
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 (0xe7fd), /* b .-2 */
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 (0xe7fd), /* b .-2 */
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 (0xe7fd), /* b .-2 */
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) */
};
/* NaCl ARM -> ARM long branch stub. */
static const insn_sequence elf32_arm_stub_long_branch_arm_nacl[] =
{
ARM_INSN (0xe59fc00c), /* ldr ip, [pc, #12] */
ARM_INSN (0xe3ccc13f), /* bic ip, ip, #0xc000000f */
ARM_INSN (0xe12fff1c), /* bx ip */
ARM_INSN (0xe320f000), /* nop */
ARM_INSN (0xe125be70), /* bkpt 0x5be0 */
DATA_WORD (0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
};
/* NaCl ARM -> ARM long branch stub, PIC. */
static const insn_sequence elf32_arm_stub_long_branch_arm_nacl_pic[] =
{
ARM_INSN (0xe59fc00c), /* ldr ip, [pc, #12] */
ARM_INSN (0xe08cc00f), /* add ip, ip, pc */
ARM_INSN (0xe3ccc13f), /* bic ip, ip, #0xc000000f */
ARM_INSN (0xe12fff1c), /* bx ip */
ARM_INSN (0xe125be70), /* bkpt 0x5be0 */
DATA_WORD (0, R_ARM_REL32, 8), /* dcd R_ARM_REL32(X+8) */
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */
};
/* Stub used for transition to secure state (aka SG veneer). */
static const insn_sequence elf32_arm_stub_cmse_branch_thumb_only[] =
{
THUMB32_INSN (0xe97fe97f), /* sg. */
THUMB32_B_INSN (0xf000b800, -4), /* b.w original_branch_dest. */
};
/* 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 (long_branch_arm_nacl) \
DEF_STUB (long_branch_arm_nacl_pic) \
DEF_STUB (cmse_branch_thumb_only) \
DEF_STUB (a8_veneer_b_cond) \
DEF_STUB (a8_veneer_b) \
DEF_STUB (a8_veneer_bl) \
DEF_STUB (a8_veneer_blx) \
DEF_STUB (long_branch_thumb2_only) \
DEF_STUB (long_branch_thumb2_only_pure)
#define DEF_STUB(x) arm_stub_##x,
enum elf32_arm_stub_type
{
arm_stub_none,
DEF_STUBS
max_stub_type
};
#undef DEF_STUB
/* Note the first a8_veneer type. */
const unsigned arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond;
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;
/* Same as above but for the source of the branch to the stub. Used for
Cortex-A8 erratum workaround to patch it to branch to the stub. As
such, source section does not need to be recorded since Cortex-A8 erratum
workaround stubs are only generated when both source and target are in the
same section. */
bfd_vma source_value;
/* 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;
/* Information about a STM32L4XX erratum veneer, or a branch to such a
veneer. */
typedef enum
{
STM32L4XX_ERRATUM_BRANCH_TO_VENEER,
STM32L4XX_ERRATUM_VENEER
}
elf32_stm32l4xx_erratum_type;
typedef struct elf32_stm32l4xx_erratum_list
{
struct elf32_stm32l4xx_erratum_list *next;
bfd_vma vma;
union
{
struct
{
struct elf32_stm32l4xx_erratum_list *veneer;
unsigned int insn;
} b;
struct
{
struct elf32_stm32l4xx_erratum_list *branch;
unsigned int id;
} v;
} u;
elf32_stm32l4xx_erratum_type type;
}
elf32_stm32l4xx_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;
unsigned int stm32l4xx_erratumcount;
elf32_stm32l4xx_erratum_list *stm32l4xx_erratumlist;
unsigned int additional_reloc_count;
/* 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 target_offset;
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;
bool 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;
};
/* Structure to handle FDPIC support for local functions. */
struct fdpic_local
{
unsigned int funcdesc_cnt;
unsigned int gotofffuncdesc_cnt;
int funcdesc_offset;
};
struct elf_arm_obj_tdata
{
struct elf_obj_tdata root;
/* 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;
/* The number of entries in each of the arrays in this strcuture.
Used to avoid buffer overruns. */
bfd_size_type num_entries;
/* 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;
/* Maintains FDPIC counters and funcdesc info. */
struct fdpic_local *local_fdpic_cnts;
};
#define elf_arm_tdata(bfd) \
((struct elf_arm_obj_tdata *) (bfd)->tdata.any)
#define elf32_arm_num_entries(bfd) \
(elf_arm_tdata (bfd)->num_entries)
#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 elf32_arm_local_fdpic_cnts(bfd) \
(elf_arm_tdata (bfd)->local_fdpic_cnts)
#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 bool
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))
/* Structure to handle FDPIC support for extern functions. */
struct fdpic_global {
unsigned int gotofffuncdesc_cnt;
unsigned int gotfuncdesc_cnt;
unsigned int funcdesc_cnt;
int funcdesc_offset;
int gotfuncdesc_offset;
};
/* Arm ELF linker hash entry. */
struct elf32_arm_link_hash_entry
{
struct elf_link_hash_entry root;
/* 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;