From 7479dfd4deee7e65f5a9f89bfdd027a213172c42 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 30 Sep 2004 16:43:41 +0000 Subject: [PATCH] 2004-09-30 H.J. Lu PR 414 * elflink.c (_bfd_elf_merge_symbol): Check TLS symbol. --- bfd/ChangeLog | 5 +++++ bfd/elflink.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 231242b485a..bb4d5e3e44a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2004-09-30 H.J. Lu + + PR 414 + * elflink.c (_bfd_elf_merge_symbol): Check TLS symbol. + 2004-09-30 Paul Brook * reloc.c: Add BFD_RELOC_ARM_SMI. diff --git a/bfd/elflink.c b/bfd/elflink.c index 8320fd87831..e93145d6c24 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -709,7 +709,7 @@ _bfd_elf_merge_symbol (bfd *abfd, bfd_boolean *type_change_ok, bfd_boolean *size_change_ok) { - asection *sec; + asection *sec, *oldsec; struct elf_link_hash_entry *h; struct elf_link_hash_entry *flip; int bind; @@ -753,26 +753,31 @@ _bfd_elf_merge_symbol (bfd *abfd, return TRUE; } - /* OLDBFD is a BFD associated with the existing symbol. */ + /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the + existing symbol. */ switch (h->root.type) { default: oldbfd = NULL; + oldsec = NULL; break; case bfd_link_hash_undefined: case bfd_link_hash_undefweak: oldbfd = h->root.u.undef.abfd; + oldsec = NULL; break; case bfd_link_hash_defined: case bfd_link_hash_defweak: oldbfd = h->root.u.def.section->owner; + oldsec = h->root.u.def.section; break; case bfd_link_hash_common: oldbfd = h->root.u.c.p->section->owner; + oldsec = h->root.u.c.p->section; break; } @@ -840,6 +845,54 @@ _bfd_elf_merge_symbol (bfd *abfd, else olddef = TRUE; + /* Check TLS symbol. */ + if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS) + && ELF_ST_TYPE (sym->st_info) != h->type) + { + bfd *ntbfd, *tbfd; + bfd_boolean ntdef, tdef; + asection *ntsec, *tsec; + + if (h->type == STT_TLS) + { + ntbfd = abfd; + ntsec = sec; + ntdef = newdef; + tbfd = oldbfd; + tsec = oldsec; + tdef = olddef; + } + else + { + ntbfd = oldbfd; + ntsec = oldsec; + ntdef = olddef; + tbfd = abfd; + tsec = sec; + tdef = newdef; + } + + if (tdef && ntdef) + (*_bfd_error_handler) + (_("%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A"), + tbfd, tsec, ntbfd, ntsec, h->root.root.string); + else if (!tdef && !ntdef) + (*_bfd_error_handler) + (_("%s: TLS reference in %B mismatches non-TLS reference in %B"), + tbfd, ntbfd, h->root.root.string); + else if (tdef) + (*_bfd_error_handler) + (_("%s: TLS definition in %B section %A mismatches non-TLS reference in %B"), + tbfd, tsec, ntbfd, h->root.root.string); + else + (*_bfd_error_handler) + (_("%s: TLS reference in %B mismatches non-TLS definition in %B section %A"), + tbfd, ntbfd, ntsec, h->root.root.string); + + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + /* We need to remember if a symbol has a definition in a dynamic object or is weak in all dynamic objects. Internal and hidden visibility will make it unavailable to dynamic objects. */ -- 2.30.2