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.
This commit is contained in:
H.J. Lu 2008-09-16 14:09:34 +00:00
parent e87d403811
commit 0a36a439ee
6 changed files with 72 additions and 12 deletions

View 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

View 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;

View 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.

View file

@ -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;
}

View file

@ -0,0 +1,2 @@
void foo (void) { }
void bar (void) { }

View 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