[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  <cmiranda@synopsys.com>

	    * 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.
This commit is contained in:
Cupertino Miranda
2018-10-04 10:17:03 +01:00
parent fda57deda7
commit d07b621f4c
2 changed files with 105 additions and 44 deletions

View File

@ -208,7 +208,7 @@ arc_got_entry_type_for_reloc (reloc_howto_type *howto)
__LINE__, name_for_global_symbol (H)); \ __LINE__, name_for_global_symbol (H)); \
} \ } \
if (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)) \ if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
return FALSE; \ return FALSE; \
htab->s##SECNAME->size += 4; \ htab->s##SECNAME->size += 4; \
@ -284,6 +284,7 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p,
BFD_ASSERT (entry); BFD_ASSERT (entry);
if (h == NULL if (h == NULL
|| h->forced_local == TRUE
|| (! elf_hash_table (info)->dynamic_sections_created || (! elf_hash_table (info)->dynamic_sections_created
|| (bfd_link_pic (info) || (bfd_link_pic (info)
&& SYMBOL_REFERENCES_LOCAL (info, h)))) && 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_ASSERT (tls_sec && tls_sec->output_section);
bfd_vma sec_vma = tls_sec->output_section->vma; 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 sym_value - sec_vma
+ (elf_hash_table (info)->dynamic_sections_created + (elf_hash_table (info)->dynamic_sections_created
? 0 ? 0
: (align_power (TCB_SIZE, : (align_power (0,
tls_sec->alignment_power))), tls_sec->alignment_power))),
htab->sgot->contents + entry->offset htab->sgot->contents + entry->offset
+ (entry->existing_entries == TLS_GOT_MOD_AND_OFF + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
? 4 : 0)); ? 4 : 0));
ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx " ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx "
"@ %lx, for symbol %s\n", "@ %lx, for symbol %s\n",
(entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" :
"GOT_TLS_IE"), "GOT_TLS_IE"),
(long) (sym_value - sec_vma), (long) (sym_value - sec_vma),
(long) (htab->sgot->output_section->vma (long) (htab->sgot->output_section->vma
+ htab->sgot->output_offset + htab->sgot->output_offset
+ entry->offset + entry->offset
+ (entry->existing_entries == TLS_GOT_MOD_AND_OFF + (entry->existing_entries == TLS_GOT_MOD_AND_OFF
? 4 : 0)), ? 4 : 0)),
symbol_name); symbol_name);
}
} }
break; break;

View File

@ -1989,36 +1989,35 @@ elf_arc_check_relocs (bfd * abfd,
switch (r_type) switch (r_type)
{ {
case R_ARC_32: case R_ARC_32:
case R_ARC_32_ME: case R_ARC_32_ME:
/* During shared library creation, these relocs should not /* During shared library creation, these relocs should not
appear in a shared library (as memory will be read only appear in a shared library (as memory will be read only
and the dynamic linker can not resolve these. However and the dynamic linker can not resolve these. However
the error should not occur for e.g. debugging or the error should not occur for e.g. debugging or
non-readonly sections. */ non-readonly sections. */
if (h != NULL if (h != NULL
&& (bfd_link_dll (info) && !bfd_link_pie (info)) && (bfd_link_dll (info) && !bfd_link_pie (info))
&& (sec->flags & SEC_ALLOC) != 0 && (sec->flags & SEC_ALLOC) != 0
&& (sec->flags & SEC_READONLY) != 0 && (sec->flags & SEC_READONLY) != 0
&& ((sec->flags & SEC_CODE) != 0 && ((sec->flags & SEC_CODE) != 0
|| (sec->flags & SEC_DEBUGGING) != 0)) || (sec->flags & SEC_DEBUGGING) != 0))
{ {
const char *name; const char *name;
if (h) if (h)
name = h->root.root.string; name = h->root.root.string;
else else
/* bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL); */ name = "UNKNOWN";
name = "UNKNOWN"; _bfd_error_handler
_bfd_error_handler /* xgettext:c-format */
/* xgettext:c-format */ (_("%pB: relocation %s against `%s' can not be used"
(_("%pB: relocation %s against `%s' can not be used" " when making a shared object; recompile with -fPIC"),
" when making a shared object; recompile with -fPIC"), abfd,
abfd, arc_elf_howto (r_type)->name,
arc_elf_howto (r_type)->name, name);
name); bfd_set_error (bfd_error_bad_value);
bfd_set_error (bfd_error_bad_value); return FALSE;
return FALSE; }
}
/* In some cases we are not setting the 'non_got_ref' /* In some cases we are not setting the 'non_got_ref'
flag, even though the relocations don't require a GOT 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) if (is_reloc_for_GOT (howto)
|| is_reloc_for_TLS (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)) if (! _bfd_elf_create_got_section (dynobj, info))
return FALSE; return FALSE;
@ -2490,6 +2508,38 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd,
s = bfd_get_linker_section (dynobj, SECTION); \ s = bfd_get_linker_section (dynobj, SECTION); \
break; 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 /* Function : elf_arc_finish_dynamic_sections
Brief : Finish up the dynamic sections handling. Brief : Finish up the dynamic sections handling.
Args : output_bfd : 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; return TRUE;
} }