From a4fd1a8ee5a761bb9163bc7e1dacf14313860303 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Fri, 18 Aug 2006 15:00:18 +0000 Subject: [PATCH] 2006-08-18 Paul Brook 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. --- bfd/ChangeLog | 14 +++ bfd/elf32-arm.c | 177 +++++++++++++++++++++++---- ld/ChangeLog | 5 + ld/emultempl/armelf.em | 6 +- ld/testsuite/ChangeLog | 7 ++ ld/testsuite/ld-arm/arm-elf.exp | 6 +- ld/testsuite/ld-arm/armthumb-lib.d | 44 +++++++ ld/testsuite/ld-arm/armthumb-lib.sym | 18 +++ 8 files changed, 248 insertions(+), 29 deletions(-) create mode 100644 ld/testsuite/ld-arm/armthumb-lib.d create mode 100644 ld/testsuite/ld-arm/armthumb-lib.sym diff --git a/bfd/ChangeLog b/bfd/ChangeLog index affb063704..6136a0c3e9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2006-08-18 Paul Brook + + * 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 * elf64-ppc.c (create_linkage_sections): Align .glink to 8 bytes. diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index a458d46ce9..3472da260b 100644 --- a/bfd/elf32-arm.c +++ b/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 diff --git a/ld/ChangeLog b/ld/ChangeLog index 49e65fc172..698f0eb27f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2006-08-18 Paul Brook + + * emultempl/armelf.em (arm_elf_before_allocation): Call + gld${EMULATION_NAME}_before_allocation after setting interworking bfd. + 2006-08-17 Pedro Alves * pe-dll.c (autofilter_symbolprefixlist): Remove .idata$. diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index bd74ab5705..17fc522c74 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -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 */ { diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index ac678c3034..eca6c30aa8 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2006-08-18 Paul Brook + + * 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 PR ld/3052 diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index e8e6a85246..eee320433c 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -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}} diff --git a/ld/testsuite/ld-arm/armthumb-lib.d b/ld/testsuite/ld-arm/armthumb-lib.d new file mode 100644 index 0000000000..66e0590487 --- /dev/null +++ b/ld/testsuite/ld-arm/armthumb-lib.d @@ -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: + +.* : + .*: 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\) + +.* : + .*: e59fc004 ldr ip, \[pc, #4\] ; 33c + .*: e08cc00f add ip, ip, pc + .*: e12fff1c bx ip + .*: ffffffe5 .* diff --git a/ld/testsuite/ld-arm/armthumb-lib.sym b/ld/testsuite/ld-arm/armthumb-lib.sym new file mode 100644 index 0000000000..d05794c093 --- /dev/null +++ b/ld/testsuite/ld-arm/armthumb-lib.sym @@ -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