diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2008-09-16 14:09:34 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2008-09-16 14:09:34 +0000 |
commit | 0a36a439ee413816df8ab88a769135076e6355f6 (patch) | |
tree | 9038090ce719b70f67aaacdbd267a4bc5aad52de /bfd | |
parent | e87d403811e6f31fde1848a31c9e1feec914b37e (diff) | |
download | gdb-0a36a439ee413816df8ab88a769135076e6355f6.zip gdb-0a36a439ee413816df8ab88a769135076e6355f6.tar.gz gdb-0a36a439ee413816df8ab88a769135076e6355f6.tar.bz2 |
bfd/
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.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/elflink.c | 39 |
2 files changed, 33 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; |