diff options
author | Jakub Jelinek <jakub@redhat.com> | 2003-01-24 23:44:45 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2003-01-24 23:44:45 +0000 |
commit | b9734f35729dfe8bba288ff1b6ab2c45fbacc03d (patch) | |
tree | 8239278e95b0efb28bb27b3cd15df6de41c4f5cb /gas | |
parent | c34ee0383a5eb2b49f172da630431191af4886eb (diff) | |
download | gdb-b9734f35729dfe8bba288ff1b6ab2c45fbacc03d.zip gdb-b9734f35729dfe8bba288ff1b6ab2c45fbacc03d.tar.gz gdb-b9734f35729dfe8bba288ff1b6ab2c45fbacc03d.tar.bz2 |
bfd/
* elf32-sparc.c (_bfd_sparc_elf_howto_table): Add TLS relocs.
(elf32_sparc_rev32_howto): New variable.
(sparc_reloc_map): Add TLS relocs.
(elf32_sparc_reloc_type_lookup, elf32_sparc_info_to_howto):
Handle REV32.
(sparc_elf_hix22_reloc, sparc_elf_lox10_reloc, elf32_sparc_mkobject):
New functions.
(struct elf32_sparc_dyn_relocs, struct elf32_sparc_link_hash_entry,
struct elf32_sparc_link_hash_table):
New structures.
(elf32_sparc_tdata, elf32_sparc_local_got_tls_type,
elf32_sparc_hash_table): Define.
(link_hash_newfunc, elf32_sparc_link_hash_table_create,
create_got_section, elf32_sparc_create_dynamic_sections,
elf32_sparc_copy_indirect_symbol, elf32_sparc_tls_transition): New
functions.
(elf32_sparc_check_relocs): Handle TLS relocs. Add dynamic reloc
reference counting.
(elf32_sparc_gc_sweep_hook): Likewise.
(elf32_sparc_adjust_dynamic_symbol): Likewise.
(elf32_sparc_size_dynamic_sections): Likewise.
(elf32_sparc_relocate_section): Likewise.
(allocate_dynrelocs, readonly_dynrelocs, dtpoff_base, tpoff):
New functions.
(elf32_sparc_object_p): Allocate backend private object data.
(bfd_elf32_bfd_link_hash_table_create,
elf_backend_copy_indirect_symbol, bfd_elf32_mkobject,
elf_backend_can_refcount): Define.
(elf_backend_create_dynamic_sections): Define to
elf32_sparc_create_dynamic_sections.
* reloc.c: Add SPARC TLS relocs.
* bfd-in2.h, libbfd.h: Rebuilt.
* elf64-sparc.c (sparc64_elf_howto_table): Add TLS relocs.
(sparc_reloc_map): Likewise.
gas/
* config/tc-sparc.c (sparc_ip): Handle TLS % operators.
(tc_gen_reloc): Handle TLS relocs.
(sparc_cons, cons_fix_new_sparc): Handle %r_tls_dtpoff.
* config/tc-sparc.h (tc_fix_adjustable): Don't adjust TLS
relocs.
* config/obj-elf.c (obj_elf_section_word): Handle tls.
(obj_elf_type): Handle tls_object.
include/
* elf/sparc.h: Add TLS relocs. Move R_SPARC_REV32 to 252.
ld/testsuite/
* ld-sparc/sparc.exp: New.
* ld-sparc/tlsg32.s: New test.
* ld-sparc/tlsg32.sd: Likewise.
* ld-sparc/tlsg64.s: Likewise.
* ld-sparc/tlsg64.sd: Likewise.
* ld-sparc/tlslib.s: Likewise.
* ld-sparc/tlsnopic.s: Likewise.
* ld-sparc/tlspic.s: Likewise.
* ld-sparc/tlssunbin32.dd: Likewise.
* ld-sparc/tlssunbin32.rd: Likewise.
* ld-sparc/tlssunbin32.s: Likewise.
* ld-sparc/tlssunbin32.sd: Likewise.
* ld-sparc/tlssunbin32.td: Likewise.
* ld-sparc/tlssunbin64.dd: Likewise.
* ld-sparc/tlssunbin64.rd: Likewise.
* ld-sparc/tlssunbin64.s: Likewise.
* ld-sparc/tlssunbin64.sd: Likewise.
* ld-sparc/tlssunbin64.td: Likewise.
* ld-sparc/tlssunbinpic32.s: Likewise.
* ld-sparc/tlssunbinpic64.s: Likewise.
* ld-sparc/tlssunnopic32.dd: Likewise.
* ld-sparc/tlssunnopic32.rd: Likewise.
* ld-sparc/tlssunnopic32.s: Likewise.
* ld-sparc/tlssunnopic32.sd: Likewise.
* ld-sparc/tlssunnopic64.dd: Likewise.
* ld-sparc/tlssunnopic64.rd: Likewise.
* ld-sparc/tlssunnopic64.s: Likewise.
* ld-sparc/tlssunnopic64.sd: Likewise.
* ld-sparc/tlssunpic32.dd: Likewise.
* ld-sparc/tlssunpic32.rd: Likewise.
* ld-sparc/tlssunpic32.s: Likewise.
* ld-sparc/tlssunpic32.sd: Likewise.
* ld-sparc/tlssunpic32.td: Likewise.
* ld-sparc/tlssunpic64.dd: Likewise.
* ld-sparc/tlssunpic64.rd: Likewise.
* ld-sparc/tlssunpic64.s: Likewise.
* ld-sparc/tlssunpic64.sd: Likewise.
* ld-sparc/tlssunpic64.td: Likewise.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 5 | ||||
-rw-r--r-- | gas/config/tc-sparc.c | 143 | ||||
-rw-r--r-- | gas/config/tc-sparc.h | 2 |
4 files changed, 156 insertions, 4 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 1f05074..a2f9e07 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2003-01-25 Jakub Jelinek <jakub@redhat.com> + + * config/tc-sparc.c (sparc_ip): Handle TLS % operators. + (tc_gen_reloc): Handle TLS relocs. + (sparc_cons, cons_fix_new_sparc): Handle %r_tls_dtpoff. + * config/tc-sparc.h (tc_fix_adjustable): Don't adjust TLS + relocs. + * config/obj-elf.c (obj_elf_section_word): Handle tls. + (obj_elf_type): Handle tls_object. + 2003-01-24 Martin Schwidefsky <schwidefsky@de.ibm.com> * config/tc-s390.c (s390_tls_suffix): New function. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 7976704..05d668f 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -868,6 +868,8 @@ obj_elf_section_word (str, len) return SHF_ALLOC; if (len == 9 && strncmp (str, "execinstr", 9) == 0) return SHF_EXECINSTR; + if (len == 3 && strncmp (str, "tls", 3) == 0) + return SHF_TLS; #ifdef md_elf_section_word { @@ -1638,6 +1640,9 @@ obj_elf_type (ignore) else if (strcmp (typename, "object") == 0 || strcmp (typename, "STT_OBJECT") == 0) type = BSF_OBJECT; + else if (strcmp (typename, "tls_object") == 0 + || strcmp (typename, "STT_TLS") == 0) + type = BSF_OBJECT | BSF_THREAD_LOCAL; #ifdef md_elf_symbol_type else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1) ; diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index da9252b..49a50e7 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -1806,10 +1806,88 @@ sparc_ip (str, pinsn) break; case '\0': /* End of args. */ - if (*s == '\0') + if (s[0] == ',' && s[1] == '%') { - match = 1; + static const struct tls_ops { + /* The name as it appears in assembler. */ + char *name; + /* strlen (name), precomputed for speed */ + int len; + /* The reloc this pseudo-op translates to. */ + int reloc; + /* 1 if call. */ + int call; + } tls_ops[] = { + { "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 }, + { "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 }, + { "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 }, + { "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 }, + { "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 }, + { "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 }, + { "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 }, + { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 } + }; + const struct tls_ops *o; + char *s1; + int npar = 0; + + for (o = tls_ops; o->name; o++) + if (strncmp (s + 2, o->name, o->len) == 0) + break; + if (o->name == NULL) + break; + + if (s[o->len + 2] != '(') + { + as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name); + return special_case; + } + + if (! o->call && the_insn.reloc != BFD_RELOC_NONE) + { + as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"), + o->name); + return special_case; + } + + if (o->call + && (the_insn.reloc != BFD_RELOC_32_PCREL_S2 + || the_insn.exp.X_add_number != 0 + || the_insn.exp.X_add_symbol + != symbol_find_or_make ("__tls_get_addr"))) + { + as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"), + o->name); + return special_case; + } + + the_insn.reloc = o->reloc; + memset (&the_insn.exp, 0, sizeof (the_insn.exp)); + s += o->len + 3; + + for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) + if (*s1 == '(') + npar++; + else if (*s1 == ')') + { + if (!npar) + break; + npar--; + } + + if (*s1 != ')') + { + as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name); + return special_case; + } + + *s1 = '\0'; + (void) get_expression (s); + *s1 = ')'; + s = s1 + 1; } + if (*s == '\0') + match = 1; break; case '+': @@ -2176,6 +2254,18 @@ sparc_ip (str, pinsn) { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 }, { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 }, { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 }, + { "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 }, + { "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 }, + { "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 }, + { "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 }, + { "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0, + 0 }, + { "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0, + 0 }, + { "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 }, + { "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 }, + { "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 }, + { "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 }, { NULL, 0, 0, 0, 0 } }; const struct ops *o; @@ -2378,6 +2468,13 @@ sparc_ip (str, pinsn) goto error; } + if (the_insn.reloc >= BFD_RELOC_SPARC_TLS_GD_HI22 + && the_insn.reloc <= BFD_RELOC_SPARC_TLS_TPOFF64) + { + error_message = _(": TLS operand can't be a constant"); + goto error; + } + /* Constants that won't fit are checked in md_apply_fix3 and bfd_install_relocation. ??? It would be preferable to install the constants @@ -3305,6 +3402,26 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_SPARC_PLT64: case BFD_RELOC_VTABLE_ENTRY: case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_SPARC_TLS_GD_HI22: + case BFD_RELOC_SPARC_TLS_GD_LO10: + case BFD_RELOC_SPARC_TLS_GD_ADD: + case BFD_RELOC_SPARC_TLS_GD_CALL: + case BFD_RELOC_SPARC_TLS_LDM_HI22: + case BFD_RELOC_SPARC_TLS_LDM_LO10: + case BFD_RELOC_SPARC_TLS_LDM_ADD: + case BFD_RELOC_SPARC_TLS_LDM_CALL: + case BFD_RELOC_SPARC_TLS_LDO_HIX22: + case BFD_RELOC_SPARC_TLS_LDO_LOX10: + case BFD_RELOC_SPARC_TLS_LDO_ADD: + case BFD_RELOC_SPARC_TLS_IE_HI22: + case BFD_RELOC_SPARC_TLS_IE_LO10: + case BFD_RELOC_SPARC_TLS_IE_LD: + case BFD_RELOC_SPARC_TLS_IE_LDX: + case BFD_RELOC_SPARC_TLS_IE_ADD: + case BFD_RELOC_SPARC_TLS_LE_HIX22: + case BFD_RELOC_SPARC_TLS_LE_LOX10: + case BFD_RELOC_SPARC_TLS_DTPOFF32: + case BFD_RELOC_SPARC_TLS_DTPOFF64: code = fixp->fx_r_type; break; default: @@ -3393,7 +3510,9 @@ tc_gen_reloc (section, fixp) && code != BFD_RELOC_SPARC_WDISP22 && code != BFD_RELOC_SPARC_WDISP16 && code != BFD_RELOC_SPARC_WDISP19 - && code != BFD_RELOC_SPARC_WPLT30) + && code != BFD_RELOC_SPARC_WPLT30 + && code != BFD_RELOC_SPARC_TLS_GD_CALL + && code != BFD_RELOC_SPARC_TLS_LDM_CALL) reloc->addend = fixp->fx_addnumber; else if (symbol_section_p (fixp->fx_addsy)) reloc->addend = (section->vma @@ -4196,6 +4315,16 @@ sparc_cons (exp, size) sparc_cons_special_reloc = "plt"; } } + else if (strncmp (input_line_pointer + 3, "tls_dtpoff", 10) == 0) + { + if (size != 4 && size != 8) + as_bad (_("Illegal operands: %%r_tls_dtpoff in %d-byte data field"), size); + else + { + input_line_pointer += 13; + sparc_cons_special_reloc = "tls_dtpoff"; + } + } if (sparc_cons_special_reloc) { int bad = 0; @@ -4329,12 +4458,18 @@ cons_fix_new_sparc (frag, where, nbytes, exp) case 8: r = BFD_RELOC_64_PCREL; break; default: abort (); } - else + else if (*sparc_cons_special_reloc == 'p') switch (nbytes) { case 4: r = BFD_RELOC_SPARC_PLT32; break; case 8: r = BFD_RELOC_SPARC_PLT64; break; } + else + switch (nbytes) + { + case 4: r = BFD_RELOC_SPARC_TLS_DTPOFF32; break; + case 8: r = BFD_RELOC_SPARC_TLS_DTPOFF64; break; + } } else if (sparc_no_align_cons) { diff --git a/gas/config/tc-sparc.h b/gas/config/tc-sparc.h index 1d44506..17b3b6f 100644 --- a/gas/config/tc-sparc.h +++ b/gas/config/tc-sparc.h @@ -102,6 +102,8 @@ extern void sparc_handle_align PARAMS ((struct frag *)); #define tc_fix_adjustable(FIX) \ ((FIX)->fx_r_type != BFD_RELOC_VTABLE_INHERIT \ && (FIX)->fx_r_type != BFD_RELOC_VTABLE_ENTRY \ + && ((FIX)->fx_r_type < BFD_RELOC_SPARC_TLS_GD_HI22 \ + || (FIX)->fx_r_type > BFD_RELOC_SPARC_TLS_TPOFF64) \ && (! sparc_pic_code \ || ((FIX)->fx_r_type != BFD_RELOC_HI22 \ && (FIX)->fx_r_type != BFD_RELOC_LO10 \ |