2006-08-18 Paul Brook <paul@codesourcery.com>
bfd/ * elf32-arm.c (elf32_arm_link_hash_entry): Add export_glue. (elf32_arm_link_hash_newfunc): Initialize export_glue. (record_arm_to_thumb_glue): Return stub symbol. (elf32_arm_create_thumb_stub): New function. (elf32_arm_to_thumb_stub): Use it. (elf32_arm_to_thumb_export_stub): New function. (elf32_arm_begin_write_processing): New function. (allocate_dynrelocs): Allocate Arm stubs. (elf_backend_begin_write_processing): Define. (elf32_arm_symbian_begin_write_processing): Remove ATTRIBUTE_UNUSED. Call elf32_arm_begin_write_processing. ld/ * emultempl/armelf.em (arm_elf_before_allocation): Call gld${EMULATION_NAME}_before_allocation after setting interworking bfd. ld/testsuite/ * ld-arm/arm-elf.exp (armelftests): Add armthumb-lib.so. Add -use-blx to mixed-lib.so * ld-arm/armthumb-lib.d: New file. * ld-arm/armthumb-lib.sym: New file.
This commit is contained in:
parent
7c9e8d9811
commit
a4fd1a8ee5
8 changed files with 248 additions and 29 deletions
|
@ -1,3 +1,17 @@
|
|||
2006-08-18 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* elf32-arm.c (elf32_arm_link_hash_entry): Add export_glue.
|
||||
(elf32_arm_link_hash_newfunc): Initialize export_glue.
|
||||
(record_arm_to_thumb_glue): Return stub symbol.
|
||||
(elf32_arm_create_thumb_stub): New function.
|
||||
(elf32_arm_to_thumb_stub): Use it.
|
||||
(elf32_arm_to_thumb_export_stub): New function.
|
||||
(elf32_arm_begin_write_processing): New function.
|
||||
(allocate_dynrelocs): Allocate Arm stubs.
|
||||
(elf_backend_begin_write_processing): Define.
|
||||
(elf32_arm_symbian_begin_write_processing): Remove ATTRIBUTE_UNUSED.
|
||||
Call elf32_arm_begin_write_processing.
|
||||
|
||||
2006-08-17 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf64-ppc.c (create_linkage_sections): Align .glink to 8 bytes.
|
||||
|
|
177
bfd/elf32-arm.c
177
bfd/elf32-arm.c
|
@ -2092,6 +2092,10 @@ struct elf32_arm_link_hash_entry
|
|||
#define GOT_TLS_GD 2
|
||||
#define GOT_TLS_IE 4
|
||||
unsigned char tls_type;
|
||||
|
||||
/* The symbol marking the real symbol location for exported thumb
|
||||
symbols with Arm stubs. */
|
||||
struct elf_link_hash_entry *export_glue;
|
||||
};
|
||||
|
||||
/* Traverse an arm ELF linker hash table. */
|
||||
|
@ -2203,6 +2207,7 @@ elf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry,
|
|||
ret->tls_type = GOT_UNKNOWN;
|
||||
ret->plt_thumb_refcount = 0;
|
||||
ret->plt_got_offset = -1;
|
||||
ret->export_glue = NULL;
|
||||
}
|
||||
|
||||
return (struct bfd_hash_entry *) ret;
|
||||
|
@ -2581,7 +2586,9 @@ bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info * info)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
/* Allocate space and symbols for calling a Thumb function from Arm mode.
|
||||
returns the symbol identifying teh stub. */
|
||||
static struct elf_link_hash_entry *
|
||||
record_arm_to_thumb_glue (struct bfd_link_info * link_info,
|
||||
struct elf_link_hash_entry * h)
|
||||
{
|
||||
|
@ -2616,7 +2623,7 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
|
|||
{
|
||||
/* We've already seen this guy. */
|
||||
free (tmp_name);
|
||||
return;
|
||||
return myh;
|
||||
}
|
||||
|
||||
/* The only trick here is using hash_table->arm_glue_size as the value.
|
||||
|
@ -2639,7 +2646,7 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info,
|
|||
else
|
||||
globals->arm_glue_size += ARM2THUMB_STATIC_GLUE_SIZE;
|
||||
|
||||
return;
|
||||
return myh;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3194,30 +3201,25 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Arm code calling a Thumb function. */
|
||||
/* Populate an Arm to Thumb stub. Returns the stub symbol. */
|
||||
|
||||
static int
|
||||
elf32_arm_to_thumb_stub (struct bfd_link_info * info,
|
||||
const char * name,
|
||||
bfd * input_bfd,
|
||||
bfd * output_bfd,
|
||||
asection * input_section,
|
||||
bfd_byte * hit_data,
|
||||
asection * sym_sec,
|
||||
bfd_vma offset,
|
||||
bfd_signed_vma addend,
|
||||
bfd_vma val)
|
||||
static struct elf_link_hash_entry *
|
||||
elf32_arm_create_thumb_stub (struct bfd_link_info * info,
|
||||
const char * name,
|
||||
bfd * input_bfd,
|
||||
bfd * output_bfd,
|
||||
asection * sym_sec,
|
||||
bfd_vma val,
|
||||
asection *s)
|
||||
{
|
||||
unsigned long int tmp;
|
||||
bfd_vma my_offset;
|
||||
asection * s;
|
||||
long int ret_offset;
|
||||
struct elf_link_hash_entry * myh;
|
||||
struct elf32_arm_link_hash_table * globals;
|
||||
|
||||
myh = find_arm_glue (info, name, input_bfd);
|
||||
if (myh == NULL)
|
||||
return FALSE;
|
||||
return NULL;
|
||||
|
||||
globals = elf32_arm_hash_table (info);
|
||||
|
||||
|
@ -3225,11 +3227,6 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
|
|||
BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
|
||||
|
||||
my_offset = myh->root.u.def.value;
|
||||
s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
|
||||
ARM2THUMB_GLUE_SECTION_NAME);
|
||||
BFD_ASSERT (s != NULL);
|
||||
BFD_ASSERT (s->contents != NULL);
|
||||
BFD_ASSERT (s->output_section != NULL);
|
||||
|
||||
if ((my_offset & 0x01) == 0x01)
|
||||
{
|
||||
|
@ -3283,6 +3280,47 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
|
|||
|
||||
BFD_ASSERT (my_offset <= globals->arm_glue_size);
|
||||
|
||||
return myh;
|
||||
}
|
||||
|
||||
/* Arm code calling a Thumb function. */
|
||||
|
||||
static int
|
||||
elf32_arm_to_thumb_stub (struct bfd_link_info * info,
|
||||
const char * name,
|
||||
bfd * input_bfd,
|
||||
bfd * output_bfd,
|
||||
asection * input_section,
|
||||
bfd_byte * hit_data,
|
||||
asection * sym_sec,
|
||||
bfd_vma offset,
|
||||
bfd_signed_vma addend,
|
||||
bfd_vma val)
|
||||
{
|
||||
unsigned long int tmp;
|
||||
bfd_vma my_offset;
|
||||
asection * s;
|
||||
long int ret_offset;
|
||||
struct elf_link_hash_entry * myh;
|
||||
struct elf32_arm_link_hash_table * globals;
|
||||
|
||||
globals = elf32_arm_hash_table (info);
|
||||
|
||||
BFD_ASSERT (globals != NULL);
|
||||
BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
|
||||
|
||||
s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
|
||||
ARM2THUMB_GLUE_SECTION_NAME);
|
||||
BFD_ASSERT (s != NULL);
|
||||
BFD_ASSERT (s->contents != NULL);
|
||||
BFD_ASSERT (s->output_section != NULL);
|
||||
|
||||
myh = elf32_arm_create_thumb_stub (info, name, input_bfd, output_bfd,
|
||||
sym_sec, val, s);
|
||||
if (!myh)
|
||||
return FALSE;
|
||||
|
||||
my_offset = myh->root.u.def.value;
|
||||
tmp = bfd_get_32 (input_bfd, hit_data);
|
||||
tmp = tmp & 0xFF000000;
|
||||
|
||||
|
@ -3302,6 +3340,63 @@ elf32_arm_to_thumb_stub (struct bfd_link_info * info,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Populate Arm stub for an exported Thumb function. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf)
|
||||
{
|
||||
struct bfd_link_info * info = (struct bfd_link_info *) inf;
|
||||
asection * s;
|
||||
struct elf_link_hash_entry * myh;
|
||||
struct elf32_arm_link_hash_entry *eh;
|
||||
struct elf32_arm_link_hash_table * globals;
|
||||
asection *sec;
|
||||
bfd_vma val;
|
||||
|
||||
eh = elf32_arm_hash_entry(h);
|
||||
/* Allocate stubs for exported Thumb functions on v4t. */
|
||||
if (eh->export_glue == NULL)
|
||||
return TRUE;
|
||||
|
||||
globals = elf32_arm_hash_table (info);
|
||||
|
||||
BFD_ASSERT (globals != NULL);
|
||||
BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
|
||||
|
||||
s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
|
||||
ARM2THUMB_GLUE_SECTION_NAME);
|
||||
BFD_ASSERT (s != NULL);
|
||||
BFD_ASSERT (s->contents != NULL);
|
||||
BFD_ASSERT (s->output_section != NULL);
|
||||
|
||||
sec = eh->export_glue->root.u.def.section;
|
||||
val = eh->export_glue->root.u.def.value + sec->output_offset
|
||||
+ sec->output_section->vma;
|
||||
myh = elf32_arm_create_thumb_stub (info, h->root.root.string,
|
||||
h->root.u.def.section->owner,
|
||||
globals->obfd, sec, val, s);
|
||||
BFD_ASSERT (myh);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Generate Arm stubs for exported Thumb symbols. */
|
||||
static void
|
||||
elf32_arm_begin_write_processing (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *link_info)
|
||||
{
|
||||
struct elf32_arm_link_hash_table * globals;
|
||||
|
||||
if (!link_info)
|
||||
return;
|
||||
|
||||
globals = elf32_arm_hash_table (link_info);
|
||||
if (globals->use_blx)
|
||||
return;
|
||||
|
||||
elf_link_hash_traverse (&globals->root, elf32_arm_to_thumb_export_stub,
|
||||
link_info);
|
||||
}
|
||||
|
||||
/* Some relocations map to different relocations depending on the
|
||||
target. Return the real relocation. */
|
||||
static int
|
||||
|
@ -7465,6 +7560,36 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
|
|||
else
|
||||
h->got.offset = (bfd_vma) -1;
|
||||
|
||||
/* Allocate stubs for exported Thumb functions on v4t. */
|
||||
if (!htab->use_blx && h->dynindx != -1
|
||||
&& ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
|
||||
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
|
||||
{
|
||||
struct elf_link_hash_entry * th;
|
||||
struct bfd_link_hash_entry * bh;
|
||||
struct elf_link_hash_entry * myh;
|
||||
char name[1024];
|
||||
asection *s;
|
||||
bh = NULL;
|
||||
/* Create a new symbol to regist the real location of the function. */
|
||||
s = h->root.u.def.section;
|
||||
sprintf(name, "__real_%s", h->root.root.string);
|
||||
_bfd_generic_link_add_one_symbol (info, s->owner,
|
||||
name, BSF_GLOBAL, s,
|
||||
h->root.u.def.value,
|
||||
NULL, TRUE, FALSE, &bh);
|
||||
|
||||
myh = (struct elf_link_hash_entry *) bh;
|
||||
myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC);
|
||||
myh->forced_local = 1;
|
||||
eh->export_glue = myh;
|
||||
th = record_arm_to_thumb_glue (info, h);
|
||||
/* Point the symbol at the stub. */
|
||||
h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
|
||||
h->root.u.def.section = th->root.u.def.section;
|
||||
h->root.u.def.value = th->root.u.def.value & ~1;
|
||||
}
|
||||
|
||||
if (eh->relocs_copied == NULL)
|
||||
return TRUE;
|
||||
|
||||
|
@ -9327,6 +9452,8 @@ const struct elf_size_info elf32_arm_size_info = {
|
|||
elf32_arm_additional_program_headers
|
||||
#define elf_backend_output_arch_local_syms \
|
||||
elf32_arm_output_arch_local_syms
|
||||
#define elf_backend_begin_write_processing \
|
||||
elf32_arm_begin_write_processing
|
||||
|
||||
#define elf_backend_can_refcount 1
|
||||
#define elf_backend_can_gc_sections 1
|
||||
|
@ -9468,8 +9595,7 @@ elf32_arm_symbian_special_sections[] =
|
|||
|
||||
static void
|
||||
elf32_arm_symbian_begin_write_processing (bfd *abfd,
|
||||
struct bfd_link_info *link_info
|
||||
ATTRIBUTE_UNUSED)
|
||||
struct bfd_link_info *link_info)
|
||||
{
|
||||
/* BPABI objects are never loaded directly by an OS kernel; they are
|
||||
processed by a postlinker first, into an OS-specific format. If
|
||||
|
@ -9480,6 +9606,7 @@ elf32_arm_symbian_begin_write_processing (bfd *abfd,
|
|||
recognize that the program headers should not be mapped into any
|
||||
loadable segment. */
|
||||
abfd->flags &= ~D_PAGED;
|
||||
elf32_arm_begin_write_processing(abfd, link_info);
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2006-08-18 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* emultempl/armelf.em (arm_elf_before_allocation): Call
|
||||
gld${EMULATION_NAME}_before_allocation after setting interworking bfd.
|
||||
|
||||
2006-08-17 Pedro Alves <pedro_alves@portugalmail.pt>
|
||||
|
||||
* pe-dll.c (autofilter_symbolprefixlist): Remove .idata$.
|
||||
|
|
|
@ -103,9 +103,6 @@ arm_elf_before_allocation (void)
|
|||
{
|
||||
bfd *tem;
|
||||
|
||||
/* Call the standard elf routine. */
|
||||
gld${EMULATION_NAME}_before_allocation ();
|
||||
|
||||
if (link_info.input_bfds != NULL)
|
||||
{
|
||||
/* The interworking bfd must be the last one in the link. */
|
||||
|
@ -126,6 +123,9 @@ arm_elf_before_allocation (void)
|
|||
}
|
||||
/* We should be able to set the size of the interworking stub section. */
|
||||
|
||||
/* Call the standard elf routine. */
|
||||
gld${EMULATION_NAME}_before_allocation ();
|
||||
|
||||
/* Here we rummage through the found bfds to collect glue information. */
|
||||
/* FIXME: should this be based on a command line option? krk@cygnus.com */
|
||||
{
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2006-08-18 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* ld-arm/arm-elf.exp (armelftests): Add armthumb-lib.so. Add
|
||||
-use-blx to mixed-lib.so
|
||||
* ld-arm/armthumb-lib.d: New file.
|
||||
* ld-arm/armthumb-lib.sym: New file.
|
||||
|
||||
2006-08-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/3052
|
||||
|
|
|
@ -77,7 +77,11 @@ set armelftests {
|
|||
{"Non-pcrel function reference" "tmpdir/arm-lib.so" "" {arm-app-abs32.s}
|
||||
{{objdump -fdw arm-app-abs32.d} {objdump -Rw arm-app-abs32.r}}
|
||||
"arm-app-abs32"}
|
||||
{"Mixed ARM/Thumb shared library" "-shared -T arm-lib.ld" ""
|
||||
{"Thumb shared library with ARM entry points" "-shared -T arm-lib.ld" ""
|
||||
{mixed-lib.s}
|
||||
{{objdump -fdw armthumb-lib.d} {readelf -Ds armthumb-lib.sym}}
|
||||
"armthumb-lib.so"}
|
||||
{"Mixed ARM/Thumb shared library" "-shared -T arm-lib.ld -use-blx" ""
|
||||
{mixed-lib.s}
|
||||
{{objdump -fdw mixed-lib.d} {objdump -Rw mixed-lib.r}
|
||||
{readelf -Ds mixed-lib.sym}}
|
||||
|
|
44
ld/testsuite/ld-arm/armthumb-lib.d
Normal file
44
ld/testsuite/ld-arm/armthumb-lib.d
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
tmpdir/armthumb-lib.so: file format elf32-(little|big)arm
|
||||
architecture: arm, flags 0x00000150:
|
||||
HAS_SYMS, DYNAMIC, D_PAGED
|
||||
start address 0x.*
|
||||
|
||||
Disassembly of section .plt:
|
||||
|
||||
.* <.plt>:
|
||||
.*: e52de004 str lr, \[sp, #-4\]!
|
||||
.*: e59fe004 ldr lr, \[pc, #4\] ; .* <\.plt\+0x10>
|
||||
.*: e08fe00e add lr, pc, lr
|
||||
.*: e5bef008 ldr pc, \[lr, #8\]!
|
||||
.*: .*
|
||||
.*: e28fc6.* add ip, pc, #.* ; 0x.*
|
||||
.*: e28cca.* add ip, ip, #.* ; 0x.*
|
||||
.*: e5bcf.* ldr pc, \[ip, #.*\]!
|
||||
Disassembly of section .text:
|
||||
|
||||
.* <lib_func1>:
|
||||
.*: e1a0c00d mov ip, sp
|
||||
.*: e92dd800 stmdb sp!, {fp, ip, lr, pc}
|
||||
.*: ebfffff. bl .* <.text-0x..>
|
||||
.*: e89d6800 ldmia sp, {fp, sp, lr}
|
||||
.*: e12fff1e bx lr
|
||||
.*: e1a00000 nop \(mov r0,r0\)
|
||||
.*: e1a00000 nop \(mov r0,r0\)
|
||||
.*: e1a00000 nop \(mov r0,r0\)
|
||||
|
||||
.* <__real_lib_func2>:
|
||||
.*: 4770 bx lr
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
.*: 46c0 nop \(mov r8, r8\)
|
||||
|
||||
.* <lib_func2>:
|
||||
.*: e59fc004 ldr ip, \[pc, #4\] ; 33c <lib_func2\+0xc>
|
||||
.*: e08cc00f add ip, ip, pc
|
||||
.*: e12fff1c bx ip
|
||||
.*: ffffffe5 .*
|
18
ld/testsuite/ld-arm/armthumb-lib.sym
Normal file
18
ld/testsuite/ld-arm/armthumb-lib.sym
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
Symbol table for image:
|
||||
Num Buc: Value Size Type Bind Vis Ndx Name
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _edata
|
||||
.. ..: .......0 20 FUNC GLOBAL DEFAULT 6 lib_func1
|
||||
.. ..: .......0 2 FUNC GLOBAL DEFAULT 6 lib_func2
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _bss_end__
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_end__
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _stack
|
||||
.. ..: ........ 4 OBJECT GLOBAL DEFAULT 9 data_obj
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start__
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _end
|
||||
.. ..: 00000000 0 NOTYPE GLOBAL DEFAULT UND app_func2
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_end
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT 9 __data_start
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __end__
|
||||
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_start
|
Loading…
Reference in a new issue