diff options
Diffstat (limited to 'gas/config')
-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 |
6 files changed, 189 insertions, 24 deletions
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) |