diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/elflink.c | 39 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/comm1.c | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/func1.c | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/shared.exp | 12 |
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 |