2006-08-18 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Fri, 18 Aug 2006 15:00:18 +0000 (15:00 +0000)
committerPaul Brook <paul@codesourcery.com>
Fri, 18 Aug 2006 15:00:18 +0000 (15:00 +0000)
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
bfd/elf32-arm.c
ld/ChangeLog
ld/emultempl/armelf.em
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/armthumb-lib.d [new file with mode: 0644]
ld/testsuite/ld-arm/armthumb-lib.sym [new file with mode: 0644]

index affb063..6136a0c 100644 (file)
@@ -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.
 2006-08-17  Alan Modra  <amodra@bigpond.net.au>
 
        * elf64-ppc.c (create_linkage_sections): Align .glink to 8 bytes.
index a458d46..3472da2 100644 (file)
@@ -2092,6 +2092,10 @@ struct elf32_arm_link_hash_entry
 #define GOT_TLS_GD     2
 #define GOT_TLS_IE     4
     unsigned char tls_type;
 #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.  */
   };
 
 /* 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->tls_type = GOT_UNKNOWN;
       ret->plt_thumb_refcount = 0;
       ret->plt_got_offset = -1;
+      ret->export_glue = NULL;
     }
 
   return (struct bfd_hash_entry *) ret;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -2581,7 +2586,9 @@ bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info * info)
   return TRUE;
 }
 
   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)
 {
 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);
     {
       /* 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.
     }
 
   /* 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;
 
   else
     globals->arm_glue_size += ARM2THUMB_STATIC_GLUE_SIZE;
 
-  return;
+  return myh;
 }
 
 static void
 }
 
 static void
@@ -3194,30 +3201,25 @@ elf32_thumb_to_arm_stub (struct bfd_link_info * info,
   return TRUE;
 }
 
   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;
   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)
   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);
 
 
   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;
   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)
     {
 
   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);
 
 
   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;
 
   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;
 }
 
   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
 /* 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;
 
   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;
 
   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
   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
 
 #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, 
 
 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
 {
   /* 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;
      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
 }
 
 static bfd_boolean
index 49e65fc..698f0eb 100644 (file)
@@ -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$.
 2006-08-17  Pedro Alves  <pedro_alves@portugalmail.pt>
 
        * pe-dll.c (autofilter_symbolprefixlist): Remove .idata$.
index bd74ab5..17fc522 100644 (file)
@@ -103,9 +103,6 @@ arm_elf_before_allocation (void)
 {
   bfd *tem;
 
 {
   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.  */
   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.  */
 
     }
   /* 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  */
   {
   /* Here we rummage through the found bfds to collect glue information.  */
   /* FIXME: should this be based on a command line option? krk@cygnus.com  */
   {
index ac678c3..eca6c30 100644 (file)
@@ -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
 2006-08-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/3052
index e8e6a85..eee3204 100644 (file)
@@ -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"}
     {"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}}
      {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 (file)
index 0000000..66e0590
--- /dev/null
@@ -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        .*
diff --git a/ld/testsuite/ld-arm/armthumb-lib.sym b/ld/testsuite/ld-arm/armthumb-lib.sym
new file mode 100644 (file)
index 0000000..d05794c
--- /dev/null
@@ -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