diff options
author | Alan Modra <amodra@gmail.com> | 2017-04-17 18:33:52 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2017-04-17 23:14:37 +0930 |
commit | c5d37467b152fe98f02ac1ff8188e32ecd0def95 (patch) | |
tree | 46caf31ba379349fdf89ea75c9841ebad7b44ee9 /bfd/elflink.c | |
parent | c661778cb6b406d5b55fbf22ff88fbc85ee3f4c2 (diff) | |
download | gdb-c5d37467b152fe98f02ac1ff8188e32ecd0def95.zip gdb-c5d37467b152fe98f02ac1ff8188e32ecd0def95.tar.gz gdb-c5d37467b152fe98f02ac1ff8188e32ecd0def95.tar.bz2 |
Undo dynamic symbol state after regular object sym type mismatch
We already handle the case of an object file first defining a symbol
that a later shared library also defines where the symbol types are
incompatible. This patch handles the reverse, when a later object
file defines an incompatible symbol defined by an earlier shared
library.
bfd/
* elflink.c (_bfd_elf_merge_symbol): Undo dynamic linking
state when a regular object file defines a symbol with
incompatible type to that defined by an earlier shared lib.
ld/
* testsuite/ld-elf/indirect5a.c,
* testsuite/ld-elf/indirect5b.c,
* testsuite/ld-elf/indirect5.map,
* testsuite/ld-elf/indirect5.out: New test.
* testsuite/ld-elf/indirect6a.c: Likewise.
* testsuite/ld-elf/indirect.exp (check_dynamic_syms): New proc.
Run new tests and check dynsyms.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index dfcc51e..ec2032b 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1242,23 +1242,50 @@ _bfd_elf_merge_symbol (bfd *abfd, oldfunc = (h->type != STT_NOTYPE && bed->is_function_type (h->type)); - /* If creating a default indirect symbol ("foo" or "foo@") from a - dynamic versioned definition ("foo@@") skip doing so if there is - an existing regular definition with a different type. We don't - want, for example, a "time" variable in the executable overriding - a "time" function in a shared library. */ - if (pold_alignment == NULL - && newdyn - && newdef - && !olddyn - && (olddef || h->root.type == bfd_link_hash_common) + if (!(newfunc && oldfunc) && ELF_ST_TYPE (sym->st_info) != h->type && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE && h->type != STT_NOTYPE - && !(newfunc && oldfunc)) + && (newdef || bfd_is_com_section (sec)) + && (olddef || h->root.type == bfd_link_hash_common)) { - *skip = TRUE; - return TRUE; + /* If creating a default indirect symbol ("foo" or "foo@") from + a dynamic versioned definition ("foo@@") skip doing so if + there is an existing regular definition with a different + type. We don't want, for example, a "time" variable in the + executable overriding a "time" function in a shared library. */ + if (newdyn + && !olddyn) + { + *skip = TRUE; + return TRUE; + } + + /* When adding a symbol from a regular object file after we have + created indirect symbols, undo the indirection and any + dynamic state. */ + if (hi != h + && !newdyn + && olddyn) + { + h = hi; + (*bed->elf_backend_hide_symbol) (info, h, TRUE); + h->forced_local = 0; + h->ref_dynamic = 0; + h->def_dynamic = 0; + h->dynamic_def = 0; + if (h->root.u.undef.next || info->hash->undefs_tail == &h->root) + { + h->root.type = bfd_link_hash_undefined; + h->root.u.undef.abfd = abfd; + } + else + { + h->root.type = bfd_link_hash_new; + h->root.u.undef.abfd = NULL; + } + return TRUE; + } } /* Check TLS symbols. We don't check undefined symbols introduced |