2007-04-17 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Tue, 17 Apr 2007 20:09:52 +0000 (20:09 +0000)
committerPaul Brook <paul@codesourcery.com>
Tue, 17 Apr 2007 20:09:52 +0000 (20:09 +0000)
bfd/
* elf.c (_bfd_elf_is_function_type): New function.
* elflink.c (_bfd_elf_merge_symbol): Use bed->is_function_type.
(_bfd_elf_dynamic_symbol_p, _bfd_elf_symbol_refs_local_p,
is_global_data_symbol_definition, elf_link_add_object_symbols): Ditto.
* elf-bfd.h (elf_backend_data): Add is_function_type.
(_bfd_elf_is_function_type): Add prototype.
* elfxx-target.h (elf_backend_is_function_type): Add default
definition.
(elfNN_bed): Add elf_backend_is_function_type.
* elf32-arm.c (elf32_arm_is_function_type): New function.
(elf_backend_is_function_type): Define.

ld/testsuite/
* ld-arm/preempt-app.s: New test.
* ld-arm/preempt-app.sym: New.
* ld-arm/arm-elf.exp: Add preempt-app.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elf32-arm.c
bfd/elflink.c
bfd/elfxx-target.h
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/preempt-app.s [new file with mode: 0644]
ld/testsuite/ld-arm/preempt-app.sym [new file with mode: 0644]

index 7d7838c848bde749439b1cd7e3f5940a739c7150..b670e62c8197e3c1106643a38a52f2aa9d98602f 100644 (file)
@@ -1,3 +1,17 @@
+2007-04-17  Paul Brook  <paul@codesourcery.com>
+
+       * elf.c (_bfd_elf_is_function_type): New function.
+       * elflink.c (_bfd_elf_merge_symbol): Use bed->is_function_type.
+       (_bfd_elf_dynamic_symbol_p, _bfd_elf_symbol_refs_local_p,
+       is_global_data_symbol_definition, elf_link_add_object_symbols): Ditto.
+       * elf-bfd.h (elf_backend_data): Add is_function_type.
+       (_bfd_elf_is_function_type): Add prototype.
+       * elfxx-target.h (elf_backend_is_function_type): Add default
+       definition.
+       (elfNN_bed): Add elf_backend_is_function_type.
+       * elf32-arm.c (elf32_arm_is_function_type): New function.
+       (elf_backend_is_function_type): Define.
+
 2007-04-17  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Put
index 4a01fe6ceb6f91127e72332e17451a3cf7593e68..e9ee29b12c37cb8f413e002782e68651c30ff511 100644 (file)
@@ -1050,6 +1050,9 @@ struct elf_backend_data
   /* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
   bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *);
 
+  /* Return TRUE if type is a function symbol type.  */
+  bfd_boolean (*is_function_type) (unsigned int type);
+
   /* Used to handle bad SHF_LINK_ORDER input.  */
   bfd_error_handler_type link_order_error_handler;
 
@@ -1919,6 +1922,8 @@ extern struct elf_segment_map * _bfd_elf_make_dynamic_segment
 extern bfd_boolean _bfd_elf_map_sections_to_segments
   (bfd *, struct bfd_link_info *);
 
+extern bfd_boolean _bfd_elf_is_function_type (unsigned int);
+
 /* Exported interface for writing elf corefile notes. */
 extern char *elfcore_write_note
   (bfd *, char *, int *, const char *, int, const void *, int);
index 80073022ecbce55ac11aa7dd6514ca3a885e412f..1f3408e32862461f5136c71054cd0e71cad1e3ab 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9167,3 +9167,14 @@ _bfd_elf_set_osabi (bfd * abfd,
 
   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
 }
