* elf32-m68k.c: Rewrite initialization of GOT entries for TLS

relocations.  Rewrite output of dynamic TLS relocations.
        (DTP_OFFSET, TP_OFFSET): New constants.
        (dtpoff_base): Update.
        (tpoff): Rename to tpoff_base, update.
        (elf_m68k_init_got_entry_static, elf_m68k_init_got_entry_local_shared):
        New functions.  Move code from elf_m68k_relocate_section here.
        (elf_m68k_relocate_section): Update.
        (elf_m68k_finish_dynamic_symbol): Fix handling of local TLS symbols.
This commit is contained in:
Nick Clifton 2009-08-26 13:42:27 +00:00
parent e5f2b1de7c
commit 325e58c76a
2 changed files with 173 additions and 140 deletions

View File

@ -1,3 +1,15 @@
2009-08-26 Maxim Kuvyrkov <maxim@codesourcery.com>
* elf32-m68k.c: Rewrite initialization of GOT entries for TLS
relocations. Rewrite output of dynamic TLS relocations.
(DTP_OFFSET, TP_OFFSET): New constants.
(dtpoff_base): Update.
(tpoff): Rename to tpoff_base, update.
(elf_m68k_init_got_entry_static, elf_m68k_init_got_entry_local_shared):
New functions. Move code from elf_m68k_relocate_section here.
(elf_m68k_relocate_section): Update.
(elf_m68k_finish_dynamic_symbol): Fix handling of local TLS symbols.
2009-08-26 Maxim Kuvyrkov <maxim@codesourcery.com>
* elf32-m68k.c (elf_m68k_copy_indirect_symbol): Propagate

View File

