2009-02-23 Christophe Lyon <christophe.lyon@st.com>
bfd/ * elf32-arm.c (stub_insn_type): New type. (stub_reloc_type): Likewise. (insn_sequence): Likewise. (elf32_arm_stub_long_branch_any_any): Encode using insn_sequence. (elf32_arm_stub_long_branch_v4t_arm_thumb): Likewise. (elf32_arm_stub_long_branch_thumb_only): Likewise. (elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise. (elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise. (elf32_arm_stub_long_branch_any_any_pic): Likewise. (elf32_arm_stub_hash_entry): Add new helper fields. (stub_hash_newfunc): Initialize these new fields. (arm_build_one_stub): Encode Arm and Thumb instructions separately to take endianness into account. (arm_size_one_stub): Compute size of stubs using insn_sequence. (arm_map_one_stub): Code is now more generic, thanks to insn_sequence. ld/testsuite/ * ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test. * ld-arm/farcall-thumb-arm-be8.d: New expected result. * ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.
This commit is contained in:
parent
4c664d7bf7
commit
461a49caca
|
@ -1,3 +1,22 @@
|
|||
2009-02-20 Christophe Lyon <christophe.lyon@st.com>
|
||||
|
||||
* elf32-arm.c (stub_insn_type): New type.
|
||||
(stub_reloc_type): Likewise.
|
||||
(insn_sequence): Likewise.
|
||||
(elf32_arm_stub_long_branch_any_any): Encode using insn_sequence.
|
||||
(elf32_arm_stub_long_branch_v4t_arm_thumb): Likewise.
|
||||
(elf32_arm_stub_long_branch_thumb_only): Likewise.
|
||||
(elf32_arm_stub_long_branch_v4t_thumb_arm): Likewise.
|
||||
(elf32_arm_stub_short_branch_v4t_thumb_arm): Likewise.
|
||||
(elf32_arm_stub_long_branch_any_any_pic): Likewise.
|
||||
(elf32_arm_stub_hash_entry): Add new helper fields.
|
||||
(stub_hash_newfunc): Initialize these new fields.
|
||||
(arm_build_one_stub): Encode Arm and Thumb instructions separately
|
||||
to take endianness into account.
|
||||
(arm_size_one_stub): Compute size of stubs using insn_sequence.
|
||||
(arm_map_one_stub): Code is now more generic, thanks to
|
||||
insn_sequence.
|
||||
|
||||
2009-02-23 Christophe Lyon <christophe.lyon@st.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_stub_long_branch_thumb_only): Fix stub
|
||||
|
|
376
bfd/elf32-arm.c
376
bfd/elf32-arm.c
|
@ -2010,63 +2010,92 @@ static const bfd_vma elf32_arm_symbian_plt_entry [] =
|
|||
#define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4)
|
||||
#define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4)
|
||||
|
||||
enum stub_insn_type
|
||||
{
|
||||
THUMB16_TYPE = 1,
|
||||
THUMB32_TYPE,
|
||||
ARM_TYPE,
|
||||
DATA_TYPE
|
||||
};
|
||||
|
||||
enum stub_reloc_type
|
||||
{
|
||||
STUB_RELOC_NONE = 0,
|
||||
STUB_RELOC_ABS,
|
||||
STUB_RELOC_PIC,
|
||||
};
|
||||
|
||||
#define THUMB16_INSN(X) {(X), THUMB16_TYPE, R_ARM_NONE, 0}
|
||||
#define THUMB32_INSN(X) {(X), THUMB32_TYPE, R_ARM_NONE, 0}
|
||||
#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;
|
||||
enum stub_reloc_type reloc_type;
|
||||
int reloc_addend;
|
||||
} insn_sequence;
|
||||
|
||||
/* Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
|
||||
to reach the stub if necessary. */
|
||||
static const bfd_vma elf32_arm_stub_long_branch_any_any[] =
|
||||
static const insn_sequence elf32_arm_stub_long_branch_any_any[] =
|
||||
{
|
||||
0xe51ff004, /* ldr pc, [pc, #-4] */
|
||||
0x00000000, /* dcd R_ARM_ABS32(X) */
|
||||
ARM_INSN(0xe51ff004), /* ldr pc, [pc, #-4] */
|
||||
DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
|
||||
};
|
||||
|
||||
/* V4T Arm -> Thumb long branch stub. Used on V4T where blx is not
|
||||
available. */
|
||||
static const bfd_vma elf32_arm_stub_long_branch_v4t_arm_thumb[] =
|
||||
static const insn_sequence elf32_arm_stub_long_branch_v4t_arm_thumb[] =
|
||||
{
|
||||
0xe59fc000, /* ldr ip, [pc, #0] */
|
||||
0xe12fff1c, /* bx ip */
|
||||
0x00000000, /* dcd R_ARM_ABS32(X) */
|
||||
ARM_INSN(0xe59fc000), /* ldr ip, [pc, #0] */
|
||||
ARM_INSN(0xe12fff1c), /* bx ip */
|
||||
DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
|
||||
};
|
||||
|
||||
/* Thumb -> Thumb long branch stub. Used on architectures which
|
||||
support only this mode, or on V4T where it is expensive to switch
|
||||
to ARM. */
|
||||
static const bfd_vma elf32_arm_stub_long_branch_thumb_only[] =
|
||||
static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
|
||||
{
|
||||
0x4802b401, /* push {r0} */
|
||||
/* ldr r0, [pc, #8] */
|
||||
0xbc014684, /* mov ip, r0 */
|
||||
/* pop {r0} */
|
||||
0xbf004760, /* bx ip */
|
||||
/* nop */
|
||||
0x00000000, /* dcd R_ARM_ABS32(X) */
|
||||
THUMB16_INSN(0xb401), /* push {r0} */
|
||||
THUMB16_INSN(0x4802), /* ldr r0, [pc, #8] */
|
||||
THUMB16_INSN(0x4684), /* mov ip, r0 */
|
||||
THUMB16_INSN(0xbc01), /* pop {r0} */
|
||||
THUMB16_INSN(0x4760), /* bx ip */
|
||||
THUMB16_INSN(0xbf00), /* nop */
|
||||
DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
|
||||
};
|
||||
|
||||
/* V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
|
||||
available. */
|
||||
static const bfd_vma elf32_arm_stub_long_branch_v4t_thumb_arm[] =
|
||||
static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
|
||||
{
|
||||
0x46c04778, /* bx pc */
|
||||
/* nop */
|
||||
0xe51ff004, /* ldr pc, [pc, #-4] */
|
||||
0x00000000, /* dcd R_ARM_ABS32(X) */
|
||||
THUMB16_INSN(0x4778), /* bx pc */
|
||||
THUMB16_INSN(0x46c0), /* nop */
|
||||
ARM_INSN(0xe51ff004), /* ldr pc, [pc, #-4] */
|
||||
DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
|
||||
};
|
||||
|
||||
/* V4T Thumb -> ARM short branch stub. Shorter variant of the above
|
||||
one, when the destination is close enough. */
|
||||
static const bfd_vma elf32_arm_stub_short_branch_v4t_thumb_arm[] =
|
||||
static const insn_sequence elf32_arm_stub_short_branch_v4t_thumb_arm[] =
|
||||
{
|
||||
0x46c04778, /* bx pc */
|
||||
/* nop */
|
||||
0xea000000, /* b (X) */
|
||||
THUMB16_INSN(0x4778), /* bx pc */
|
||||
THUMB16_INSN(0x46c0), /* nop */
|
||||
ARM_REL_INSN(0xea000000, -8), /* b (X-8) */
|
||||
};
|
||||
|
||||
/* ARM/Thumb -> ARM/Thumb long branch stub, PIC. On V5T and above, use
|
||||
blx to reach the stub if necessary. */
|
||||
static const bfd_vma elf32_arm_stub_long_branch_any_any_pic[] =
|
||||
static const insn_sequence elf32_arm_stub_long_branch_any_any_pic[] =
|
||||
{
|
||||
0xe59fc000, /* ldr r12, [pc] */
|
||||
0xe08ff00c, /* add pc, pc, ip */
|
||||
0x00000000, /* dcd R_ARM_REL32(X-4) */
|
||||
ARM_INSN(0xe59fc000), /* ldr r12, [pc] */
|
||||
ARM_INSN(0xe08ff00c), /* add pc, pc, ip */
|
||||
DATA_WORD(0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X-4) */
|
||||
};
|
||||
|
||||
/* Section name for stubs is the associated section name plus this
|
||||
|
@ -2100,7 +2129,14 @@ struct elf32_arm_stub_hash_entry
|
|||
bfd_vma target_value;
|
||||
asection *target_section;
|
||||
|
||||
/* 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;
|
||||
|
@ -2469,6 +2505,9 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
eh->target_value = 0;
|
||||
eh->target_section = NULL;
|
||||
eh->stub_type = arm_stub_none;
|
||||
eh->stub_size = 0;
|
||||
eh->stub_template = NULL;
|
||||
eh->stub_template_size = 0;
|
||||
eh->h = NULL;
|
||||
eh->id_sec = NULL;
|
||||
}
|
||||
|
@ -3108,9 +3147,11 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
bfd_vma sym_value;
|
||||
int template_size;
|
||||
int size;
|
||||
const bfd_vma *template;
|
||||
const insn_sequence *template;
|
||||
int i;
|
||||
struct elf32_arm_link_hash_table * globals;
|
||||
int stub_reloc_idx = -1;
|
||||
int stub_reloc_offset;
|
||||
|
||||
/* Massage our args to the form they really have. */
|
||||
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
|
||||
|
@ -3136,101 +3177,61 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
|
||||
switch (stub_entry->stub_type)
|
||||
{
|
||||
case arm_stub_long_branch_any_any:
|
||||
template = elf32_arm_stub_long_branch_any_any;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_arm_thumb:
|
||||
template = elf32_arm_stub_long_branch_v4t_arm_thumb;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_long_branch_thumb_only:
|
||||
template = elf32_arm_stub_long_branch_thumb_only;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_thumb_arm:
|
||||
template = elf32_arm_stub_long_branch_v4t_thumb_arm;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_short_branch_v4t_thumb_arm:
|
||||
template = elf32_arm_stub_short_branch_v4t_thumb_arm;
|
||||
template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_long_branch_any_any_pic:
|
||||
template = elf32_arm_stub_long_branch_any_any_pic;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
return FALSE;
|
||||
}
|
||||
template = stub_entry->stub_template;
|
||||
template_size = stub_entry->stub_template_size;
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < (template_size / 4); i++)
|
||||
for (i = 0; i < template_size; i++)
|
||||
{
|
||||
/* A 0 pattern is a placeholder, every other pattern is an
|
||||
instruction. */
|
||||
if (template[i] != 0)
|
||||
put_arm_insn (globals, stub_bfd, template[i], loc + size);
|
||||
else
|
||||
bfd_put_32 (stub_bfd, template[i], loc + size);
|
||||
switch(template[i].type)
|
||||
{
|
||||
case THUMB16_TYPE:
|
||||
put_thumb_insn (globals, stub_bfd, template[i].data, loc + size);
|
||||
size += 2;
|
||||
break;
|
||||
|
||||
size += 4;
|
||||
case ARM_TYPE:
|
||||
put_arm_insn (globals, stub_bfd, template[i].data, loc + size);
|
||||
/* Handle cases where the target is encoded within the
|
||||
instruction. */
|
||||
if (template[i].reloc_type == R_ARM_JUMP24)
|
||||
{
|
||||
stub_reloc_idx = i;
|
||||
stub_reloc_offset = size;
|
||||
}
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
case DATA_TYPE:
|
||||
bfd_put_32 (stub_bfd, template[i].data, loc + size);
|
||||
stub_reloc_idx = i;
|
||||
stub_reloc_offset = size;
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
stub_sec->size += size;
|
||||
|
||||
/* Stub size has already been computed in arm_size_one_stub. Check
|
||||
consistency. */
|
||||
BFD_ASSERT (size == stub_entry->stub_size);
|
||||
|
||||
/* Destination is Thumb. Force bit 0 to 1 to reflect this. */
|
||||
if (stub_entry->st_type == STT_ARM_TFUNC)
|
||||
sym_value |= 1;
|
||||
|
||||
switch (stub_entry->stub_type)
|
||||
{
|
||||
case arm_stub_long_branch_any_any:
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 4, sym_value, 0);
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_arm_thumb:
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 8, sym_value, 0);
|
||||
break;
|
||||
case arm_stub_long_branch_thumb_only:
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 12, sym_value, 0);
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_thumb_arm:
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_ABS32),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 8, sym_value, 0);
|
||||
break;
|
||||
case arm_stub_short_branch_v4t_thumb_arm:
|
||||
{
|
||||
long int rel_offset;
|
||||
static const insn32 t2a3_b_insn = 0xea000000;
|
||||
/* Assume there is one and only one entry to relocate in each stub. */
|
||||
BFD_ASSERT (stub_reloc_idx != -1);
|
||||
|
||||
rel_offset = sym_value - (stub_addr + 8 + 4);
|
||||
|
||||
put_arm_insn (globals, stub_bfd,
|
||||
(bfd_vma) t2a3_b_insn | ((rel_offset >> 2) & 0x00FFFFFF),
|
||||
loc + 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case arm_stub_long_branch_any_any_pic:
|
||||
/* We want the value relative to the address 8 bytes from the
|
||||
start of the stub. */
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (R_ARM_REL32),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 8, sym_value, -4);
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL();
|
||||
break;
|
||||
}
|
||||
_bfd_final_link_relocate (elf32_arm_howto_from_type (template[stub_reloc_idx].reloc_type),
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + stub_reloc_offset,
|
||||
sym_value, template[stub_reloc_idx].reloc_addend);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -3244,7 +3245,7 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
{
|
||||
struct elf32_arm_stub_hash_entry *stub_entry;
|
||||
struct elf32_arm_link_hash_table *htab;
|
||||
const bfd_vma *template;
|
||||
const insn_sequence *template;
|
||||
int template_size;
|
||||
int size;
|
||||
int i;
|
||||
|
@ -3257,27 +3258,28 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
{
|
||||
case arm_stub_long_branch_any_any:
|
||||
template = elf32_arm_stub_long_branch_any_any;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_long_branch_any_any) / sizeof (insn_sequence);
|
||||
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_arm_thumb:
|
||||
template = elf32_arm_stub_long_branch_v4t_arm_thumb;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_long_branch_v4t_arm_thumb) / sizeof (insn_sequence);
|
||||
break;
|
||||
case arm_stub_long_branch_thumb_only:
|
||||
template = elf32_arm_stub_long_branch_thumb_only;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_long_branch_thumb_only) / sizeof (insn_sequence);
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_thumb_arm:
|
||||
template = elf32_arm_stub_long_branch_v4t_thumb_arm;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_long_branch_v4t_thumb_arm) / sizeof (insn_sequence);
|
||||
break;
|
||||
case arm_stub_short_branch_v4t_thumb_arm:
|
||||
template = elf32_arm_stub_short_branch_v4t_thumb_arm;
|
||||
template_size = (sizeof(elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_short_branch_v4t_thumb_arm) / sizeof (insn_sequence);
|
||||
break;
|
||||
case arm_stub_long_branch_any_any_pic:
|
||||
template = elf32_arm_stub_long_branch_any_any_pic;
|
||||
template_size = (sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (bfd_vma)) * 4;
|
||||
template_size = sizeof (elf32_arm_stub_long_branch_any_any_pic) / sizeof (insn_sequence);
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
|
@ -3286,10 +3288,35 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
|
|||
}
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < (template_size / 4); i++)
|
||||
size += 4;
|
||||
for (i = 0; i < template_size; i++)
|
||||
{
|
||||
switch(template[i].type)
|
||||
{
|
||||
case THUMB16_TYPE:
|
||||
size += 2;
|
||||
break;
|
||||
|
||||
case ARM_TYPE:
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
case DATA_TYPE:
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
stub_entry->stub_size = size;
|
||||
stub_entry->stub_template = template;
|
||||
stub_entry->stub_template_size = template_size;
|
||||
|
||||
size = (size + 7) & ~7;
|
||||
stub_entry->stub_sec->size += size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -11665,6 +11692,11 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
|
|||
bfd_vma addr;
|
||||
char *stub_name;
|
||||
output_arch_syminfo *osi;
|
||||
const insn_sequence *template;
|
||||
enum stub_insn_type prev_type;
|
||||
int size;
|
||||
int i;
|
||||
enum map_symbol_type sym_type;
|
||||
|
||||
/* Massage our args to the form they really have. */
|
||||
stub_entry = (struct elf32_arm_stub_hash_entry *) gen_entry;
|
||||
|
@ -11683,62 +11715,70 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
|
|||
addr = (bfd_vma) stub_entry->stub_offset;
|
||||
stub_name = stub_entry->output_name;
|
||||
|
||||
switch (stub_entry->stub_type)
|
||||
template = stub_entry->stub_template;
|
||||
switch(template[0].type)
|
||||
{
|
||||
case arm_stub_long_branch_any_any:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 8))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 4))
|
||||
case ARM_TYPE:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, stub_entry->stub_size))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_arm_thumb:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_long_branch_thumb_only:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 16))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 12))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_long_branch_v4t_thumb_arm:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 20))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_short_branch_v4t_thumb_arm:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_long_branch_any_any_pic:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 8))
|
||||
case THUMB16_TYPE:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1,
|
||||
stub_entry->stub_size))
|
||||
return FALSE;
|
||||
break;
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
}
|
||||
|
||||
prev_type = DATA_TYPE;
|
||||
size = 0;
|
||||
for (i = 0; i < stub_entry->stub_template_size; i++)
|
||||
{
|
||||
switch(template[i].type)
|
||||
{
|
||||
case ARM_TYPE:
|
||||
sym_type = ARM_MAP_ARM;
|
||||
break;
|
||||
|
||||
case THUMB16_TYPE:
|
||||
sym_type = ARM_MAP_THUMB;
|
||||
break;
|
||||
|
||||
case DATA_TYPE:
|
||||
sym_type = ARM_MAP_DATA;
|
||||
break;
|
||||
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
}
|
||||
|
||||
if (template[i].type != prev_type)
|
||||
{
|
||||
prev_type = template[i].type;
|
||||
if (!elf32_arm_output_map_sym (osi, sym_type, addr + size))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch(template[i].type)
|
||||
{
|
||||
case ARM_TYPE:
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
case THUMB16_TYPE:
|
||||
size += 2;
|
||||
break;
|
||||
|
||||
case DATA_TYPE:
|
||||
size += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
BFD_FAIL ();
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
2009-02-23 Christophe Lyon <christophe.lyon@st.com>
|
||||
|
||||
* ld-arm/arm-elf.exp: Add new farcall-thumb-arm-be8 test.
|
||||
* ld-arm/farcall-thumb-arm-be8.d: New expected result.
|
||||
* ld-arm/farcall-arm-arm-be8.d: Replace wildcards by instructions.
|
||||
|
||||
2009-02-23 Christophe Lyon <christophe.lyon@st.com>
|
||||
|
||||
* ld-arm/arm-elf.exp: Rewrite non-EABI variants of
|
||||
thumb2-bl-as-thumb1-bad and thumb2-bl-bad tests, which now
|
||||
pass. farcall-thumb-thumb now passes in EABI mode.
|
||||
|
|
|
@ -297,6 +297,9 @@ set armeabitests {
|
|||
{"Thumb-ARM farcall" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W" {farcall-thumb-arm.s}
|
||||
{{objdump -d farcall-thumb-arm.d}}
|
||||
"farcall-thumb-arm"}
|
||||
{"Thumb-ARM farcall (BE8)" "-Ttext 0x1000 --section-start .foo=0x2001014 -EB --be8" "-W -EB" {farcall-thumb-arm.s}
|
||||
{{objdump -d farcall-thumb-arm-be8.d}}
|
||||
"farcall-thumb-arm"}
|
||||
{"Thumb-ARM (short) call" "-Ttext 0x1000 --section-start .foo=0x0002014" "-W" {farcall-thumb-arm-short.s}
|
||||
{{objdump -d farcall-thumb-arm-short.d}}
|
||||
"farcall-thumb-arm-short"}
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
Disassembly of section .text:
|
||||
|
||||
00001000 <__bar_veneer>:
|
||||
1000: 04f01fe5 .*
|
||||
1000: 04f01fe5 ldr pc, \[pc, #-4\] ; 1004 <__bar_veneer\+0x4>
|
||||
1004: 02001020 .word 0x02001020
|
||||
|
||||
00001008 <_start>:
|
||||
1008: fcffffeb .*
|
||||
1008: fcffffeb bl 1000 <__bar_veneer>
|
||||
Disassembly of section .foo:
|
||||
|
||||
02001020 <bar>:
|
||||
2001020: 1eff2fe1 .*
|
||||
2001020: 1eff2fe1 bx lr
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
.*: file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00001000 <__bar_from_thumb>:
|
||||
1000: 7847 bx pc
|
||||
1002: c046 nop.*
|
||||
1004: 04f01fe5 ldr pc, \[pc, #-4\] ; 1008 <__bar_from_thumb\+0x8>
|
||||
1008: 02001014 .word 0x02001014
|
||||
100c: 00000000 .word 0x00000000
|
||||
|
||||
00001010 <_start>:
|
||||
1010: fff7 f6ff bl 1000 <__bar_from_thumb>
|
||||
Disassembly of section .foo:
|
||||
|
||||
02001014 <bar>:
|
||||
2001014: 1eff2fe1 bx lr
|
Loading…
Reference in New Issue