+
+
+/* Return TRUE for ELF symbol types that represent functions.
+   This is the default version of this function, which is sufficient for
+   most targets.  It returns true if TYPE is STT_FUNC.  */
+
+bfd_boolean
+_bfd_elf_is_function_type (unsigned int type)
+{
+  return (type == STT_FUNC);
+}
index e8be0d5d927da8f83a76040cb13e1a88ec7264be..10a64085f2fd3fb4736a1e0fedb9c6cad6284d52 100644 (file)
@@ -10557,6 +10557,13 @@ elf32_arm_additional_program_headers (bfd *abfd,
     return 0;
 }
 
+/* We have two function types: STT_FUNC and STT_ARM_TFUNC.  */
+static bfd_boolean
+elf32_arm_is_function_type (unsigned int type)
+{
+  return (type == STT_FUNC) || (type == STT_ARM_TFUNC);
+}
+
 /* We use this to override swap_symbol_in and swap_symbol_out.  */
 const struct elf_size_info elf32_arm_size_info = {
   sizeof (Elf32_External_Ehdr),
@@ -10643,6 +10650,7 @@ const struct elf_size_info elf32_arm_size_info = {
   elf32_arm_output_arch_local_syms
 #define elf_backend_begin_write_processing \
     elf32_arm_begin_write_processing
+#define elf_backend_is_function_type           elf32_arm_is_function_type 
 
 #define elf_backend_can_refcount    1
 #define elf_backend_can_gc_sections 1
index 0058002cdafebd7a6ab86aad6d7647f67e9fb834..807455ed948e2268ee1a999e44e5eb8b844d62da 100644 (file)
@@ -947,6 +947,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
            && h->root.type != bfd_link_hash_undefweak
            && h->root.type != bfd_link_hash_common);
 
+  bed = get_elf_backend_data (abfd);
   /* When we try to create a default indirect symbol from the dynamic
      definition with the default version, we skip it if its type and
      the type of existing regular definition mismatch.  We only do it
@@ -961,7 +962,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (olddef || h->root.type == bfd_link_hash_common)
       && ELF_ST_TYPE (sym->st_info) != h->type
       && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-      && h->type != STT_NOTYPE)
+      && h->type != STT_NOTYPE
+      && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
+          && bed->is_function_type (h->type)))
     {
       *skip = TRUE;
       return TRUE;
@@ -1152,6 +1155,11 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (olddef && newdyn)
     oldweak = FALSE;
 
+  /* Allow changes between different types of funciton symbol.  */
+  if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))
+      && bed->is_function_type (h->type))
+    *type_change_ok = TRUE;
+
   /* It's OK to change the type if either the existing symbol or the
      new symbol is weak.  A type change is also OK if the old symbol
      is undefined and the new symbol is defined.  */
@@ -1198,7 +1206,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (sec->flags & SEC_ALLOC) != 0
       && (sec->flags & SEC_LOAD) == 0
       && sym->st_size > 0
-      && ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+      && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
     newdyncommon = TRUE;
   else
     newdyncommon = FALSE;
@@ -1210,14 +1218,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (h->root.u.def.section->flags & SEC_ALLOC) != 0
       && (h->root.u.def.section->flags & SEC_LOAD) == 0
       && h->size > 0
-      && h->type != STT_FUNC)
+      && !bed->is_function_type (h->type))
     olddyncommon = TRUE;
   else
     olddyncommon = FALSE;
 
   /* We now know everything about the old and new symbols.  We ask the
      backend to check if we can merge them.  */
