aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elf32-m68k.c301
2 files changed, 173 insertions, 140 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 12966bc..3e8634f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,17 @@
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
non_got_ref value.
(elf_m68k_check_relocs): Handle dynamic TLS relocations.
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index ced19a1..1eeb978 100644
--- a/bfd/elf32-m68k.c
+++ b/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)
- {
- /* 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);
- }
- 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)
+ if (srela == NULL)
{
- 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);
+ srela = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (srela != NULL);
}
- 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;
+
+ relocation = bfd_get_signed_32 (output_bfd,
+ (sgot->contents
+ + got_entry_offset));
- switch (elf_m68k_reloc_got_type (got_entry->key_.type))
+ /* 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);