diff options
author | Jakub Jelinek <jakub@redhat.com> | 2002-05-23 13:12:53 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2002-05-23 13:12:53 +0000 |
commit | 13ae64f3c752ec57e71471d8820c72823a8d827e (patch) | |
tree | 31161b5f99c140525dc599d1b5bff0fc3ab9ab2e /bfd/elfxx-ia64.c | |
parent | baf0cc5e964e70eccb5348c5e9097971d0e184d2 (diff) | |
download | gdb-13ae64f3c752ec57e71471d8820c72823a8d827e.zip gdb-13ae64f3c752ec57e71471d8820c72823a8d827e.tar.gz gdb-13ae64f3c752ec57e71471d8820c72823a8d827e.tar.bz2 |
* 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.c | 274 |
1 files changed, 258 insertions, 16 deletions
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index f92ab6a..943159b 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; |