aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.h
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2002-05-23 13:12:53 +0000
committerJakub Jelinek <jakub@redhat.com>2002-05-23 13:12:53 +0000
commit13ae64f3c752ec57e71471d8820c72823a8d827e (patch)
tree31161b5f99c140525dc599d1b5bff0fc3ab9ab2e /bfd/elflink.h
parentbaf0cc5e964e70eccb5348c5e9097971d0e184d2 (diff)
downloadgdb-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/elflink.h')
-rw-r--r--bfd/elflink.h96
1 files changed, 91 insertions, 5 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 4c5661b..5046416 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -1723,7 +1723,23 @@ elf_link_add_object_symbols (abfd, info)
if (name == (const char *) NULL)
goto error_return;
- if (add_symbol_hook)
+ if (sym.st_shndx == SHN_COMMON && ELF_ST_TYPE (sym.st_info) == STT_TLS)
+ {
+ asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
+
+ if (tcomm == NULL)
+ {
+ tcomm = bfd_make_section (abfd, ".tcommon");
+ if (tcomm == NULL
+ || !bfd_set_section_flags (abfd, tcomm, (SEC_ALLOC
+ | SEC_IS_COMMON
+ | SEC_LINKER_CREATED
+ | SEC_THREAD_LOCAL)))
+ goto error_return;
+ }
+ sec = tcomm;
+ }
+ else if (add_symbol_hook)
{
if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,
&value))
@@ -3457,7 +3473,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
elf_tdata (output_bfd)->cverdefs = cdefs;
}
- if (info->new_dtags && info->flags)
+ if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
{
if (! elf_add_dynamic_entry (info, (bfd_vma) DT_FLAGS, info->flags))
return false;
@@ -4481,6 +4497,8 @@ struct elf_final_link_info
asection *hash_sec;
/* symbol version section (.gnu.version). */
asection *symver_sec;
+ /* first SHF_TLS section (if any). */
+ asection *first_tls_sec;
/* Buffer large enough to hold contents of any section. */
bfd_byte *contents;
/* Buffer large enough to hold external relocs of any section. */
@@ -4960,6 +4978,14 @@ elf_bfd_final_link (abfd, info)
finfo.symbuf = NULL;
finfo.symshndxbuf = NULL;
finfo.symbuf_count = 0;
+ finfo.first_tls_sec = NULL;
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ if ((o->flags & SEC_THREAD_LOCAL) != 0
+ && (o->flags & SEC_LOAD) != 0)
+ {
+ finfo.first_tls_sec = o;
+ break;
+ }
/* Count up the number of relocations we will output for each output
section, so that we know the sizes of the reloc sections. We
@@ -5324,6 +5350,40 @@ elf_bfd_final_link (abfd, info)
goto error_return;
}
+ if (finfo.first_tls_sec)
+ {
+ unsigned int align = 0;
+ bfd_vma base = finfo.first_tls_sec->vma, end = 0;
+ asection *sec;
+
+ for (sec = finfo.first_tls_sec;
+ sec && (sec->flags & SEC_THREAD_LOCAL);
+ sec = sec->next)
+ {
+ bfd_vma size = sec->_raw_size;
+
+ if (bfd_get_section_alignment (abfd, sec) > align)
+ align = bfd_get_section_alignment (abfd, sec);
+ if (sec->_raw_size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ struct bfd_link_order *o;
+
+ size = 0;
+ for (o = sec->link_order_head; o != NULL; o = o->next)
+ if (size < o->offset + o->size)
+ size = o->offset + o->size;
+ }
+ end = sec->vma + size;
+ }
+ elf_hash_table (info)->tls_segment
+ = bfd_zalloc (abfd, sizeof (struct elf_link_tls_segment));
+ if (elf_hash_table (info)->tls_segment == NULL)
+ goto error_return;
+ elf_hash_table (info)->tls_segment->start = base;
+ elf_hash_table (info)->tls_segment->size = end - base;
+ elf_hash_table (info)->tls_segment->align = align;
+ }
+
/* Since ELF permits relocations to be against local symbols, we
must have the local symbols available when we do the relocations.
Since we would rather only read the local symbols once, and we
@@ -6100,7 +6160,16 @@ elf_link_output_extsym (h, data)
addresses. */
sym.st_value = h->root.u.def.value + input_sec->output_offset;
if (! finfo->info->relocateable)
- sym.st_value += input_sec->output_section->vma;
+ {
+ sym.st_value += input_sec->output_section->vma;
+ if (h->type == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS segment
+ base. */
+ BFD_ASSERT (finfo->first_tls_sec != NULL);
+ sym.st_value -= finfo->first_tls_sec->vma;
+ }
+ }
}
else
{
@@ -6564,7 +6633,15 @@ elf_link_input_bfd (finfo, input_bfd)
these requirements. */
osym.st_value += isec->output_offset;
if (! finfo->info->relocateable)
- osym.st_value += isec->output_section->vma;
+ {
+ osym.st_value += isec->output_section->vma;
+ if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS segment base. */
+ BFD_ASSERT (finfo->first_tls_sec != NULL);
+ osym.st_value -= finfo->first_tls_sec->vma;
+ }
+ }
if (! elf_link_output_sym (finfo, name, &osym, isec))
return false;
@@ -6899,7 +6976,16 @@ elf_link_input_bfd (finfo, input_bfd)
isym->st_value += sec->output_offset;
if (! finfo->info->relocateable)
- isym->st_value += osec->vma;
+ {
+ isym->st_value += osec->vma;
+ if (ELF_ST_TYPE (isym->st_info) == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS
+ segment base. */
+ BFD_ASSERT (finfo->first_tls_sec != NULL);
+ isym->st_value -= finfo->first_tls_sec->vma;
+ }
+ }
finfo->indices[r_symndx]
= bfd_get_symcount (output_bfd);