-  bed = get_elf_backend_data (abfd);
   if (bed->merge_symbol
       && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
                             pold_alignment, skip, override,
@@ -1272,7 +1279,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (olddef
          || (h->root.type == bfd_link_hash_common
              && (newweak
-                 || ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
+                 || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
     {
       *override = TRUE;
       newdef = FALSE;
@@ -1327,7 +1334,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (newdef
          || (bfd_is_com_section (sec)
              && (oldweak
-                 || h->type == STT_FUNC)))
+                 || bed->is_function_type (h->type))))
       && olddyn
       && olddef
       && h->def_dynamic)
@@ -2640,6 +2647,8 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
                           bfd_boolean ignore_protected)
 {
   bfd_boolean binding_stays_local_p;
+  const struct elf_backend_data *bed;
+  struct elf_link_hash_table *hash_table;
 
   if (h == NULL)
     return FALSE;
@@ -2665,10 +2674,16 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
       return FALSE;
 
     case STV_PROTECTED:
+      hash_table = elf_hash_table (info);
+      if (!is_elf_hash_table (hash_table))
+       return FALSE;
+
+      bed = get_elf_backend_data (hash_table->dynobj);
+
       /* Proper resolution for function pointer equality may require
         that these symbols perhaps be resolved dynamically, even though
         we should be resolving them to the current module.  */
-      if (!ignore_protected || h->type != STT_FUNC)
+      if (!ignore_protected || !bed->is_function_type (h->type))
        binding_stays_local_p = TRUE;
       break;
 
@@ -2695,6 +2710,9 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
                              struct bfd_link_info *info,
                              bfd_boolean local_protected)
 {
+  const struct elf_backend_data *bed;
+  struct elf_link_hash_table *hash_table;
+
   /* If it's a local sym, of course we resolve locally.  */
   if (h == NULL)
     return TRUE;
@@ -2731,8 +2749,14 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
   if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
     return TRUE;
 
+  hash_table = elf_hash_table (info);
+  if (!is_elf_hash_table (hash_table))
+    return TRUE;
+
+  bed = get_elf_backend_data (hash_table->dynobj);
+
   /* STV_PROTECTED non-function symbols are local.  */
-  if (h->type != STT_FUNC)
+  if (!bed->is_function_type (h->type))
     return TRUE;
 
   /* Function pointer equality tests may require that STV_PROTECTED
@@ -2781,8 +2805,9 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
       && ELF_ST_BIND (sym->st_info) < STB_LOOS)
     return FALSE;
 
+  bed = get_elf_backend_data (abfd);
   /* Function symbols do not count.  */
-  if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+  if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
     return FALSE;
 
   /* If the section is undefined, then so is the symbol.  */
@@ -2791,7 +2816,6 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
 
   /* If the symbol is defined in the common section, then
      it is a common definition and so does not count.  */
-  bed = get_elf_backend_data (abfd);
   if (bed->common_definition (sym))
     return FALSE;
 
@@ -3799,8 +3823,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
             if it is not a function, because it might be the version
             symbol itself.  FIXME: What if it isn't?  */
          if ((iver.vs_vers & VERSYM_HIDDEN) != 0
-             || (vernum > 1 && (! bfd_is_abs_section (sec)
-                                || ELF_ST_TYPE (isym->st_info) == STT_FUNC)))
+             || (vernum > 1
+                 && (!bfd_is_abs_section (sec)
+                     || bed->is_function_type (ELF_ST_TYPE (isym->st_info)))))
            {
              const char *verstr;
              size_t namelen, verlen, newlen;
@@ -3947,7 +3972,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       if (dynamic
          && definition
          && (flags & BSF_WEAK) != 0
-         && ELF_ST_TYPE (isym->st_info) != STT_FUNC
+         && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
          && is_elf_hash_table (htab)
          && h->u.weakdef == NULL)
        {
@@ -4072,7 +4097,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
             to be the size of the common symbol.  The code just above
             won't fix the size if a common symbol becomes larger.  We
             don't warn about a size change here, because that is
-            covered by --warn-common.  */
+            covered by --warn-common.  Allow changed between different
+            function types.  */
          if (h->root.type == bfd_link_hash_common)
            h->size = h->root.u.c.size;
 
@@ -4414,7 +4440,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          h = *hpp;
          if (h != NULL
              && h->root.type == bfd_link_hash_defined
-             && h->type != STT_FUNC)
+             && !bed->is_function_type (h->type))
            {
              *sym_hash = h;
              sym_hash++;
index ea21b625120ab0db0f63666db82e333cb89ac85f..7b147817486db26954cbebb2c6278334f9c9eed3 100644 (file)
 #define elf_backend_hash_symbol _bfd_elf_hash_symbol
 #endif
 
+#ifndef elf_backend_is_function_type
+#define elf_backend_is_function_type _bfd_elf_is_function_type
+#endif
+
 extern const struct elf_size_info _bfd_elfNN_size_info;
 
 static struct elf_backend_data elfNN_bed =
@@ -672,6 +676,7 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_common_section,
   elf_backend_merge_symbol,
   elf_backend_hash_symbol,
+  elf_backend_is_function_type,
   elf_backend_link_order_error_handler,
   elf_backend_relplt_name,
   ELF_MACHINE_ALT1,
index da49ab720053510e847338ff726f2c12a9bd5263..5b5a49615812df6c464668d4b32cf713e597a857 100644 (file)
@@ -1,3 +1,9 @@
+2007-04-17  Paul Brook  <paul@codesourcery.com>
+
+       * ld-arm/preempt-app.s: New test.
+       * ld-arm/preempt-app.sym: New.
+       * ld-arm/arm-elf.exp: Add preempt-app.
+
 2007-04-12  Richard Sandiford  <richard@codesourcery.com>
 
        * ld-mips-elf/vxworks1-lib.td: New test.
index 5844266323c07d597164f66422b962311617ad17..f28bd095d9d41d4a98d51da76c5f940aad01b408 100644 (file)
@@ -159,6 +159,10 @@ set armelftests {
     {"arm-pic-veneer" "-static -T arm.ld --pic-veneer" "" {arm-pic-veneer.s}
      {{objdump -d arm-pic-veneer.d}}
      "arm-pic-veneer"}
+    {"Preempt Thumb symbol" "tmpdir/mixed-lib.so -T arm-dyn.ld --use-blx" ""
+     {preempt-app.s}
+     {{readelf -Ds preempt-app.sym}}
+     "preempt-app"}
 }
 
 run_ld_link_tests $armelftests
diff --git a/ld/testsuite/ld-arm/preempt-app.s b/ld/testsuite/ld-arm/preempt-app.s
new file mode 100644 (file)
index 0000000..f1eccc2
--- /dev/null
@@ -0,0 +1,27 @@
+       @ Preempt an ARM shared library function with a Thumb function
+       @ in the application.
+       .text
+       .p2align 4
+       .globl _start
+_start:
+       mov     ip, sp
+       stmdb   sp!, {r11, ip, lr, pc}
+       bl      lib_func1
+       ldmia   sp, {r11, sp, lr}
+       bx lr
+
+       .p2align 4
+       .globl app_func2
+       .type app_func2,%function
+app_func2:
+       bx      lr
+
+       .p2align 4
+       .globl lib_func1
+       .type lib_func1,%function
+       .thumb_func
+lib_func1:
+       bx lr
+
+       .data
+       .long data_obj
diff --git a/ld/testsuite/ld-arm/preempt-app.sym b/ld/testsuite/ld-arm/preempt-app.sym
new file mode 100644 (file)
index 0000000..d8ebf3b
--- /dev/null
@@ -0,0 +1,16 @@
+
+Symbol table for image:
+  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS _edata
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __bss_start__
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS _end
+   ..  ..: ........     4  OBJECT GLOBAL DEFAULT  10 data_obj
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __bss_end__
+   ..  ..: .......1    20    FUNC GLOBAL DEFAULT   6 lib_func1
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __exidx_start
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT   9 __data_start
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __end__
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __bss_start
+   ..  ..: .......0     0    FUNC GLOBAL DEFAULT   6 app_func2
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS _bss_end__
+   ..  ..: ........     0  NOTYPE GLOBAL DEFAULT ABS __exidx_end