aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog6
-rw-r--r--bfd/elflink.c39
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-elf/comm1.c17
-rw-r--r--ld/testsuite/ld-elf/func1.c2
-rw-r--r--ld/testsuite/ld-elf/shared.exp12
6 files changed, 72 insertions, 12 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6a2e8f3..705c6f7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 010c614..ab6c2db 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index a2c3050..cc898e6 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
index 0000000..c553d86
--- /dev/null
+++ b/ld/testsuite/ld-elf/comm1.c
@@ -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
index 0000000..99443e4
--- /dev/null
+++ b/ld/testsuite/ld-elf/func1.c
@@ -0,0 +1,2 @@
+void foo (void) { }
+void bar (void) { }
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 846027e..f0bc403 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -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