summaryrefslogtreecommitdiff
path: root/bfd/elfxx-ia64.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2002-05-23 13:12:52 +0000
committerJakub Jelinek <jakub@redhat.com>2002-05-23 13:12:52 +0000
commit0bd2384fe1128c431edeab5b171f038cd1b0aaa5 (patch)
tree70e9710e457d11b9fc533c482441d24dba41cb22 /bfd/elfxx-ia64.c
parentf9a7273c7d4b6fbca7e384f4396b75a98704b852 (diff)
downloadgdb-0bd2384fe1128c431edeab5b171f038cd1b0aaa5.tar.gz
* elf.c (_bfd_elf_make_section_from_shdr): Set SEC_THREAD_LOCAL
for symbols from SHF_TLS section. (_bfd_elf_print_private_bfd_data): Add PT_TLS. (elf_fake_sections): Set SHF_TLS for SEC_THREAD_LOCAL sections. (map_sections_to_segments): Build PT_TLS segment if necessary. (assign_file_positions_for_segments): Likewise. (get_program_header_size): Account for PT_TLS segment. (swap_out_syms): Set type of BSF_THREAD_LOCAL symbols and symbols from SEC_THREAD_LOCAL sections to STT_TLS. * reloc.c: Add 386 and IA-64 TLS relocs. * section.c (SEC_THREAD_LOCAL): Define. (SEC_CONSTRUCTOR_TEXT, SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS): Remove. * elflink.h (elf_link_add_object_symbols): Support .tcommon. (size_dynamic_sections): If DF_STATIC_TLS, set DF_FLAGS unconditionally. (struct elf_final_link_info): Add first_tls_sec. (elf_bfd_final_link): Set first_tls_sec. Compute elf_hash_table (info)->tls_segment. (elf_link_output_extsym): Handle STT_TLS symbols. (elf_link_input_bfd): Likewise. * syms.c (BSF_THREAD_LOCAL): Define. * bfd-in2.h: Rebuilt. * libbfd.h: Rebuilt. * elf32-i386.c (elf_i386_tls_transition, dtpoff_base, tpoff, elf_i386_mkobject, elf_i386_object_p): New functions. (elf_howto_table): Add TLS relocs. (elf_i386_reloc_type_lookup): Support TLS relocs. (elf_i386_info_to_howto_rel): Likewise. (struct elf_i386_link_hash_entry): Add tls_type. (struct elf_i386_obj_tdata): New. (elf_i386_hash_entry, elf_i386_tdata, elf_i386_local_got_tls_type): New macros. (struct elf_i386_link_hash_table): Add tls_ldm_got. (link_hash_newfunc): Clear tls_type. (elf_i386_check_relocs): Support TLS relocs. (elf_i386_gc_sweep_hook): Likewise. (allocate_dynrelocs): Likewise. (elf_i386_size_dynamic_sections): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. (bfd_elf32_mkobject, elf_backend_object_p): Define. * elfxx-ia64.c (struct elfNN_ia64_dyn_sym_info): Add tprel_offset, dtpmod_offset, dtprel_offset, tprel_done, dtpmod_done, dtprel_done, want_tprel, want_dtpmod, want_dtprel. (elfNN_ia64_tprel_base, elfNN_ia64_dtprel_base): New functions. (ia64_howto_table): Add TLS relocs, rename R_IA64_LTOFF_TP22 to R_IA64_LTOFF_TPREL22. (elf_code_to_howto_index): Add TLS relocs. (elfNN_ia64_check_relocs): Support TLS relocs. (allocate_global_data_got): Account for TLS .got data. (allocate_dynrel_entries): Account for TLS dynamic relocations. (elfNN_ia64_install_value): Supprt TLS relocs. (set_got_entry): Support TLS relocs. (elfNN_ia64_relocate_section): Likewise. * config/obj-elf.c (elf_common): Renamed from obj_elf_common. (obj_elf_common): Call elf_common. (obj_elf_tls_common): New function. (elf_pseudo_tab): Support .tls_common. (special_sections): Add .tdata and .tbss. (obj_elf_change_section): Set SEC_THREAD_LOCAL for SHF_TLS sections. (obj_elf_parse_section_letters): Support T in section flags (SHF_TLS). (obj_elf_parse_section_letters): Include T in error message. * config/tc-ppc.c (ppc_section_letter): Likewise. * config/tc-alpha.c (alpha_elf_section_letter): Likewise. (tc_gen_reloc): Handle SEC_THREAD_LOCAL the same way as SEC_MERGE. * config/tc-sparc.c (md_apply_fix3): Likewise. * config/tc-i386.c (tc_i386_fix_adjustable): Add TLS relocs. Define them if not BFD_ASSEMBLER. (lex_got): Support @TLSGD, @TLSLDM, @GOTTPOFF, @TPOFF, @DTPOFF and @NTPOFF. (md_apply_fix3): Add TLS relocs. * config/tc-ia64.c (enum reloc_func): Add FUNC_DTP_MODULE, FUNC_DTP_RELATIVE, FUNC_TP_RELATIVE, FUNC_LT_DTP_MODULE, FUNC_LT_DTP_RELATIVE, FUNC_LT_TP_RELATIVE. (pseudo_func): Support @dtpmod(), @dtprel() and @tprel(). (ia64_elf_section_letter): Include T in error message. (md_begin): Support TLS operators. (md_operand): Likewise. (ia64_gen_real_reloc_type): Support TLS relocs. * testsuite/gas/i386/tlspic.s: New file. * testsuite/gas/i386/tlsd.s: New file. * testsuite/gas/i386/tlsnopic.s: New file. * testsuite/gas/i386/tlsd.d: New file. * testsuite/gas/i386/tlsnopic.d: New file. * testsuite/gas/i386/tlspic.d: New file. * testsuite/gas/i386/i386.exp: Add tlsd, tlsnopic and tlspic tests. * testsuite/gas/ia64/tls.s: New file. * testsuite/gas/ia64/tls.d: New file. * testsuite/gas/ia64/ia64.exp: Add tls test. * write.c (adjust_reloc_syms): Don't change symbols in SEC_THREAD_LOCAL sections to STT_SECTION + addend. * elf/common.h (PT_TLS, SHF_TLS, STT_TLS, DF_STATIC_TLS): Define. * elf/ia64.h (R_IA64_LTOFF_TPREL22): Renamed from R_IA64_LTOFF_TP22. * elf/i386.h: Add TLS relocs. * scripttempl/elf.sc: Add .rel{,a}.t{bss,data}, .tdata and .tbss. * ldlang.c (lang_add_section): Set SEC_THREAD_LOCAL for output section if necessary. Handle .tbss. (lang_size_sections): Clear _raw_size for .tbss section (it allocates space in PT_TLS segment only). * ldwrite.c (build_link_order): Build link order for .tbss too. * readelf.c (get_segment_type): Add PT_TLS. (get_elf_section_flags): Add SHF_TLS. (get_dynamic_flags): Optimize. Add DF_STATIC_TLS. (process_dynamic_segment): Use puts instead of printf. (get_symbol_type): Support STT_TLS. * objdump.c (dump_section_header): Remove SEC_CONSTRUCTOR_TEXT, SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS. Add SEC_THREAD_LOCAL.
Diffstat (limited to 'bfd/elfxx-ia64.c')
-rw-r--r--bfd/elfxx-ia64.c274
1 files changed, 258 insertions, 16 deletions
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c
index f92ab6ae0d8..943159b15b5 100644
--- a/bfd/elfxx-ia64.c
+++ b/bfd/elfxx-ia64.c
@@ -79,6 +79,9 @@ struct elfNN_ia64_dyn_sym_info
bfd_vma pltoff_offset;
bfd_vma plt_offset;
bfd_vma plt2_offset;
+ bfd_vma tprel_offset;
+ bfd_vma dtpmod_offset;
+ bfd_vma dtprel_offset;
/* The symbol table entry, if any, that this was derrived from. */
struct elf_link_hash_entry *h;
@@ -97,6 +100,9 @@ struct elfNN_ia64_dyn_sym_info
unsigned got_done : 1;
unsigned fptr_done : 1;
unsigned pltoff_done : 1;
+ unsigned tprel_done : 1;
+ unsigned dtpmod_done : 1;
+ unsigned dtprel_done : 1;
/* True for the different kinds of linker data we want created. */
unsigned want_got : 1;
@@ -105,6 +111,9 @@ struct elfNN_ia64_dyn_sym_info
unsigned want_plt : 1;
unsigned want_plt2 : 1;
unsigned want_pltoff : 1;
+ unsigned want_tprel : 1;
+ unsigned want_dtpmod : 1;
+ unsigned want_dtprel : 1;
};
struct elfNN_ia64_local_hash_entry
@@ -285,6 +294,10 @@ static bfd_vma set_pltoff_entry
PARAMS ((bfd *abfd, struct bfd_link_info *info,
struct elfNN_ia64_dyn_sym_info *dyn_i,
bfd_vma value, boolean));
+static bfd_vma elfNN_ia64_tprel_base
+ PARAMS ((struct bfd_link_info *info));
+static bfd_vma elfNN_ia64_dtprel_base
+ PARAMS ((struct bfd_link_info *info));
static int elfNN_ia64_unwind_entry_compare
PARAMS ((const PTR, const PTR));
static boolean elfNN_ia64_final_link
@@ -423,10 +436,25 @@ static reloc_howto_type ia64_howto_table[] =
IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, false, true),
IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, false, true),
+ IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, false, false),
IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, false, false),
+ IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, false, false),
IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, false, false),
IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, false, false),
- IA64_HOWTO (R_IA64_LTOFF_TP22, "LTOFF_TP22", 0, false, false),
+ IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, false, false),
+
+ IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, false, false),
+ IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, false, false),
+ IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, false, false),
+
+ IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, false, false),
+ IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, false, false),
+ IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, false, false),
+ IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, false, false),
+ IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, false, false),
+ IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, false, false),
+ IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, false, false),
+ IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, false, false),
};
static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
@@ -541,10 +569,25 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
+ case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
+ case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
- case BFD_RELOC_IA64_LTOFF_TP22: rtype = R_IA64_LTOFF_TP22; break;
+ case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
+
+ case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
+ case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
+ case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
+
+ case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
+ case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
+ case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
+ case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
+ case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
+ case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
+ case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
+ case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
default: return 0;
}
@@ -2097,6 +2140,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
NEED_FULL_PLT = 16,
NEED_DYNREL = 32,
NEED_LTOFF_FPTR = 64,
+ NEED_TPREL = 128,
+ NEED_DTPMOD = 256,
+ NEED_DTPREL = 512
};
struct elf_link_hash_entry *h = NULL;
@@ -2134,11 +2180,42 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
need_entry = 0;
switch (ELFNN_R_TYPE (rel->r_info))
{
- case R_IA64_TPREL22:
case R_IA64_TPREL64MSB:
case R_IA64_TPREL64LSB:
- case R_IA64_LTOFF_TP22:
- return false;
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_TPREL64LSB;
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_IA64_LTOFF_TPREL22:
+ need_entry = NEED_TPREL;
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_IA64_DTPREL64MSB:
+ case R_IA64_DTPREL64LSB:
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_DTPREL64LSB;
+ break;
+
+ case R_IA64_LTOFF_DTPREL22:
+ need_entry = NEED_DTPREL;
+ break;
+
+ case R_IA64_DTPMOD64MSB:
+ case R_IA64_DTPMOD64LSB:
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_DTPMOD64LSB;
+ break;
+
+ case R_IA64_LTOFF_DTPMOD22:
+ need_entry = NEED_DTPMOD;
+ break;
case R_IA64_LTOFF_FPTR22:
case R_IA64_LTOFF_FPTR64I:
@@ -2248,7 +2325,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
dyn_i->h = h;
/* Create what's needed. */
- if (need_entry & NEED_GOT)
+ if (need_entry & (NEED_GOT | NEED_TPREL | NEED_DTPMOD | NEED_DTPREL))
{
if (!got)
{
@@ -2256,7 +2333,14 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
if (!got)
return false;
}
- dyn_i->want_got = 1;
+ if (need_entry & NEED_GOT)
+ dyn_i->want_got = 1;
+ if (need_entry & NEED_TPREL)
+ dyn_i->want_tprel = 1;
+ if (need_entry & NEED_DTPMOD)
+ dyn_i->want_dtpmod = 1;
+ if (need_entry & NEED_DTPREL)
+ dyn_i->want_dtprel = 1;
}
if (need_entry & NEED_FPTR)
{
@@ -2336,6 +2420,21 @@ allocate_global_data_got (dyn_i, data)
dyn_i->got_offset = x->ofs;
x->ofs += 8;
}
+ if (dyn_i->want_tprel)
+ {
+ dyn_i->tprel_offset = x->ofs;
+ x->ofs += 8;
+ }
+ if (dyn_i->want_dtpmod)
+ {
+ dyn_i->dtpmod_offset = x->ofs;
+ x->ofs += 8;
+ }
+ if (dyn_i->want_dtprel)
+ {
+ dyn_i->dtprel_offset = x->ofs;
+ x->ofs += 8;
+ }
return true;
}
@@ -2582,6 +2681,10 @@ allocate_dynrel_entries (dyn_i, data)
if (!dynamic_symbol)
count *= 2;
break;
+ case R_IA64_TPREL64LSB:
+ case R_IA64_DTPREL64LSB:
+ case R_IA64_DTPMOD64LSB:
+ break;
default:
abort ();
}
@@ -2593,6 +2696,12 @@ allocate_dynrel_entries (dyn_i, data)
if (((dynamic_symbol || shared) && dyn_i->want_got)
|| (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ if ((dynamic_symbol || shared) && dyn_i->want_tprel)
+ ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ if ((dynamic_symbol || shared) && dyn_i->want_dtpmod)
+ ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ if (dynamic_symbol && dyn_i->want_dtprel)
+ ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
if (dyn_i->want_pltoff)
{
@@ -2903,7 +3012,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
/* Instruction relocations. */
- case R_IA64_IMM14: opnd = IA64_OPND_IMM14; break;
+ case R_IA64_IMM14:
+ case R_IA64_TPREL14:
+ case R_IA64_DTPREL14:
+ opnd = IA64_OPND_IMM14;
+ break;
case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
@@ -2920,6 +3033,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_PLTOFF22:
case R_IA64_PCREL22:
case R_IA64_LTOFF_FPTR22:
+ case R_IA64_TPREL22:
+ case R_IA64_DTPREL22:
+ case R_IA64_LTOFF_TPREL22:
+ case R_IA64_LTOFF_DTPMOD22:
+ case R_IA64_LTOFF_DTPREL22:
opnd = IA64_OPND_IMM22;
break;
@@ -2930,6 +3048,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_PCREL64I:
case R_IA64_FPTR64I:
case R_IA64_LTOFF_FPTR64I:
+ case R_IA64_TPREL64I:
+ case R_IA64_DTPREL64I:
opnd = IA64_OPND_IMMU64;
break;
@@ -2943,6 +3063,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_SEGREL32MSB:
case R_IA64_SECREL32MSB:
case R_IA64_LTV32MSB:
+ case R_IA64_DTPREL32MSB:
size = 4; bigendian = 1;
break;
@@ -2954,6 +3075,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_SEGREL32LSB:
case R_IA64_SECREL32LSB:
case R_IA64_LTV32LSB:
+ case R_IA64_DTPREL32LSB:
size = 4; bigendian = 0;
break;
@@ -2966,6 +3088,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_SEGREL64MSB:
case R_IA64_SECREL64MSB:
case R_IA64_LTV64MSB:
+ case R_IA64_TPREL64MSB:
+ case R_IA64_DTPMOD64MSB:
+ case R_IA64_DTPREL64MSB:
size = 8; bigendian = 1;
break;
@@ -2978,6 +3103,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
case R_IA64_SEGREL64LSB:
case R_IA64_SECREL64LSB:
case R_IA64_LTV64LSB:
+ case R_IA64_TPREL64LSB:
+ case R_IA64_DTPMOD64LSB:
+ case R_IA64_DTPREL64LSB:
size = 8; bigendian = 0;
break;
@@ -3132,26 +3260,53 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *got_sec;
+ boolean done;
+ bfd_vma got_offset;
ia64_info = elfNN_ia64_hash_table (info);
got_sec = ia64_info->got_sec;
- BFD_ASSERT ((dyn_i->got_offset & 7) == 0);
-
- if (! dyn_i->got_done)
+ switch (dyn_r_type)
{
+ case R_IA64_TPREL64LSB:
+ done = dyn_i->tprel_done;
+ dyn_i->tprel_done = true;
+ got_offset = dyn_i->tprel_offset;
+ break;
+ case R_IA64_DTPMOD64LSB:
+ done = dyn_i->dtpmod_done;
+ dyn_i->dtpmod_done = true;
+ got_offset = dyn_i->dtpmod_offset;
+ break;
+ case R_IA64_DTPREL64LSB:
+ done = dyn_i->dtprel_done;
+ dyn_i->dtprel_done = true;
+ got_offset = dyn_i->dtprel_offset;
+ break;
+ default:
+ done = dyn_i->got_done;
dyn_i->got_done = true;
+ got_offset = dyn_i->got_offset;
+ break;
+ }
+ BFD_ASSERT ((got_offset & 7) == 0);
+
+ if (! done)
+ {
/* Store the target address in the linkage table entry. */
- bfd_put_64 (abfd, value, got_sec->contents + dyn_i->got_offset);
+ bfd_put_64 (abfd, value, got_sec->contents + got_offset);
/* Install a dynamic relocation if needed. */
- if (info->shared
+ if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
|| elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
|| elfNN_ia64_aix_vec (abfd->xvec)
|| (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
{
- if (dynindx == -1)
+ if (dynindx == -1
+ && dyn_r_type != R_IA64_TPREL64LSB
+ && dyn_r_type != R_IA64_DTPMOD64LSB
+ && dyn_r_type != R_IA64_DTPREL64LSB)
{
dyn_r_type = R_IA64_REL64LSB;
dynindx = 0;
@@ -3171,6 +3326,15 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
case R_IA64_FPTR64LSB:
dyn_r_type = R_IA64_FPTR64MSB;
break;
+ case R_IA64_TPREL64LSB:
+ dyn_r_type = R_IA64_TPREL64MSB;
+ break;
+ case R_IA64_DTPMOD64LSB:
+ dyn_r_type = R_IA64_DTPMOD64MSB;
+ break;
+ case R_IA64_DTPREL64LSB:
+ dyn_r_type = R_IA64_DTPREL64MSB;
+ break;
default:
BFD_ASSERT (false);
break;
@@ -3179,7 +3343,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
ia64_info->rel_got_sec,
- dyn_i->got_offset, dyn_r_type,
+ got_offset, dyn_r_type,
dynindx, addend);
}
}
@@ -3187,7 +3351,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
/* Return the address of the linkage table entry. */
value = (got_sec->output_section->vma
+ got_sec->output_offset
- + dyn_i->got_offset);
+ + got_offset);
return value;
}
@@ -3285,6 +3449,35 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
return value;
}
+/* Return the base VMA address which should be subtracted from real addresses
+ when resolving @tprel() relocation.
+ Main program TLS (whose template starts at PT_TLS p_vaddr)
+ is assigned offset round(16, PT_TLS p_align). */
+
+static bfd_vma
+elfNN_ia64_tprel_base (info)
+ struct bfd_link_info *info;
+{
+ struct elf_link_tls_segment *tls_segment
+ = elf_hash_table (info)->tls_segment;
+
+ BFD_ASSERT (tls_segment != NULL);
+ return (tls_segment->start
+ - align_power ((bfd_vma) 16, tls_segment->align));
+}
+
+/* Return the base VMA address which should be subtracted from real addresses
+ when resolving @dtprel() relocation.
+ This is PT_TLS segment p_vaddr. */
+
+static bfd_vma
+elfNN_ia64_dtprel_base (info)
+ struct bfd_link_info *info;
+{
+ BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
+ return elf_hash_table (info)->tls_segment->start;
+}
+
/* Called through qsort to sort the .IA_64.unwind section during a
non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
to the output bfd so we can do proper endianness frobbing. */
@@ -4030,6 +4223,55 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
r_type);
break;
+ case R_IA64_TPREL14:
+ case R_IA64_TPREL22:
+ case R_IA64_TPREL64I:
+ value -= elfNN_ia64_tprel_base (info);
+ r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ break;
+
+ case R_IA64_DTPREL14:
+ case R_IA64_DTPREL22:
+ case R_IA64_DTPREL64I:
+ value -= elfNN_ia64_dtprel_base (info);
+ r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ break;
+
+ case R_IA64_LTOFF_TPREL22:
+ case R_IA64_LTOFF_DTPMOD22:
+ case R_IA64_LTOFF_DTPREL22:
+ {
+ int got_r_type;
+
+ switch (r_type)
+ {
+ default:
+ case R_IA64_LTOFF_TPREL22:
+ if (!dynamic_symbol_p && !info->shared)
+ value -= elfNN_ia64_tprel_base (info);
+ got_r_type = R_IA64_TPREL64LSB;
+ break;
+ case R_IA64_LTOFF_DTPMOD22:
+ if (!dynamic_symbol_p && !info->shared)
+ value = 1;
+ got_r_type = R_IA64_DTPMOD64LSB;
+ break;
+ case R_IA64_LTOFF_DTPREL22:
+ if (!dynamic_symbol_p)
+ value -= elfNN_ia64_dtprel_base (info);
+ got_r_type = R_IA64_DTPREL64LSB;
+ break;
+ }
+ dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, false);
+ value = set_got_entry (input_bfd, info, dyn_i,
+ (h ? h->dynindx : -1), rel->r_addend,
+ value, got_r_type);
+ value -= gp_val;
+ r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
+ r_type);
+ }
+ break;
+
default:
r = bfd_reloc_notsupported;
break;