aboutsummaryrefslogtreecommitdiff
path: root/gas
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 /gas
parentbaf0cc5e964e70eccb5348c5e9097971d0e184d2 (diff)
downloadbinutils-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/ChangeLog42
-rw-r--r--gas/config/obj-elf.c52
-rw-r--r--gas/config/tc-alpha.c5
-rw-r--r--gas/config/tc-i386.c38
-rw-r--r--gas/config/tc-ia64.c115
-rw-r--r--gas/config/tc-ppc.c2
-rw-r--r--gas/config/tc-sparc.c1
-rw-r--r--gas/testsuite/gas/i386/i386.exp3
-rw-r--r--gas/testsuite/gas/i386/tlsd.d33
-rw-r--r--gas/testsuite/gas/i386/tlsd.s42
-rw-r--r--gas/testsuite/gas/i386/tlsnopic.d31
-rw-r--r--gas/testsuite/gas/i386/tlsnopic.s45
-rw-r--r--gas/testsuite/gas/i386/tlspic.d23
-rw-r--r--gas/testsuite/gas/i386/tlspic.s27
-rw-r--r--gas/testsuite/gas/ia64/ia64.exp1
-rw-r--r--gas/testsuite/gas/ia64/tls.d53
-rw-r--r--gas/testsuite/gas/ia64/tls.s64
-rw-r--r--gas/write.c7
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.,