From d07b621f4cc585607c7eee7cc58ce54a7dde52f5 Mon Sep 17 00:00:00 2001 From: Cupertino Miranda Date: Thu, 4 Oct 2018 10:17:03 +0100 Subject: [PATCH] [ARC] More fixes for TLS. Added warning for static TLS reloc. Fixed issue related to TLS and partial static linking of libraries: This issue was detected when throwing exceptions in C++ while linking with -static-libstdc++. TLS relocation from the libstdc++ wasn't being patched as local now that it was static linked with the executable. Fix for TLS with static and pie. Problem introduced by earlier patch: Fixes the following glibc tests: - elf/tst-tls1-static bfd/ xxxx-xx-xx Cupertino Miranda * arc-got.h (arc_got_entry_type_for_reloc): Changed to correct static TLS relocs. * elf32-arc.c (elf_arc_check_relocs): Introduced warning to TLS relocs which require -fPIC. (arc_create_forced_local_got_entries_for_tls): Created. Traverses list of GOT entries to be resolved statically when needed. (elf_arc_finish_dynamic_sections): Changed. Calls arc_create_forced_local_got_entries_for_tls for each known possibly GOT symbol. --- bfd/arc-got.h | 33 ++++++++------ bfd/elf32-arc.c | 116 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 105 insertions(+), 44 deletions(-) diff --git a/bfd/arc-got.h b/bfd/arc-got.h index 69e9aa3275..253578b90c 100644 --- a/bfd/arc-got.h +++ b/bfd/arc-got.h @@ -208,7 +208,7 @@ arc_got_entry_type_for_reloc (reloc_howto_type *howto) __LINE__, name_for_global_symbol (H)); \ } \ if (H) \ - if (h->dynindx == -1 && !h->forced_local) \ + if (H->dynindx == -1 && !H->forced_local) \ if (! bfd_elf_link_record_dynamic_symbol (info, H)) \ return FALSE; \ htab->s##SECNAME->size += 4; \ @@ -284,6 +284,7 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, BFD_ASSERT (entry); if (h == NULL + || h->forced_local == TRUE || (! elf_hash_table (info)->dynamic_sections_created || (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)))) @@ -331,27 +332,31 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, BFD_ASSERT (tls_sec && tls_sec->output_section); bfd_vma sec_vma = tls_sec->output_section->vma; - bfd_put_32 (output_bfd, + if (h == NULL || h->forced_local + || !elf_hash_table (info)->dynamic_sections_created) + { + bfd_put_32 (output_bfd, sym_value - sec_vma + (elf_hash_table (info)->dynamic_sections_created ? 0 - : (align_power (TCB_SIZE, + : (align_power (0, tls_sec->alignment_power))), htab->sgot->contents + entry->offset + (entry->existing_entries == TLS_GOT_MOD_AND_OFF ? 4 : 0)); - ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx " - "@ %lx, for symbol %s\n", - (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : - "GOT_TLS_IE"), - (long) (sym_value - sec_vma), - (long) (htab->sgot->output_section->vma - + htab->sgot->output_offset - + entry->offset - + (entry->existing_entries == TLS_GOT_MOD_AND_OFF - ? 4 : 0)), - symbol_name); + ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx " + "@ %lx, for symbol %s\n", + (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : + "GOT_TLS_IE"), + (long) (sym_value - sec_vma), + (long) (htab->sgot->output_section->vma + + htab->sgot->output_offset + + entry->offset + + (entry->existing_entries == TLS_GOT_MOD_AND_OFF + ? 4 : 0)), + symbol_name); + } } break; diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index 668642c302..e96b3f8697 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -1989,36 +1989,35 @@ elf_arc_check_relocs (bfd * abfd, switch (r_type) { - case R_ARC_32: - case R_ARC_32_ME: - /* During shared library creation, these relocs should not - appear in a shared library (as memory will be read only - and the dynamic linker can not resolve these. However - the error should not occur for e.g. debugging or - non-readonly sections. */ - if (h != NULL - && (bfd_link_dll (info) && !bfd_link_pie (info)) - && (sec->flags & SEC_ALLOC) != 0 - && (sec->flags & SEC_READONLY) != 0 - && ((sec->flags & SEC_CODE) != 0 - || (sec->flags & SEC_DEBUGGING) != 0)) - { - const char *name; - if (h) - name = h->root.root.string; - else - /* bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); */ - name = "UNKNOWN"; - _bfd_error_handler - /* xgettext:c-format */ - (_("%pB: relocation %s against `%s' can not be used" - " when making a shared object; recompile with -fPIC"), - abfd, - arc_elf_howto (r_type)->name, - name); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + case R_ARC_32: + case R_ARC_32_ME: + /* During shared library creation, these relocs should not + appear in a shared library (as memory will be read only + and the dynamic linker can not resolve these. However + the error should not occur for e.g. debugging or + non-readonly sections. */ + if (h != NULL + && (bfd_link_dll (info) && !bfd_link_pie (info)) + && (sec->flags & SEC_ALLOC) != 0 + && (sec->flags & SEC_READONLY) != 0 + && ((sec->flags & SEC_CODE) != 0 + || (sec->flags & SEC_DEBUGGING) != 0)) + { + const char *name; + if (h) + name = h->root.root.string; + else + name = "UNKNOWN"; + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against `%s' can not be used" + " when making a shared object; recompile with -fPIC"), + abfd, + arc_elf_howto (r_type)->name, + name); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } /* In some cases we are not setting the 'non_got_ref' flag, even though the relocations don't require a GOT @@ -2068,6 +2067,25 @@ elf_arc_check_relocs (bfd * abfd, if (is_reloc_for_GOT (howto) || is_reloc_for_TLS (howto)) { + if (bfd_link_dll (info) && !bfd_link_pie (info) + && (r_type == R_ARC_TLS_LE_32 || r_type == R_ARC_TLS_LE_S9)) + { + const char *name; + if (h) + name = h->root.root.string; + else + /* bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); */ + name = "UNKNOWN"; + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: relocation %s against `%s' can not be used" + " when making a shared object; recompile with -fPIC"), + abfd, + arc_elf_howto (r_type)->name, + name); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } if (! _bfd_elf_create_got_section (dynobj, info)) return FALSE; @@ -2490,6 +2508,38 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, s = bfd_get_linker_section (dynobj, SECTION); \ break; + +struct obfd_info_group { + bfd *output_bfd; + struct bfd_link_info *info; +}; + +static bfd_boolean +arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh, + void *data) +{ + struct elf_arc_link_hash_entry * h = + (struct elf_arc_link_hash_entry *) bh; + struct obfd_info_group *tmp = (struct obfd_info_group *) data; + + if (h->got_ents != NULL) + { + BFD_ASSERT (h); + + struct got_entry *list = h->got_ents; + + while (list != NULL) + { + create_got_dynrelocs_for_single_entry (list, tmp->output_bfd, + tmp->info, h); + list = list->next; + } + } + + return TRUE; +} + + /* Function : elf_arc_finish_dynamic_sections Brief : Finish up the dynamic sections handling. Args : output_bfd : @@ -2623,6 +2673,12 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, } } + struct obfd_info_group group; + group.output_bfd = output_bfd; + group.info = info; + bfd_hash_traverse (&info->hash->table, + arc_create_forced_local_got_entries_for_tls, &group); + return TRUE; }