aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-04-17 18:33:52 +0930
committerAlan Modra <amodra@gmail.com>2017-04-17 23:14:37 +0930
commitc5d37467b152fe98f02ac1ff8188e32ecd0def95 (patch)
tree46caf31ba379349fdf89ea75c9841ebad7b44ee9 /bfd/elflink.c
parentc661778cb6b406d5b55fbf22ff88fbc85ee3f4c2 (diff)
downloadgdb-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.c53
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