* 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:
parent
e5f2b1de7c
commit
325e58c76a
@ -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
|
||||
|
301
bfd/elf32-m68k.c
301
bfd/elf32-m68k.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user