diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-09-19 00:53:30 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-09-19 00:53:30 +0000 |
commit | 37a9e49a286b6c0b9e34387921b90c0ffa731516 (patch) | |
tree | 065d205cdcf4f3fd4e8b37d51a479eebde2e6a7f /bfd/elflink.c | |
parent | 91b96a45e3265661c6f686ae9050100b8df2794f (diff) | |
download | gdb-37a9e49a286b6c0b9e34387921b90c0ffa731516.zip gdb-37a9e49a286b6c0b9e34387921b90c0ffa731516.tar.gz gdb-37a9e49a286b6c0b9e34387921b90c0ffa731516.tar.bz2 |
Properly handle common symbol and weak function
bfd/
PR ld/14591
* elf-bfd.h (_bfd_elf_merge_symbol): Add an argument to return
if the old symbol is weak.
* elf32-sh-symbian.c (sh_symbian_relocate_section): Update
_bfd_elf_merge_symbol call.
* elflink.c (_bfd_elf_merge_symbol): Add an argument to return
if the old symbol is weak.
(_bfd_elf_add_default_symbol): Update _bfd_elf_merge_symbol
call.
(elf_link_add_object_symbols): Don't update symbol type from a
weak definition. Update symbol type from a common symbol when
overriding a weak symbol.
ld/testsuite/
PR ld/14591
* ld-elf/comm-data.exp (run_ld_link_tests): Add comm-data3a and
comm-data3b tests.
* ld-ifunc/ifunc.exp (run_ld_link_exec_tests): New.
* ld-elf/comm-data3.sd: New file.
* ld-elf/comm-data3a.s: Likewise.
* ld-elf/comm-data3b.s: Likewise.
* ld-ifunc/ifunc-17a-i386.d: Likewise.
* ld-ifunc/ifunc-17a-x86-64.d: Likewise.
* ld-ifunc/ifunc-17a.s: Likewise.
* ld-ifunc/ifunc-17b-i386.d: Likewise.
* ld-ifunc/ifunc-17b-x86-64.d: Likewise.
* ld-ifunc/ifunc-17b.s: Likewise.
* ld-ifunc/ifunc-common-1.out: Likewise.
* ld-ifunc/ifunc-common-1a.c: Likewise.
* ld-ifunc/ifunc-common-1b.c: Likewise.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 9446e7d..232c0b1 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -941,6 +941,7 @@ _bfd_elf_merge_symbol (bfd *abfd, Elf_Internal_Sym *sym, asection **psec, bfd_vma *pvalue, + bfd_boolean *pold_weak, unsigned int *pold_alignment, struct elf_link_hash_entry **sym_hash, bfd_boolean *skip, @@ -1043,6 +1044,8 @@ _bfd_elf_merge_symbol (bfd *abfd, newweak = bind == STB_WEAK; oldweak = (h->root.type == bfd_link_hash_defweak || h->root.type == bfd_link_hash_undefweak); + if (pold_weak) + *pold_weak = oldweak; /* In cases involving weak versioned symbols, we may wind up trying to merge a symbol with itself. Catch that here, to avoid the @@ -1665,7 +1668,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, size_change_ok = FALSE; sec = *psec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value, - NULL, &hi, &skip, &override, + NULL, NULL, &hi, &skip, &override, &type_change_ok, &size_change_ok)) return FALSE; @@ -1774,7 +1777,7 @@ nondefault: size_change_ok = FALSE; sec = *psec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value, - NULL, &hi, &skip, &override, + NULL, NULL, &hi, &skip, &override, &type_change_ok, &size_change_ok)) return FALSE; @@ -3868,6 +3871,8 @@ error_free_dyn: bfd_boolean size_change_ok; bfd_boolean type_change_ok; bfd_boolean new_weakdef; + bfd_boolean new_weak; + bfd_boolean old_weak; bfd_boolean override; bfd_boolean common; unsigned int old_alignment; @@ -4000,6 +4005,7 @@ error_free_dyn: size_change_ok = FALSE; type_change_ok = bed->type_change_ok; + old_weak = FALSE; old_alignment = 0; old_bfd = NULL; new_sec = sec; @@ -4145,7 +4151,7 @@ error_free_dyn: } if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, - &value, &old_alignment, + &value, &old_weak, &old_alignment, sym_hash, &skip, &override, &type_change_ok, &size_change_ok)) goto error_free_vers; @@ -4207,10 +4213,11 @@ error_free_dyn: if (is_elf_hash_table (htab)) h->unique_global = (flags & BSF_GNU_UNIQUE) != 0; + new_weak = (flags & BSF_WEAK) != 0; new_weakdef = FALSE; if (dynamic && definition - && (flags & BSF_WEAK) != 0 + && new_weak && !bed->is_function_type (ELF_ST_TYPE (isym->st_info)) && is_elf_hash_table (htab) && h->u.weakdef == NULL) @@ -4339,7 +4346,9 @@ error_free_dyn: h->size = h->root.u.c.size; if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE - && (definition || h->type == STT_NOTYPE)) + && ((definition && !new_weak) + || (old_weak && h->root.type == bfd_link_hash_common) + || h->type == STT_NOTYPE)) { unsigned int type = ELF_ST_TYPE (isym->st_info); |