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 /gas | |
parent | baf0cc5e964e70eccb5348c5e9097971d0e184d2 (diff) | |
download | binutils-13ae64f3c752ec57e71471d8820c72823a8d827e.zip binutils-13ae64f3c752ec57e71471d8820c72823a8d827e.tar.gz binutils-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 'gas')
-rw-r--r-- | gas/ChangeLog | 42 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 52 | ||||
-rw-r--r-- | gas/config/tc-alpha.c | 5 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 38 | ||||
-rw-r--r-- | gas/config/tc-ia64.c | 115 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 2 | ||||
-rw-r--r-- | gas/config/tc-sparc.c | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/i386.exp | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlsd.d | 33 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlsd.s | 42 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlsnopic.d | 31 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlsnopic.s | 45 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlspic.d | 23 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/tlspic.s | 27 | ||||
-rw-r--r-- | gas/testsuite/gas/ia64/ia64.exp | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/ia64/tls.d | 53 | ||||
-rw-r--r-- | gas/testsuite/gas/ia64/tls.s | 64 | ||||
-rw-r--r-- | gas/write.c | 7 |
18 files changed, 560 insertions, 24 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 9d8b183..9e9b168 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,45 @@ +2002-05-23 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2002-05-23 Nick Clifton <nickc@cambridge.redhat.com> * config/tc-arm.c (md_apply_fix3): For the Thumb BLX reloc diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 8aca056..5524b07 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -61,6 +61,7 @@ static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR)); static void build_group_lists PARAMS ((bfd *, asection *, PTR)); static int elf_separate_stab_sections PARAMS ((void)); static void elf_init_stab_section PARAMS ((segT)); +static symbolS *elf_common PARAMS ((int)); #ifdef NEED_ECOFF_DEBUG static boolean elf_get_extr PARAMS ((asymbol *, EXTR *)); @@ -84,6 +85,7 @@ static int obj_elf_section_type PARAMS ((char *, size_t)); static void obj_elf_symver PARAMS ((int)); static void obj_elf_subsection PARAMS ((int)); static void obj_elf_popsection PARAMS ((int)); +static void obj_elf_tls_common PARAMS ((int)); static const pseudo_typeS elf_pseudo_table[] = { @@ -130,6 +132,8 @@ static const pseudo_typeS elf_pseudo_table[] = {"data", obj_elf_data, 0}, {"text", obj_elf_text, 0}, + {"tls_common", obj_elf_tls_common, 0}, + /* End sentinel. */ {NULL, NULL, 0}, }; @@ -280,8 +284,8 @@ elf_file_symbol (s) #endif } -void -obj_elf_common (is_common) +static symbolS * +elf_common (is_common) int is_common; { char *name; @@ -294,7 +298,7 @@ obj_elf_common (is_common) if (flag_mri && is_common) { s_mri_common (0); - return; + return NULL; } name = input_line_pointer; @@ -307,14 +311,14 @@ obj_elf_common (is_common) { as_bad (_("expected comma after symbol-name")); ignore_rest_of_line (); - return; + return NULL; } input_line_pointer++; /* skip ',' */ if ((temp = get_absolute_expression ()) < 0) { as_bad (_(".COMMon length (%d.) <0! Ignored."), temp); ignore_rest_of_line (); - return; + return NULL; } size = temp; *p = 0; @@ -324,7 +328,7 @@ obj_elf_common (is_common) { as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); ignore_rest_of_line (); - return; + return NULL; } if (S_GET_VALUE (symbolP) != 0) { @@ -374,7 +378,7 @@ obj_elf_common (is_common) { as_bad (_("common alignment not a power of 2")); ignore_rest_of_line (); - return; + return NULL; } } else @@ -426,7 +430,7 @@ obj_elf_common (is_common) symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; demand_empty_rest_of_line (); - return; + return symbolP; { bad_common_segment: @@ -439,10 +443,27 @@ obj_elf_common (is_common) *p = c; input_line_pointer = p; ignore_rest_of_line (); - return; + return NULL; } } +void +obj_elf_common (is_common) + int is_common; +{ + elf_common (is_common); +} + +static void +obj_elf_tls_common (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + symbolS *symbolP = elf_common (0); + + if (symbolP) + symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL; +} + static void obj_elf_local (ignore) int ignore ATTRIBUTE_UNUSED; @@ -594,6 +615,8 @@ static struct special_section const special_sections[] = { ".note", SHT_NOTE, 0 }, { ".rodata", SHT_PROGBITS, SHF_ALLOC }, { ".rodata1", SHT_PROGBITS, SHF_ALLOC }, + { ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS }, + { ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS }, { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, #if 0 /* FIXME: The current gcc, as of 2002-03-03, will emit @@ -717,7 +740,8 @@ obj_elf_change_section (name, type, attr, entsize, group_name, push) | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0) | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0) | ((attr & SHF_MERGE) ? SEC_MERGE : 0) - | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0)); + | ((attr & SHF_STRINGS) ? SEC_STRINGS : 0) + | ((attr & SHF_TLS) ? SEC_THREAD_LOCAL : 0)); #ifdef md_elf_section_flags flags = md_elf_section_flags (flags, attr, type); #endif @@ -749,7 +773,8 @@ obj_elf_change_section (name, type, attr, entsize, group_name, push) saw the first time. */ if ((old_sec->flags ^ flags) & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE - | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS)) + | SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS + | SEC_THREAD_LOCAL)) as_warn (_("ignoring changed section attributes for %s"), name); else if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize) as_warn (_("ignoring changed section entity size for %s"), name); @@ -792,6 +817,9 @@ obj_elf_parse_section_letters (str, len) case 'G': attr |= SHF_GROUP; break; + case 'T': + attr |= SHF_TLS; + break; /* Compatibility. */ case 'm': if (*(str - 1) == 'a') @@ -806,7 +834,7 @@ obj_elf_parse_section_letters (str, len) } default: { - char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G"); + char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G,T"); #ifdef md_elf_section_letter int md_attr = md_elf_section_letter (*str, &bad_msg); if (md_attr >= 0) diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index ab2d40b..7746f99 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -1556,7 +1556,8 @@ tc_gen_reloc (sec, fixp) * of thing, and as a result we need to fake it out here. */ if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy) - || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)) + || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) + || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL)) && !S_IS_COMMON (fixp->fx_addsy)) reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value; #endif @@ -5467,7 +5468,7 @@ alpha_elf_section_letter (letter, ptr_msg) if (letter == 's') return SHF_ALPHA_GPREL; - *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string"); + *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string"); return 0; } diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index f681014..653245f 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1219,6 +1219,12 @@ tc_i386_fix_adjustable (fixP) if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF || fixP->fx_r_type == BFD_RELOC_386_PLT32 || fixP->fx_r_type == BFD_RELOC_386_GOT32 + || fixP->fx_r_type == BFD_RELOC_386_TLS_GD + || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM + || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 + || fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32 + || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32 + || fixP->fx_r_type == BFD_RELOC_386_TLS_LE || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL @@ -1236,6 +1242,12 @@ tc_i386_fix_adjustable (fixP) #define BFD_RELOC_386_PLT32 0 #define BFD_RELOC_386_GOT32 0 #define BFD_RELOC_386_GOTOFF 0 +#define BFD_RELOC_386_TLS_GD 0 +#define BFD_RELOC_386_TLS_LDM 0 +#define BFD_RELOC_386_TLS_LDO_32 0 +#define BFD_RELOC_386_TLS_IE_32 0 +#define BFD_RELOC_386_TLS_LE_32 0 +#define BFD_RELOC_386_TLS_LE 0 #define BFD_RELOC_X86_64_PLT32 0 #define BFD_RELOC_X86_64_GOT32 0 #define BFD_RELOC_X86_64_GOTPCREL 0 @@ -3371,10 +3383,16 @@ lex_got (reloc, adjust) const char *str; const RELOC_ENUM rel[NUM_FLAG_CODE]; } gotrel[] = { - { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } }, - { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } }, - { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } }, - { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } } + { "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } }, + { "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } }, + { "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } }, + { "TLSGD", { BFD_RELOC_386_TLS_GD, 0, 0 } }, + { "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0, 0 } }, + { "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, 0, 0 } }, + { "TPOFF", { BFD_RELOC_386_TLS_LE_32, 0, 0 } }, + { "NTPOFF", { BFD_RELOC_386_TLS_LE, 0, 0 } }, + { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, 0, 0 } }, + { "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } } }; char *cp; unsigned int j; @@ -4577,6 +4595,12 @@ md_apply_fix3 (fixP, valP, seg) value -= 1; break; case BFD_RELOC_386_GOT32: + case BFD_RELOC_386_TLS_GD: + case BFD_RELOC_386_TLS_LDM: + case BFD_RELOC_386_TLS_LDO_32: + case BFD_RELOC_386_TLS_IE_32: + case BFD_RELOC_386_TLS_LE_32: + case BFD_RELOC_386_TLS_LE: case BFD_RELOC_X86_64_GOT32: value = 0; /* Fully resolved at runtime. No addend. */ break; @@ -5045,6 +5069,12 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_386_GOT32: case BFD_RELOC_386_GOTOFF: case BFD_RELOC_386_GOTPC: + case BFD_RELOC_386_TLS_GD: + case BFD_RELOC_386_TLS_LDM: + case BFD_RELOC_386_TLS_LDO_32: + case BFD_RELOC_386_TLS_IE_32: + case BFD_RELOC_386_TLS_LE_32: + case BFD_RELOC_386_TLS_LE: case BFD_RELOC_X86_64_32S: case BFD_RELOC_RVA: case BFD_RELOC_VTABLE_ENTRY: diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index cbbc914..ae26ada 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -77,6 +77,8 @@ enum special_section enum reloc_func { + FUNC_DTP_MODULE, + FUNC_DTP_RELATIVE, FUNC_FPTR_RELATIVE, FUNC_GP_RELATIVE, FUNC_LT_RELATIVE, @@ -84,8 +86,12 @@ enum reloc_func FUNC_PLT_RELATIVE, FUNC_SEC_RELATIVE, FUNC_SEG_RELATIVE, + FUNC_TP_RELATIVE, FUNC_LTV_RELATIVE, FUNC_LT_FPTR_RELATIVE, + FUNC_LT_DTP_MODULE, + FUNC_LT_DTP_RELATIVE, + FUNC_LT_TP_RELATIVE, FUNC_IPLT_RELOC, }; @@ -476,6 +482,8 @@ static struct pseudo_func[] = { /* reloc pseudo functions (these must come first!): */ + { "dtpmod", PSEUDO_FUNC_RELOC, { 0 } }, + { "dtprel", PSEUDO_FUNC_RELOC, { 0 } }, { "fptr", PSEUDO_FUNC_RELOC, { 0 } }, { "gprel", PSEUDO_FUNC_RELOC, { 0 } }, { "ltoff", PSEUDO_FUNC_RELOC, { 0 } }, @@ -483,8 +491,12 @@ pseudo_func[] = { "pltoff", PSEUDO_FUNC_RELOC, { 0 } }, { "secrel", PSEUDO_FUNC_RELOC, { 0 } }, { "segrel", PSEUDO_FUNC_RELOC, { 0 } }, + { "tprel", PSEUDO_FUNC_RELOC, { 0 } }, { "ltv", PSEUDO_FUNC_RELOC, { 0 } }, { "", 0, { 0 } }, /* placeholder for FUNC_LT_FPTR_RELATIVE */ + { "", 0, { 0 } }, /* placeholder for FUNC_LT_DTP_MODULE */ + { "", 0, { 0 } }, /* placeholder for FUNC_LT_DTP_RELATIVE */ + { "", 0, { 0 } }, /* placeholder for FUNC_LT_TP_RELATIVE */ { "iplt", PSEUDO_FUNC_RELOC, { 0 } }, /* mbtype4 constants: */ @@ -943,7 +955,7 @@ ia64_elf_section_letter (letter, ptr_msg) if (letter == 's') return SHF_IA_64_SHORT; - *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string"); + *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string"); return 0; } @@ -6494,6 +6506,14 @@ md_begin () bfd_set_section_alignment (stdoutput, text_section, 4); target_big_endian = TARGET_BYTES_BIG_ENDIAN; + pseudo_func[FUNC_DTP_MODULE].u.sym = + symbol_new (".<dtpmod>", undefined_section, FUNC_DTP_MODULE, + &zero_address_frag); + + pseudo_func[FUNC_DTP_RELATIVE].u.sym = + symbol_new (".<dtprel>", undefined_section, FUNC_DTP_RELATIVE, + &zero_address_frag); + pseudo_func[FUNC_FPTR_RELATIVE].u.sym = symbol_new (".<fptr>", undefined_section, FUNC_FPTR_RELATIVE, &zero_address_frag); @@ -6522,6 +6542,10 @@ md_begin () symbol_new (".<segrel>", undefined_section, FUNC_SEG_RELATIVE, &zero_address_frag); + pseudo_func[FUNC_TP_RELATIVE].u.sym = + symbol_new (".<tprel>", undefined_section, FUNC_TP_RELATIVE, + &zero_address_frag); + pseudo_func[FUNC_LTV_RELATIVE].u.sym = symbol_new (".<ltv>", undefined_section, FUNC_LTV_RELATIVE, &zero_address_frag); @@ -6530,6 +6554,18 @@ md_begin () symbol_new (".<ltoff.fptr>", undefined_section, FUNC_LT_FPTR_RELATIVE, &zero_address_frag); + pseudo_func[FUNC_LT_DTP_MODULE].u.sym = + symbol_new (".<ltoff.dtpmod>", undefined_section, FUNC_LT_DTP_MODULE, + &zero_address_frag); + + pseudo_func[FUNC_LT_DTP_RELATIVE].u.sym = + symbol_new (".<ltoff.dptrel>", undefined_section, FUNC_LT_DTP_RELATIVE, + &zero_address_frag); + + pseudo_func[FUNC_LT_TP_RELATIVE].u.sym = + symbol_new (".<ltoff.tprel>", undefined_section, FUNC_LT_TP_RELATIVE, + &zero_address_frag); + pseudo_func[FUNC_IPLT_RELOC].u.sym = symbol_new (".<iplt>", undefined_section, FUNC_IPLT_RELOC, &zero_address_frag); @@ -9826,11 +9862,22 @@ md_operand (e) as_bad ("Not a symbolic expression"); goto err; } - if (S_GET_VALUE (e->X_op_symbol) == FUNC_FPTR_RELATIVE - && i == FUNC_LT_RELATIVE) - i = FUNC_LT_FPTR_RELATIVE; - else + if (i != FUNC_LT_RELATIVE) + { + as_bad ("Illegal combination of relocation functions"); + goto err; + } + switch (S_GET_VALUE (e->X_op_symbol)) { + case FUNC_FPTR_RELATIVE: + i = FUNC_LT_FPTR_RELATIVE; break; + case FUNC_DTP_MODULE: + i = FUNC_LT_DTP_MODULE; break; + case FUNC_DTP_RELATIVE: + i = FUNC_LT_DTP_RELATIVE; break; + case FUNC_TP_RELATIVE: + i = FUNC_LT_TP_RELATIVE; break; + default: as_bad ("Illegal combination of relocation functions"); goto err; } @@ -10163,6 +10210,64 @@ ia64_gen_real_reloc_type (sym, r_type) } break; + case FUNC_TP_RELATIVE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM14: + new = BFD_RELOC_IA64_TPREL14; break; + case BFD_RELOC_IA64_IMM22: + new = BFD_RELOC_IA64_TPREL22; break; + case BFD_RELOC_IA64_IMM64: + new = BFD_RELOC_IA64_TPREL64I; break; + default: + break; + } + break; + + case FUNC_LT_TP_RELATIVE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM22: + new = BFD_RELOC_IA64_LTOFF_TPREL22; break; + default: + break; + } + break; + + case FUNC_LT_DTP_MODULE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM22: + new = BFD_RELOC_IA64_LTOFF_DTPMOD22; break; + default: + break; + } + break; + + case FUNC_DTP_RELATIVE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM14: + new = BFD_RELOC_IA64_DTPREL14; break; + case BFD_RELOC_IA64_IMM22: + new = BFD_RELOC_IA64_DTPREL22; break; + case BFD_RELOC_IA64_IMM64: + new = BFD_RELOC_IA64_DTPREL64I; break; + default: + break; + } + break; + + case FUNC_LT_DTP_RELATIVE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM22: + new = BFD_RELOC_IA64_LTOFF_DTPREL22; break; + default: + break; + } + break; + case FUNC_IPLT_RELOC: break; diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 808487b..e1c7c57 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -2485,7 +2485,7 @@ ppc_section_letter (letter, ptr_msg) if (letter == 'e') return SHF_EXCLUDE; - *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S in string"); + *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string"); return 0; } diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 2d75fef..80cf39e 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -2916,6 +2916,7 @@ md_apply_fix3 (fixP, valP, segment) && (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym) || (seg->flags & SEC_MERGE) + || (seg->flags & SEC_THREAD_LOCAL) || (sparc_pic_code && ! fixP->fx_pcrel) || (seg != segment && (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0) diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index e664680..23d654c 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -75,6 +75,9 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] && ![istarget *-*-linux*oldld*]) } then { run_dump_test "relax" + run_dump_test "tlsd" + run_dump_test "tlspic" + run_dump_test "tlsnopic" } set ASFLAGS "$old_ASFLAGS" diff --git a/gas/testsuite/gas/i386/tlsd.d b/gas/testsuite/gas/i386/tlsd.d new file mode 100644 index 0000000..62efaa3 --- /dev/null +++ b/gas/testsuite/gas/i386/tlsd.d @@ -0,0 +1,33 @@ +#objdump: -dr +#name: i386 dynamic tls + +.*: +file format .* + +Disassembly of section .text: + +0+000 <fn>: + 0: 55 [ ]*push %ebp + 1: 89 e5 [ ]*mov %esp,%ebp + 3: 53 [ ]*push %ebx + 4: 50 [ ]*push %eax + 5: e8 00 00 00 00 [ ]*call a <fn\+0xa> + a: 5b [ ]*pop %ebx + b: 81 c3 03 00 00 00 [ ]*add \$0x3,%ebx +[ ]+d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_ + 11: 8d 04 1d 00 00 00 00 [ ]*lea 0x0\(,%ebx,1\),%eax +[ ]+14: R_386_TLS_GD foo + 18: e8 fc ff ff ff [ ]*call 19 <fn\+0x19> +[ ]+19: R_386_PLT32 ___tls_get_addr + 1d: 8d 83 00 00 00 00 [ ]*lea 0x0\(%ebx\),%eax +[ ]+1f: R_386_TLS_LDM bar + 23: e8 fc ff ff ff [ ]*call 24 <fn\+0x24> +[ ]+24: R_386_PLT32 ___tls_get_addr + 28: 8d 7f 00 [ ]*lea 0x0\(%edi\),%edi + 2b: 8d 90 00 00 00 00 [ ]*lea 0x0\(%eax\),%edx +[ ]+2d: R_386_TLS_LDO_32 bar + 31: 8d 76 00 [ ]*lea 0x0\(%esi\),%esi + 34: 8d 88 00 00 00 00 [ ]*lea 0x0\(%eax\),%ecx +[ ]+36: R_386_TLS_LDO_32 baz + 3a: 8b 5d fc [ ]*mov 0xfffffffc\(%ebp\),%ebx + 3d: c9 [ ]*leave[ ]* + 3e: c3 [ ]*ret[ ]* diff --git a/gas/testsuite/gas/i386/tlsd.s b/gas/testsuite/gas/i386/tlsd.s new file mode 100644 index 0000000..9ce01ec --- /dev/null +++ b/gas/testsuite/gas/i386/tlsd.s @@ -0,0 +1,42 @@ + .section ".tdata", "awT", @progbits + .globl foo, baz + .hidden baz +foo: .long 25 +bar: .long 27 +baz: .long 29 + .text + .globl fn + .type fn,@function +fn: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %eax + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + + /* Dynamic TLS model, foo not known to be in the current object */ + leal foo@TLSGD(,%ebx,1), %eax + call ___tls_get_addr@PLT + /* %eax now contains &foo */ + + /* Dynamic TLS model, bar and baz known to be in the current object */ + leal bar@TLSLDM(%ebx), %eax + call ___tls_get_addr@PLT + + /* Just show that there can be arbitrary instructions here */ + leal 0(%edi, 1), %edi + + leal bar@DTPOFF(%eax), %edx + /* %edx now contains &bar */ + + /* Again, arbitrary instructions */ + leal 0(%esi, 1), %esi + + leal baz@DTPOFF(%eax), %ecx + /* %ecx now contains &baz */ + + movl -4(%ebp), %ebx + leave + ret diff --git a/gas/testsuite/gas/i386/tlsnopic.d b/gas/testsuite/gas/i386/tlsnopic.d new file mode 100644 index 0000000..64ec6e6 --- /dev/null +++ b/gas/testsuite/gas/i386/tlsnopic.d @@ -0,0 +1,31 @@ +#objdump: -dr +#name: i386 non-pic tls + +.*: +file format .* + +Disassembly of section .text: + +0+000 <fn>: + 0: 8b 15 00 00 00 00 [ ]*mov 0x0,%edx +[ ]+2: R_386_32 .text + 6: 81 c2 08 00 00 00 [ ]*add \$0x8,%edx +[ ]+8: R_386_GOTPC _GLOBAL_OFFSET_TABLE_ + c: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax + 12: 2b 82 00 00 00 00 [ ]*sub 0x0\(%edx\),%eax +[ ]+14: R_386_TLS_IE_32 foo + 18: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax + 1e: 2d 00 00 00 00 [ ]*sub \$0x0,%eax +[ ]+1f: R_386_TLS_LE_32 bar + 23: 65 8b 0d 00 00 00 00 [ ]*mov %gs:0x0,%ecx + 2a: 90 [ ]*nop[ ]* + 2b: 81 e9 00 00 00 00 [ ]*sub \$0x0,%ecx +[ ]+2d: R_386_TLS_LE_32 baz + 31: 65 8b 0d 00 00 00 00 [ ]*mov %gs:0x0,%ecx + 38: 90 [ ]*nop + 39: 90 [ ]*nop + 3a: 8d 81 00 00 00 00 [ ]*lea 0x0\(%ecx\),%eax +[ ]+3c: R_386_TLS_LE var + 40: 90 [ ]*nop + 41: 8d 91 00 00 00 00 lea 0x0\(%ecx\),%edx +[ ]+43: R_386_TLS_LE var2 + 47: c3 [ ]*ret[ ]* diff --git a/gas/testsuite/gas/i386/tlsnopic.s b/gas/testsuite/gas/i386/tlsnopic.s new file mode 100644 index 0000000..1b51b36 --- /dev/null +++ b/gas/testsuite/gas/i386/tlsnopic.s @@ -0,0 +1,45 @@ + .section ".tdata", "awT", @progbits + .globl baz + .hidden baz + .globl var + .hidden var2 +bar: .long 27 +baz: .long 29 +var: .long 31 +var2: .long 33 + .text + .globl fn + .type fn,@function +fn: + /* Main binary, no PIC */ +1: movl 1b, %edx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %edx + + /* foo can be anywhere in startup TLS */ + movl %gs:0, %eax + subl foo@GOTTPOFF(%edx), %eax + /* %eax now contains &foo */ + + /* bar only in the main program */ + movl %gs:0, %eax + subl $bar@TPOFF, %eax + /* %eax now contains &bar */ + + /* baz only in the main program */ + movl %gs:0, %ecx + /* Arbitrary instructions in between */ + nop + subl $baz@TPOFF, %ecx + /* %ecx now contains &baz */ + + /* var and var2 only in the main program */ + movl %gs:0, %ecx + /* Arbitrary instructions in between */ + nop + nop + leal var@NTPOFF(%ecx), %eax + /* Arbitrary instructions in between */ + nop + leal var2@NTPOFF(%ecx), %edx + + ret diff --git a/gas/testsuite/gas/i386/tlspic.d b/gas/testsuite/gas/i386/tlspic.d new file mode 100644 index 0000000..2444113 --- /dev/null +++ b/gas/testsuite/gas/i386/tlspic.d @@ -0,0 +1,23 @@ +#objdump: -dr +#name: i386 non-pic tls + +.*: +file format .* + +Disassembly of section .text: + +0+000 <fn>: + 0: 55 [ ]*push %ebp + 1: 89 e5 [ ]*mov %esp,%ebp + 3: 53 [ ]*push %ebx + 4: 50 [ ]*push %eax + 5: e8 00 00 00 00 [ ]*call a <fn\+0xa> + a: 5b [ ]*pop %ebx + b: 81 c3 03 00 00 00 [ ]*add \$0x3,%ebx +[ ]+d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_ + 11: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax + 17: 8d 76 00 [ ]*lea 0x0\(%esi\),%esi + 1a: 2b 83 00 00 00 00 [ ]*sub 0x0\(%ebx\),%eax +[ ]+1c: R_386_TLS_IE_32 foo + 20: 8b 5d fc [ ]*mov 0xfffffffc\(%ebp\),%ebx + 23: c9 [ ]*leave[ ]* + 24: c3 [ ]*ret[ ]* diff --git a/gas/testsuite/gas/i386/tlspic.s b/gas/testsuite/gas/i386/tlspic.s new file mode 100644 index 0000000..e445ab9 --- /dev/null +++ b/gas/testsuite/gas/i386/tlspic.s @@ -0,0 +1,27 @@ + .section ".tdata", "awT", @progbits + .globl foo +foo: .long 25 + .text + .globl fn + .type fn,@function +fn: + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %eax + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + + /* foo can be anywhere in the startup TLS */ + movl %gs:0, %eax + + /* Arbitrary instructions in between */ + leal 0(%esi, 1), %esi + + subl foo@GOTTPOFF(%ebx), %eax + /* %eax now contains &foo */ + + movl -4(%ebp), %ebx + leave + ret diff --git a/gas/testsuite/gas/ia64/ia64.exp b/gas/testsuite/gas/ia64/ia64.exp index 5c6db40..f8a647e 100644 --- a/gas/testsuite/gas/ia64/ia64.exp +++ b/gas/testsuite/gas/ia64/ia64.exp @@ -35,4 +35,5 @@ if [istarget "ia64-*"] then { run_dump_test "dv-mutex" run_dump_test "dv-safe" run_dump_test "dv-srlz" + run_dump_test "tls" } diff --git a/gas/testsuite/gas/ia64/tls.d b/gas/testsuite/gas/ia64/tls.d new file mode 100644 index 0000000..5ac1693 --- /dev/null +++ b/gas/testsuite/gas/ia64/tls.d @@ -0,0 +1,53 @@ +#objdump: -dr +#name: ia64 tls + +.*: +file format .* + +Disassembly of section \.text: + +0000000000000000 <foo>: + 0: 0d 20 21 0a 80 05 \[MFI\] alloc r36=ar\.pfs,8,5,0 + 2: LTOFF_TPREL22 x + 6: 00 00 00 02 00 00 nop\.f 0x0 + c: 04 08 00 90 addl r32=0,r1;; + 10: 0b 00 01 40 18 10 \[MMI\] ld8 r32=\[r32\];; + 16: 10 02 35 00 40 00 add r33=r32,r13 + 1c: 00 00 04 00 nop\.i 0x0;; + 20: 0b 10 00 1a 00 21 \[MMI\] mov r2=r13;; + 21: TPREL22 y + 26: 10 02 08 00 48 00 addl r33=0,r2 + 2c: 00 00 04 00 nop\.i 0x0;; + 30: 01 00 01 02 00 21 \[MII\] mov r32=r1 + 31: LTOFF_DTPMOD22 z + 32: LTOFF_DTPREL22 z + 36: 50 02 04 00 48 c0 addl r37=0,r1 + 3c: 04 08 00 90 addl r38=0,r1;; + 40: 19 28 01 4a 18 10 \[MMB\] ld8 r37=\[r37\] + 42: PCREL21B __tls_get_addr + 46: 60 02 98 30 20 00 ld8 r38=\[r38\] + 4c: 08 00 00 50 br\.call\.sptk\.many b0=40 <foo\+0x40>;; + 50: 0b 08 00 40 00 21 \[MMI\] mov r1=r32;; + 51: LTOFF_DTPMOD22 a + 52: DTPREL22 a + 56: 50 02 04 00 48 c0 addl r37=0,r1 + 5c: 04 00 00 90 mov r38=0;; + 60: 1d 28 01 4a 18 10 \[MFB\] ld8 r37=\[r37\] + 62: PCREL21B __tls_get_addr + 66: 00 00 00 02 00 00 nop\.f 0x0 + 6c: 08 00 00 50 br\.call\.sptk\.many b0=60 <foo\+0x60>;; + 70: 0b 08 00 40 00 21 \[MMI\] mov r1=r32;; + 71: LTOFF_DTPMOD22 b + 76: 50 02 04 00 48 c0 addl r37=0,r1 + 7c: 04 00 00 84 mov r38=r0;; + 80: 1d 28 01 4a 18 10 \[MFB\] ld8 r37=\[r37\] + 82: PCREL21B __tls_get_addr + 86: 00 00 00 02 00 00 nop\.f 0x0 + 8c: 08 00 00 50 br\.call\.sptk\.many b0=80 <foo\+0x80>;; + 90: 02 08 00 40 00 21 \[MII\] mov r1=r32 + 92: DTPREL22 b + 96: 20 00 20 00 42 20 mov r2=r8;; + 9c: 04 10 00 90 addl r33=0,r2 + a0: 1d 10 01 04 00 24 \[MFB\] addl r34=0,r2 + a0: DTPREL22 c + a6: 00 00 00 02 00 80 nop\.f 0x0 + ac: 08 00 84 00 br\.ret\.sptk\.many b0;; diff --git a/gas/testsuite/gas/ia64/tls.s b/gas/testsuite/gas/ia64/tls.s new file mode 100644 index 0000000..6a32386 --- /dev/null +++ b/gas/testsuite/gas/ia64/tls.s @@ -0,0 +1,64 @@ + .section ".tdata", "awT", @progbits + .align 16 + .global x#, y#, z#, a#, b#, c# + .protected a#, b#, c# + .type x#,@object + .size x#,4 +x: data4 1 + .type y#,@object + .size y#,4 +y: data4 2 + .type z#,@object + .size z#,4 +z: data4 3 + .align 8 + .type a#,@object + .size a#,8 +a: data8 4 + .type b#,@object + .size b#,8 +b: data8 5 + .type c#,@object + .size c#,1 +c: data1 6 + + .text + .align 16 + .global foo# + .proc foo# +foo: + .prologue + alloc r36 = ar.pfs, 0, 5, 3, 0 + .body + addl loc0 = @ltoff(@tprel(x)), gp;; + ld8 loc0 = [loc0];; + add loc1 = loc0, r13;; + + mov r2 = r13;; + addl loc1 = @tprel(y), r2;; + + mov loc0 = gp + addl out0 = @ltoff(@dtpmod(z)), gp + addl out1 = @ltoff(@dtprel(z)), gp;; + ld8 out0 = [out0] + ld8 out1 = [out1] + br.call.sptk.many b0 = __tls_get_addr;; + mov gp = loc0;; + + addl out0 = @ltoff(@dtpmod(a)), gp + addl out1 = @dtprel(a), r0;; + ld8 out0 = [out0] + br.call.sptk.many b0 = __tls_get_addr;; + mov gp = loc0;; + + addl out0 = @ltoff(@dtpmod(b)), gp + mov out1 = r0;; + ld8 out0 = [out0] + br.call.sptk.many b0 = __tls_get_addr;; + mov gp = loc0 + mov r2 = ret0;; + addl loc1 = @dtprel(b), r2 + addl loc2 = @dtprel(c), r2 + + br.ret.sptk.many b0 + .endp foo# diff --git a/gas/write.c b/gas/write.c index ce3ca8d..4c0b80a 100644 --- a/gas/write.c +++ b/gas/write.c @@ -889,6 +889,13 @@ adjust_reloc_syms (abfd, sec, xxx) symbol_mark_used_in_reloc (fixp->fx_addsy); goto done; } + + /* Never adjust a reloc against TLS local symbol. */ + if (symsec->flags & SEC_THREAD_LOCAL) + { + symbol_mark_used_in_reloc (fixp->fx_addsy); + goto done; + } #endif /* Is there some other reason we can't adjust this one? (E.g., |