This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: PR ld/6877: Inconsistent treatment of common and text
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sources dot redhat dot com
- Date: Wed, 10 Sep 2008 18:07:21 -0700
- Subject: PATCH: PR ld/6877: Inconsistent treatment of common and text
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
We are supposed to allow a common symbol to override the function in a
shared library. But it only works if the commom symbol comes first.
This patch fixes it. OK to install?
Thanks.
H.J.
---
bfd/
2008-09-10 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-10 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.
--- binutils/bfd/elflink.c.func 2008-09-10 10:10:18.000000000 -0700
+++ binutils/bfd/elflink.c 2008-09-10 18:00:11.000000000 -0700
@@ -903,7 +903,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;
@@ -1022,6 +1022,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
@@ -1037,8 +1046,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;
@@ -1219,8 +1227,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
@@ -1269,7 +1276,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;
@@ -1281,7 +1288,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;
@@ -1341,8 +1348,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;
@@ -1396,8 +1402,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)
@@ -1417,7 +1422,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;
--- binutils/ld/testsuite/ld-elf/comm1.c.func 2008-09-10 18:00:32.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/comm1.c 2008-09-10 17:54:56.000000000 -0700
@@ -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;
+}
--- binutils/ld/testsuite/ld-elf/func1.c.func 2008-09-10 18:00:32.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/func1.c 2008-09-10 17:55:08.000000000 -0700
@@ -0,0 +1,2 @@
+void foo (void) { }
+void bar (void) { }
--- binutils/ld/testsuite/ld-elf/shared.exp.func 2008-09-10 10:10:18.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/shared.exp 2008-09-10 17:59:54.000000000 -0700
@@ -126,6 +126,9 @@ set build_tests {
{"Build libdata2.so"
"-shared" "-fPIC"
{data2.c} {} "libdata2.so"}
+ {"Build libfunc1.so"
+ "-shared" "-fPIC"
+ {func1.c} {} "libfunc1.so"}
}
set run_tests {
@@ -241,6 +244,12 @@ set run_tests {
{"Run with libdata2.so"
"tmpdir/libdata2.so" ""
{weakdef1.c} "weakdef1" "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