@ -3446,9 +3446,11 @@ elf_m68k_install_rela (bfd *output_bfd,
bfd_elf32_swap_reloca_out (output_bfd, rela, loc);
}
/* Return the base VMA address which should be subtracted from real addresses
when resolving @dtpoff relocation.
This is PT_TLS segment p_vaddr. */
/* Find the base offsets for thread-local storage in this object,
for GD/LD and IE/LE respectively. */
#define DTP_OFFSET 0x8000
#define TP_OFFSET 0x7000
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
@ -3456,23 +3458,116 @@ dtpoff_base (struct bfd_link_info *info)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_sec->vma;
return elf_hash_table (info)->tls_sec->vma + DTP_OFFSET;
}
/* Return the relocation value for @tpoff relocation
if STT_TLS virtual address is ADDRESS. */
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
tpoff_base (struct bfd_link_info *info)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
bfd_vma base;
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
base = align_power ((bfd_vma) 8, htab->tls_sec->alignment_power);
return address - htab->tls_sec->vma + base;
return elf_hash_table (info)->tls_sec->vma + TP_OFFSET;
}
/* Output necessary relocation to handle a symbol during static link.
This function is called from elf_m68k_relocate_section. */
static void
elf_m68k_init_got_entry_static (struct bfd_link_info *info,
bfd *output_bfd,
enum elf_m68k_reloc_type r_type,
asection *sgot,
bfd_vma got_entry_offset,
bfd_vma relocation)
{
switch (elf_m68k_reloc_got_type (r_type))
{
case R_68K_GOT32O:
bfd_put_32 (output_bfd, relocation, sgot->contents + got_entry_offset);
break;
case R_68K_TLS_GD32:
/* We know the offset within the module,
put it into the second GOT slot. */
bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
sgot->contents + got_entry_offset + 4);
/* FALLTHRU */
case R_68K_TLS_LDM32:
/* Mark it as belonging to module 1, the executable. */
bfd_put_32 (output_bfd, 1, sgot->contents + got_entry_offset);
break;
case R_68K_TLS_IE32:
bfd_put_32 (output_bfd, relocation - tpoff_base (info),
sgot->contents + got_entry_offset);
break;
default:
BFD_ASSERT (FALSE);
}
}
/* Output necessary relocation to handle a local symbol
during dynamic link.
This function is called either from elf_m68k_relocate_section
or from elf_m68k_finish_dynamic_symbol. */
static void
elf_m68k_init_got_entry_local_shared (struct bfd_link_info *info,
bfd *output_bfd,
enum elf_m68k_reloc_type r_type,
asection *sgot,
bfd_vma got_entry_offset,
bfd_vma relocation,
asection *srela)
{
Elf_Internal_Rela outrel;
switch (elf_m68k_reloc_got_type (r_type))
{
case R_68K_GOT32O:
/* Emit RELATIVE relocation to initialize GOT slot
at run-time. */
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
outrel.r_addend = relocation;
break;
case R_68K_TLS_GD32:
/* We know the offset within the module,
put it into the second GOT slot. */
bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
sgot->contents + got_entry_offset + 4);
/* FALLTHRU */
case R_68K_TLS_LDM32:
/* We don't know the module number,
create a relocation for it. */
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32);
outrel.r_addend = 0;
break;
case R_68K_TLS_IE32:
/* Emit TPREL relocation to initialize GOT slot
at run-time. */
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32);
outrel.r_addend = relocation - elf_hash_table (info)->tls_sec->vma;
break;
default:
BFD_ASSERT (FALSE);
}
/* Offset of the GOT entry. */
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ got_entry_offset);
/* Install one of the above relocations. */
elf_m68k_install_rela (output_bfd, srela, &outrel);
bfd_put_32 (output_bfd, outrel.r_addend, sgot->contents + got_entry_offset);
}
/* Relocate an M68K ELF section. */
@ -3495,6 +3590,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
asection *sgot;
asection *splt;
asection *sreloc;
asection *srela;
struct elf_m68k_got *got;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
@ -3506,6 +3602,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
sgot = NULL;
splt = NULL;
sreloc = NULL;
srela = NULL;
got = NULL;
@ -3704,7 +3801,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
because of a version file.. We must initialize
because of a version file. We must initialize
this entry in the global offset table. Since
the offset must always be a multiple of 4, we
use the least significant bit to record whether
@ -3714,26 +3811,12 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O)
bfd_put_32 (output_bfd, relocation,
sgot->contents + off);
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_GD32)
/* Mark it as belonging to module 1,
the executable. */
{
bfd_put_32 (output_bfd, 1,
sgot->contents + off);
bfd_put_32 (output_bfd, (relocation
- dtpoff_base (info)),
sgot->contents + off + 4);
}
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_IE32)
bfd_put_32 (output_bfd, tpoff (info, relocation),
sgot->contents + off);
else
BFD_ASSERT (FALSE);
elf_m68k_init_got_entry_static (info,
output_bfd,
r_type,
sgot,
off,
relocation);
*off_ptr |= 1;
}
@ -3741,103 +3824,32 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
unresolved_reloc = FALSE;
}
else if (info->shared) /* && h == NULL */
/* Process local symbol during dynamic link. */
{
asection *srela;
Elf_Internal_Rela outrel;
srela = bfd_get_section_by_name (dynobj, ".rela.got");
BFD_ASSERT (srela != NULL);
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O)
if (srela == NULL)
{
/* Emit RELATIVE relocation to initialize GOT slot
at run-time. */
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
outrel.r_addend = relocation;
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
elf_m68k_install_rela (output_bfd, srela, &outrel);
srela = bfd_get_section_by_name (dynobj, ".rela.got");
BFD_ASSERT (srela != NULL);
}
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_LDM32)
{
/* If we don't know the module number, create
a relocation for it. */
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32);
outrel.r_addend = 0;
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
elf_m68k_install_rela (output_bfd, srela, &outrel);
}
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_GD32)
{
/* If we don't know the module number, create
a relocation for it. */
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32);
outrel.r_addend = 0;
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
elf_m68k_install_rela (output_bfd, srela, &outrel);
bfd_put_32 (output_bfd, (relocation
- dtpoff_base (info)),
sgot->contents + off + 4);
}
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_IE32)
{
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32);
outrel.r_addend = relocation - dtpoff_base (info);
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
elf_m68k_install_rela (output_bfd, srela, &outrel);
}
else
BFD_ASSERT (FALSE);
bfd_put_32 (output_bfd, outrel.r_addend,
sgot->contents + off);
elf_m68k_init_got_entry_local_shared (info,
output_bfd,
r_type,
sgot,
off,
relocation,
srela);
*off_ptr |= 1;
}
else /* h == NULL && !info->shared */
{
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O)
bfd_put_32 (output_bfd, relocation,
sgot->contents + off);
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_LDM32)
/* If this is a static link, put the number of the
only module in the GOT slot. */
bfd_put_32 (output_bfd, 1, sgot->contents + off);
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_GD32)
{
/* If we are not emitting relocations for a
general dynamic reference, then we must be in a
static link or an executable link with the
symbol binding locally. Mark it as belonging
to module 1, the executable. */
bfd_put_32 (output_bfd, 1, sgot->contents + off);
bfd_put_32 (output_bfd, (relocation
- dtpoff_base (info)),
sgot->contents + off + 4);
}
else if (elf_m68k_reloc_got_type (r_type)
== R_68K_TLS_IE32)
bfd_put_32 (output_bfd, tpoff (info, relocation),
sgot->contents + off);
else
BFD_ASSERT (FALSE);
elf_m68k_init_got_entry_static (info,
output_bfd,
r_type,
sgot,
off,
relocation);
*off_ptr |= 1;
}
@ -3867,7 +3879,6 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
}
/* This relocation does not use the addend. */
BFD_ASSERT (rel->r_addend == 0);
rel->r_addend = 0;
}
else
@ -3895,7 +3906,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
return FALSE;
}
else
relocation = tpoff (info, relocation);
relocation -= tpoff_base (info);
break;
@ -4294,15 +4305,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
while (got_entry != NULL)
{
Elf_Internal_Rela rela;
enum elf_m68k_reloc_type r_type;
bfd_vma got_entry_offset;
r_type = got_entry->key_.type;
got_entry_offset = got_entry->u.s2.offset &~ (bfd_vma) 1;
rela.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ got_entry_offset);
/* If this is a -Bsymbolic link, and the symbol is defined
locally, we just want to emit a RELATIVE reloc. Likewise if
the symbol was forced to be local because of a version file.
@ -4311,33 +4319,43 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
if (info->shared
&& SYMBOL_REFERENCES_LOCAL (info, h))
{
rela.r_addend = bfd_get_signed_32 (output_bfd,
(sgot->contents
+ got_entry_offset));
bfd_vma relocation;
switch (elf_m68k_reloc_got_type (got_entry->key_.type))
relocation = bfd_get_signed_32 (output_bfd,
(sgot->contents
+ got_entry_offset));
/* Undo TP bias. */
switch (elf_m68k_reloc_got_type (r_type))
{
case R_68K_GOT32O:
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
case R_68K_TLS_LDM32:
break;
case R_68K_TLS_GD32:
rela.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32);
relocation += dtpoff_base (info);
break;
case R_68K_TLS_IE32:
rela.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32);
relocation += tpoff_base (info);
break;
default:
BFD_ASSERT (FALSE);
break;
}
elf_m68k_install_rela (output_bfd, srela, &rela);
elf_m68k_init_got_entry_local_shared (info,
output_bfd,
r_type,
sgot,
got_entry_offset,
relocation,
srela);
}
else
{
Elf_Internal_Rela rela;
/* Put zeros to GOT slots that will be initialized
at run-time. */
{
@ -4351,8 +4369,11 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
}
rela.r_addend = 0;
rela.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ got_entry_offset);
switch (elf_m68k_reloc_got_type (got_entry->key_.type))
switch (elf_m68k_reloc_got_type (r_type))
{
case R_68K_GOT32O:
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT);