From b45b6908c154735e69e2dfefd34748f79ca85753 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 31 Jan 2013 07:32:45 +0000 Subject: [PATCH] PR ld/15056 * elfxx-sparc.c (_bfd_sparc_elf_gc_mark_hook): Handle implicit references to __tls_get_addr. * elf32-tilpro.c (tilepro_elf_gc_mark_hook): Likewise. Correct vtinherit and vtentry reloc handling too. * elfxx-tilegx.c (tilegx_elf_gc_mark_hook): As for tilepro. --- bfd/ChangeLog | 10 ++++++++++ bfd/elf32-tilepro.c | 32 +++++++++++++++++++++++++++----- bfd/elfxx-sparc.c | 23 +++++++++++++++++++++++ bfd/elfxx-tilegx.c | 32 +++++++++++++++++++++++++++----- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9598b6a50c4..c53af4ba489 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2013-01-31 Alan Modra + David S. Miller + + PR ld/15056 + * elfxx-sparc.c (_bfd_sparc_elf_gc_mark_hook): Handle implicit + references to __tls_get_addr. + * elf32-tilpro.c (tilepro_elf_gc_mark_hook): Likewise. Correct + vtinherit and vtentry reloc handling too. + * elfxx-tilegx.c (tilegx_elf_gc_mark_hook): As for tilepro. + 2013-01-31 Alan Modra * elf64-ppc.c (ppc_stub_name): Trim off trailing "+0". diff --git a/bfd/elf32-tilepro.c b/bfd/elf32-tilepro.c index fc49e2b816d..db37403b7f8 100644 --- a/bfd/elf32-tilepro.c +++ b/bfd/elf32-tilepro.c @@ -1868,11 +1868,33 @@ tilepro_elf_gc_mark_hook (asection *sec, if (h != NULL) { switch (ELF32_R_TYPE (rel->r_info)) - { - case R_TILEPRO_GNU_VTINHERIT: - case R_TILEPRO_GNU_VTENTRY: - break; - } + { + case R_TILEPRO_GNU_VTINHERIT: + case R_TILEPRO_GNU_VTENTRY: + return NULL; + } + } + + /* FIXME: The test here, in check_relocs and in relocate_section + dealing with TLS optimization, ought to be !info->executable. */ + if (info->shared) + { + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_TILEPRO_TLS_GD_CALL: + /* This reloc implicitly references __tls_get_addr. We know + another reloc will reference the same symbol as the one + on this reloc, so the real symbol and section will be + gc marked when processing the other reloc. That lets + us handle __tls_get_addr here. */ + h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr", + FALSE, FALSE, TRUE); + BFD_ASSERT (h != NULL); + h->mark = 1; + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; + sym = NULL; + } } return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 196d566aa99..9684ffd7a4d 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1873,6 +1873,29 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec, return NULL; } + /* FIXME: The test here, in check_relocs and in relocate_section + dealing with TLS optimization, ought to be !info->executable. */ + if (info->shared) + { + switch (SPARC_ELF_R_TYPE (rel->r_info)) + { + case R_SPARC_TLS_GD_CALL: + case R_SPARC_TLS_LDM_CALL: + /* This reloc implicitly references __tls_get_addr. We know + another reloc will reference the same symbol as the one + on this reloc, so the real symbol and section will be + gc marked when processing the other reloc. That lets + us handle __tls_get_addr here. */ + h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr", + FALSE, FALSE, TRUE); + BFD_ASSERT (h != NULL); + h->mark = 1; + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; + sym = NULL; + } + } + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c index b28d1a875a5..cd92bf9a875 100644 --- a/bfd/elfxx-tilegx.c +++ b/bfd/elfxx-tilegx.c @@ -2107,11 +2107,33 @@ tilegx_elf_gc_mark_hook (asection *sec, if (h != NULL) { switch (TILEGX_ELF_R_TYPE (rel->r_info)) - { - case R_TILEGX_GNU_VTINHERIT: - case R_TILEGX_GNU_VTENTRY: - break; - } + { + case R_TILEGX_GNU_VTINHERIT: + case R_TILEGX_GNU_VTENTRY: + return NULL; + } + } + + /* FIXME: The test here, in check_relocs and in relocate_section + dealing with TLS optimization, ought to be !info->executable. */ + if (info->shared) + { + switch (TILEGX_ELF_R_TYPE (rel->r_info)) + { + case R_TILEGX_TLS_GD_CALL: + /* This reloc implicitly references __tls_get_addr. We know + another reloc will reference the same symbol as the one + on this reloc, so the real symbol and section will be + gc marked when processing the other reloc. That lets + us handle __tls_get_addr here. */ + h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr", + FALSE, FALSE, TRUE); + BFD_ASSERT (h != NULL); + h->mark = 1; + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; + sym = NULL; + } } return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); -- 2.30.2