mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
bfd/
* elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define. (elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch. (arm_type_of_stub): Handle armv4t short branches. Update prototype. (arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch. (arm_build_one_stub): Likewise. (arm_size_one_stub): Likewise. (elf32_arm_size_stubs): Use new arm_type_of_stub prototype. (arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch. ld/testsuite/ * ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test. * ld-arm/farcall-group2.s: Fix comment. * ld-arm/farcall-thumb-arm-short.d: New test. * ld-arm/farcall-thumb-arm-short.s: New test.
This commit is contained in:
parent
8716772cc5
commit
c820be077e
@ -1,3 +1,15 @@
|
||||
2008-08-25 Christophe Lyon <christophe.lyon@st.com>
|
||||
|
||||
* elf32-arm.c (arm_thumb_arm_v4t_short_branch_stub): Define.
|
||||
(elf32_arm_stub_type): Add arm_thumb_arm_v4t_stub_short_branch.
|
||||
(arm_type_of_stub): Handle armv4t short branches. Update
|
||||
prototype.
|
||||
(arm_stub_is_thumb): Handle arm_thumb_arm_v4t_stub_short_branch.
|
||||
(arm_build_one_stub): Likewise.
|
||||
(arm_size_one_stub): Likewise.
|
||||
(elf32_arm_size_stubs): Use new arm_type_of_stub prototype.
|
||||
(arm_map_one_stub): Handle arm_thumb_arm_v4t_stub_short_branch.
|
||||
|
||||
2008-08-24 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Do proper
|
||||
|
@ -2045,6 +2045,13 @@ static const bfd_vma arm_thumb_arm_v4t_long_branch_stub[] =
|
||||
0x00000000, /* dcd R_ARM_ABS32(X) */
|
||||
};
|
||||
|
||||
static const bfd_vma arm_thumb_arm_v4t_short_branch_stub[] =
|
||||
{
|
||||
0x46c04778, /* bx pc */
|
||||
/* nop */
|
||||
0xea000000, /* b (X) */
|
||||
};
|
||||
|
||||
static const bfd_vma arm_pic_long_branch_stub[] =
|
||||
{
|
||||
0xe59fc000, /* ldr r12, [pc] */
|
||||
@ -2063,6 +2070,7 @@ enum elf32_arm_stub_type
|
||||
arm_thumb_v4t_stub_long_branch,
|
||||
arm_thumb_thumb_stub_long_branch,
|
||||
arm_thumb_arm_v4t_stub_long_branch,
|
||||
arm_thumb_arm_v4t_stub_short_branch,
|
||||
arm_stub_pic_long_branch,
|
||||
};
|
||||
|
||||
@ -2738,6 +2746,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_type stub_type)
|
||||
{
|
||||
case arm_thumb_thumb_stub_long_branch:
|
||||
case arm_thumb_arm_v4t_stub_long_branch:
|
||||
case arm_thumb_arm_v4t_stub_short_branch:
|
||||
return TRUE;
|
||||
case arm_stub_none:
|
||||
BFD_FAIL ();
|
||||
@ -2756,7 +2765,10 @@ arm_type_of_stub (struct bfd_link_info *info,
|
||||
const Elf_Internal_Rela *rel,
|
||||
unsigned char st_type,
|
||||
struct elf32_arm_link_hash_entry *hash,
|
||||
bfd_vma destination)
|
||||
bfd_vma destination,
|
||||
asection *sym_sec,
|
||||
bfd *input_bfd,
|
||||
const char *name)
|
||||
{
|
||||
bfd_vma location;
|
||||
bfd_signed_vma branch_offset;
|
||||
@ -2826,6 +2838,16 @@ arm_type_of_stub (struct bfd_link_info *info,
|
||||
else
|
||||
{
|
||||
/* Thumb to arm. */
|
||||
if (sym_sec != NULL
|
||||
&& sym_sec->owner != NULL
|
||||
&& !INTERWORK_FLAG (sym_sec->owner))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B(%s): warning: interworking not enabled.\n"
|
||||
" first occurrence: %B: Thumb call to ARM"),
|
||||
sym_sec->owner, input_bfd, name);
|
||||
}
|
||||
|
||||
stub_type = (info->shared | globals->pic_veneer)
|
||||
? ((globals->use_blx)
|
||||
? arm_stub_pic_long_branch
|
||||
@ -2833,6 +2855,12 @@ arm_type_of_stub (struct bfd_link_info *info,
|
||||
: (globals->use_blx)
|
||||
? arm_stub_long_branch
|
||||
: arm_thumb_arm_v4t_stub_long_branch;
|
||||
|
||||
/* Handle v4t short branches. */
|
||||
if ((stub_type == arm_thumb_arm_v4t_stub_long_branch)
|
||||
&& (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET)
|
||||
&& (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET))
|
||||
stub_type = arm_thumb_arm_v4t_stub_short_branch;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2841,8 +2869,19 @@ arm_type_of_stub (struct bfd_link_info *info,
|
||||
if (st_type == STT_ARM_TFUNC)
|
||||
{
|
||||
/* Arm to thumb. */
|
||||
/* We have an extra 2-bytes reach because of the mode change
|
||||
(bit 24 (H) of BLX encoding). */
|
||||
|
||||
if (sym_sec != NULL
|
||||
&& sym_sec->owner != NULL
|
||||
&& !INTERWORK_FLAG (sym_sec->owner))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B(%s): warning: interworking not enabled.\n"
|
||||
" first occurrence: %B: Thumb call to ARM"),
|
||||
sym_sec->owner, input_bfd, name);
|
||||
}
|
||||
|
||||
/* We have an extra 2-bytes reach because of
|
||||
the mode change (bit 24 (H) of BLX encoding). */
|
||||
if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2)
|
||||
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)
|
||||
|| !globals->use_blx)
|
||||
@ -3098,6 +3137,10 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
template = arm_thumb_arm_v4t_long_branch_stub;
|
||||
template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_thumb_arm_v4t_stub_short_branch:
|
||||
template = arm_thumb_arm_v4t_short_branch_stub;
|
||||
template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_pic_long_branch:
|
||||
template = arm_pic_long_branch_stub;
|
||||
template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
@ -3147,6 +3190,19 @@ arm_build_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
stub_bfd, stub_sec, stub_sec->contents,
|
||||
stub_entry->stub_offset + 16, sym_value, 0);
|
||||
break;
|
||||
case arm_thumb_arm_v4t_stub_short_branch:
|
||||
{
|
||||
long int rel_offset;
|
||||
static const insn32 t2a3_b_insn = 0xea000000;
|
||||
|
||||
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_pic_long_branch:
|
||||
/* We want the value relative to the address 8 bytes from the
|
||||
start of the stub. */
|
||||
@ -3197,6 +3253,10 @@ arm_size_one_stub (struct bfd_hash_entry *gen_entry,
|
||||
template = arm_thumb_arm_v4t_long_branch_stub;
|
||||
template_size = (sizeof (arm_thumb_arm_v4t_long_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_thumb_arm_v4t_stub_short_branch:
|
||||
template = arm_thumb_arm_v4t_short_branch_stub;
|
||||
template_size = (sizeof(arm_thumb_arm_v4t_short_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
break;
|
||||
case arm_stub_pic_long_branch:
|
||||
template = arm_pic_long_branch_stub;
|
||||
template_size = (sizeof (arm_pic_long_branch_stub) / sizeof (bfd_vma)) * 4;
|
||||
@ -3603,7 +3663,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
|
||||
|
||||
/* Determine what (if any) linker stub is needed. */
|
||||
stub_type = arm_type_of_stub (info, section, irela, st_type,
|
||||
hash, destination);
|
||||
hash, destination, sym_sec,
|
||||
input_bfd, sym_name);
|
||||
if (stub_type == arm_stub_none)
|
||||
continue;
|
||||
|
||||
@ -11205,6 +11266,12 @@ arm_map_one_stub (struct bfd_hash_entry * gen_entry,
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_DATA, addr + 16))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_thumb_arm_v4t_stub_short_branch:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr | 1, 8))
|
||||
return FALSE;
|
||||
if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr + 4))
|
||||
return FALSE;
|
||||
break;
|
||||
case arm_stub_pic_long_branch:
|
||||
if (!elf32_arm_output_stub_sym (osi, stub_name, addr, 12))
|
||||
return FALSE;
|
||||
|
@ -1,3 +1,10 @@
|
||||
2008-08-26 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
|
||||
* ld-arm/farcall-group2.s: Fix comment.
|
||||
* ld-arm/farcall-thumb-arm-short.d: New test.
|
||||
* ld-arm/farcall-thumb-arm-short.s: New test.
|
||||
|
||||
2008-08-22 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* ld-x86-64/dwarfreloc.exp, ld-x86-64/dwarfreloc.rd,
|
||||
|
@ -260,6 +260,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 (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"}
|
||||
{"Thumb-ARM farcall with BLX" "-Ttext 0x1000 --section-start .foo=0x2001014" "-W -march=armv5t" {farcall-thumb-arm.s}
|
||||
{{objdump -d farcall-thumb-arm-blx.d}}
|
||||
"farcall-thumb-arm-blx"}
|
||||
|
@ -1,8 +1,5 @@
|
||||
|
||||
@ Test to ensure that ARM calls exceeding 32Mb generate stubs.
|
||||
|
||||
@ We will place the section .foo at 0x2000.
|
||||
|
||||
.text
|
||||
myfunc:
|
||||
bl bar3
|
||||
|
14
ld/testsuite/ld-arm/farcall-thumb-arm-short.d
Normal file
14
ld/testsuite/ld-arm/farcall-thumb-arm-short.d
Normal file
@ -0,0 +1,14 @@
|
||||
.*: file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00001000 <__bar_from_thumb>:
|
||||
1000: 4778 bx pc
|
||||
1002: 46c0 nop \(mov r8, r8\)
|
||||
1004: ea000402 b 2014 <bar>
|
||||
00001008 <_start>:
|
||||
1008: f7ff fffa bl 1000 <__bar_from_thumb>
|
||||
Disassembly of section .foo:
|
||||
|
||||
00002014 <bar>:
|
||||
2014: e12fff1e bx lr
|
21
ld/testsuite/ld-arm/farcall-thumb-arm-short.s
Normal file
21
ld/testsuite/ld-arm/farcall-thumb-arm-short.s
Normal file
@ -0,0 +1,21 @@
|
||||
@ Test to ensure that a Thumb to ARM call within 4Mb does not generate a stub.
|
||||
|
||||
.global _start
|
||||
.syntax unified
|
||||
|
||||
@ We will place the section .text at 0x1000.
|
||||
|
||||
.text
|
||||
.thumb_func
|
||||
_start:
|
||||
bl bar
|
||||
|
||||
@ We will place the section .foo at 0x2014.
|
||||
|
||||
.section .foo, "xa"
|
||||
|
||||
.arm
|
||||
.type bar, %function
|
||||
bar:
|
||||
bx lr
|
||||
|
Loading…
Reference in New Issue
Block a user