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 */
+};
+
+
/* Cortex-A8 erratum-workaround stubs. */
/* Stub used for conditional branches (which may be beyond +/-1MB away, so we
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(a8_veneer_b_cond) \
DEF_STUB(a8_veneer_b) \
DEF_STUB(a8_veneer_bl) \
bfd *stub_bfd;
/* Linker call-backs. */
- asection * (*add_stub_section) (const char *, asection *);
+ asection * (*add_stub_section) (const char *, asection *, unsigned int);
void (*layout_sections_again) (void);
/* Array to keep track of which stub sections have been created, and
r_type = ELF32_R_TYPE (rel->r_info);
+ /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
+ are considering a function call relocation. */
+ if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_TO_ARM)
+ branch_type = ST_BRANCH_TO_THUMB;
+
/* For TLS call relocs, it is the caller's responsibility to provide
the address of the appropriate trampoline. */
if (r_type != R_ARM_TLS_CALL
? (r_type == R_ARM_TLS_CALL
/* TLS PIC Stub */
? arm_stub_long_branch_any_tls_pic
- : arm_stub_long_branch_any_arm_pic)
+ : (globals->nacl_p
+ ? arm_stub_long_branch_arm_nacl_pic
+ : arm_stub_long_branch_any_arm_pic))
/* non-PIC stubs. */
- : arm_stub_long_branch_any_any;
+ : (globals->nacl_p
+ ? arm_stub_long_branch_arm_nacl
+ : arm_stub_long_branch_any_any);
}
}
}
memcpy (s_name, link_sec->name, namelen);
memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
- stub_sec = (*htab->add_stub_section) (s_name, link_sec);
+ stub_sec = (*htab->add_stub_section) (s_name, link_sec,
+ htab->nacl_p ? 4 : 3);
if (stub_sec == NULL)
return NULL;
htab->stub_group[link_sec->id].stub_sec = stub_sec;
case arm_stub_a8_veneer_blx:
return 4;
+ case arm_stub_long_branch_arm_nacl:
+ case arm_stub_long_branch_arm_nacl_pic:
+ return 16;
+
default:
abort (); /* Should be unreachable. */
}
arm_build_one_stub (struct bfd_hash_entry *gen_entry,
void * in_arg)
{
-#define MAXRELOCS 2
+#define MAXRELOCS 3
struct elf32_arm_stub_hash_entry *stub_entry;
struct elf32_arm_link_hash_table *globals;
struct bfd_link_info *info;
bfd *stub_bfd,
struct bfd_link_info *info,
bfd_signed_vma group_size,
- asection * (*add_stub_section) (const char *, asection *),
+ asection * (*add_stub_section) (const char *, asection *,
+ unsigned int),
void (*layout_sections_again) (void))
{
bfd_size_type stub_group_size;
else
addend = signed_addend = rel->r_addend;
+ /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
+ are resolving a function call relocation. */
+ if (using_thumb_only (globals)
+ && (r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_TO_ARM)
+ branch_type = ST_BRANCH_TO_THUMB;
+
/* Record the symbol information that should be used in dynamic
relocations. */
dynreloc_st_type = st_type;
bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
bfd_vma pc = input_section->output_section->vma
+ input_section->output_offset + rel->r_offset;
- /* sb should be the origin of the *segment* containing the symbol.
- It is not clear how to obtain this OS-dependent value, so we
- make an arbitrary choice of zero. */
- bfd_vma sb = 0;
+ /* sb is the origin of the *segment* containing the symbol. */
+ bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
bfd_vma residual;
bfd_vma g_n;
bfd_signed_vma signed_value;
bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
bfd_vma pc = input_section->output_section->vma
+ input_section->output_offset + rel->r_offset;
- bfd_vma sb = 0; /* See note above. */
+ /* sb is the origin of the *segment* containing the symbol. */
+ bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
bfd_vma residual;
bfd_signed_vma signed_value;
int group = 0;
bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
bfd_vma pc = input_section->output_section->vma
+ input_section->output_offset + rel->r_offset;
- bfd_vma sb = 0; /* See note above. */
+ /* sb is the origin of the *segment* containing the symbol. */
+ bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
bfd_vma residual;
bfd_signed_vma signed_value;
int group = 0;
bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
bfd_vma pc = input_section->output_section->vma
+ input_section->output_offset + rel->r_offset;
- bfd_vma sb = 0; /* See note above. */
+ /* sb is the origin of the *segment* containing the symbol. */
+ bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0;
bfd_vma residual;
bfd_signed_vma signed_value;
int group = 0;