bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 16 Sep 2008 14:09:34 +0000 (14:09 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 16 Sep 2008 14:09:34 +0000 (14:09 +0000)
2008-09-16  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/6877
* elflink.c (_bfd_elf_merge_symbol): Allow a common symbol to
override the function in a shared library.

ld/testsuite/

2008-09-16  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/6877
* ld-elf/comm1.c: New.
* ld-elf/func1.c: Likewise.

* ld-elf/shared.exp: Add tests for libfunc1.so and comm1.

bfd/ChangeLog
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/comm1.c [new file with mode: 0644]
ld/testsuite/ld-elf/func1.c [new file with mode: 0644]
ld/testsuite/ld-elf/shared.exp

index 6a2e8f3..705c6f7 100644 (file)
@@ -1,3 +1,9 @@
+2008-09-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/6877
+       * elflink.c (_bfd_elf_merge_symbol): Allow a common symbol to
+       override the function in a shared library.
+
 2008-09-16  Alan Modra  <amodra@bigpond.net.au>
 
        PR 6844
index 010c614..ab6c2db 100644 (file)
@@ -854,7 +854,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   int bind;
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak;
+  bfd_boolean newweak, oldweak, newfunc, oldfunc;
   const struct elf_backend_data *bed;
 
   *skip = FALSE;
@@ -972,6 +972,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
            && h->root.type != bfd_link_hash_undefweak
            && h->root.type != bfd_link_hash_common);
 
+  /* NEWFUNC and OLDFUNC indicate whether the new or old symbol,
+     respectively, appear to be a function.  */
+
+  newfunc = (ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+            && bed->is_function_type (ELF_ST_TYPE (sym->st_info)));
+
+  oldfunc = (h->type != STT_NOTYPE
+            && bed->is_function_type (h->type));
+
   /* 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
@@ -987,8 +996,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && ELF_ST_TYPE (sym->st_info) != h->type
       && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
       && h->type != STT_NOTYPE
-      && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
-          && bed->is_function_type (h->type)))
+      && !(newfunc && oldfunc))
     {
       *skip = TRUE;
       return TRUE;
@@ -1180,8 +1188,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
     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))
+  if (newfunc && oldfunc)
     *type_change_ok = TRUE;
 
   /* It's OK to change the type if either the existing symbol or the
@@ -1230,7 +1237,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (sec->flags & SEC_ALLOC) != 0
       && (sec->flags & SEC_LOAD) == 0
       && sym->st_size > 0
-      && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
+      && !newfunc)
     newdyncommon = TRUE;
   else
     newdyncommon = FALSE;
@@ -1242,7 +1249,7 @@ _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
-      && !bed->is_function_type (h->type))
+      && !oldfunc)
     olddyncommon = TRUE;
   else
     olddyncommon = FALSE;
@@ -1302,8 +1309,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && newdef
       && (olddef
          || (h->root.type == bfd_link_hash_common
-             && (newweak
-                 || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
+             && (newweak || newfunc))))
     {
       *override = TRUE;
       newdef = FALSE;
@@ -1357,8 +1363,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (!newdyn
       && (newdef
          || (bfd_is_com_section (sec)
-             && (oldweak
-                 || bed->is_function_type (h->type))))
+             && (oldweak || oldfunc)))
       && olddyn
       && olddef
       && h->def_dynamic)
@@ -1378,7 +1383,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
         overriding a function.  */
 
       if (bfd_is_com_section (sec))
-       *type_change_ok = TRUE;
+       {
+         if (oldfunc)
+           {
+             /* If a common symbol overrides a function, make sure
+                that it isn't defined dynamically nor has type
+                function.  */
+             h->def_dynamic = 0;
+             h->type = STT_NOTYPE;
+           }
+         *type_change_ok = TRUE;
+       }
 
       if ((*sym_hash)->root.type == bfd_link_hash_indirect)
        flip = *sym_hash;
index a2c3050..cc898e6 100644 (file)
@@ -1,3 +1,11 @@
+2008-09-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/6877
+       * ld-elf/comm1.c: New.
+       * ld-elf/func1.c: Likewise.
+
+       * ld-elf/shared.exp: Add tests for libfunc1.so and comm1.
+
 2008-08-26  Nick Clifton  <nickc@redhat.com>
 
        * ld-arm/arm-elf.exp: Add farcall-thumb-arm-short test.
diff --git a/ld/testsuite/ld-elf/comm1.c b/ld/testsuite/ld-elf/comm1.c
new file mode 100644 (file)
index 0000000..c553d86
--- /dev/null
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int foo;
+void bar (void);
+
+int
+main ()
+{
+  if (foo != 0)
+    abort ();
+  foo = 200; 
+  bar ();
+  if (foo == 200)
+    printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/func1.c b/ld/testsuite/ld-elf/func1.c
new file mode 100644 (file)
index 0000000..99443e4
--- /dev/null
@@ -0,0 +1,2 @@
+void foo (void) { }
+void bar (void) { }
index 846027e..f0bc403 100644 (file)
@@ -123,6 +123,12 @@ set build_tests {
   {"Build libdata1.so"
    "-shared" "-fPIC"
    {data1.c} {} "libdata1.so"}
+  {"Build libcomm1.o"
+   "-r -nostdlib" ""
+   {comm1.c} {} "libcomm1.o"}
+  {"Build libfunc1.so"
+   "-shared" "-fPIC"
+   {func1.c} {} "libfunc1.so"}
 }
 
 set run_tests {
@@ -235,6 +241,12 @@ set run_tests {
     {"Run with libdata1.so"
      "tmpdir/libdata1.so" ""
      {dynbss1.c} "dynbss1" "pass.out"}
+    {"Run with libfunc1.so comm1.o"
+     "tmpdir/libfunc1.so tmpdir/comm1.o" ""
+     {dummy.c} "comm1" "pass.out"}
+    {"Run with comm1.o libfunc1.so"
+     "tmpdir/comm1.o tmpdir/libfunc1.so" ""
+     {dummy.c} "comm1" "pass.out"}
 }
 
 run_cc_link_tests $build_tests