diff options
30 files changed, 1039 insertions, 133 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d955f78..6d61abe 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,34 @@ 2021-03-12 Clément Chigot <clement.chigot@atos.net> + * reloc.c (BFD_RELOC_PPC_TLS_LE, BFD_RELOC_PPC_TLS_IE, + BFD_RELOC_PPC_TLS_M, BFD_RELOC_PPC_TLS_ML, BFD_RELOC_PPC64_TLS_GD, + BFD_RELOC_PPC64_TLS_LD, BFD_RELOC_PPC64_TLS_LE, + BFD_RELOC_PPC64_TLS_IE, BFD_RELOC_PPC64_TLS_M, + BFD_RELOC_PPC64_TLS_ML): New relocations. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + * coff-rs6000.c (xcoff_calculate_relocation): Call + xcoff_reloc_type_tls for TLS relocations. + (xcoff_howto_table): Implement TLS relocations. + (_bfd_xcoff_reloc_type_lookup): Add cases TLS relocations. + (xcoff_reloc_type_tls): New function. + * coff64-rs6000.c (xcoff_calculate_relocation): Likewise. + (xcoff_howto_table): Likewise. + (_bfd_xcoff_reloc_type_lookup): Likewise. + * coffcode.h (sec_to_styp_flags): Handle TLS sections. + (styp_to_sec_flags): Likewise. + (coff_compute_section_file_positions): Avoid file offset + optimisation for .data when the previous section is .tdata. + (coff_write_object_contents): Handle TLS sections. + * coffswap.h (coff_swap_aouthdr_out): Add support for + new fields in aouthdr. + * libxcoff.h (xcoff_reloc_type_tls): Add prototype. + * xcofflink.c (xcoff_link_add_symbols): Handle XMC_UL. + (xcoff_need_ldrel_p): Add cases for TLS relocations. + (xcoff_create_ldrel): Add l_symndx for TLS sections. + +2021-03-12 Clément Chigot <clement.chigot@atos.net> + * reloc.c (BFD_RELOC_PPC_TOC16_HI, BFD_RELOC_PPC_TOC16_LO): New relocations. * bfd-in2.h: Regenerate. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 9bd61b1..54c1c9a 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3003,6 +3003,10 @@ instruction. */ BFD_RELOC_PPC_TLS, BFD_RELOC_PPC_TLSGD, BFD_RELOC_PPC_TLSLD, + BFD_RELOC_PPC_TLSLE, + BFD_RELOC_PPC_TLSIE, + BFD_RELOC_PPC_TLSM, + BFD_RELOC_PPC_TLSML, BFD_RELOC_PPC_DTPMOD, BFD_RELOC_PPC_TPREL16, BFD_RELOC_PPC_TPREL16_LO, @@ -3030,6 +3034,12 @@ instruction. */ BFD_RELOC_PPC_GOT_DTPREL16_LO, BFD_RELOC_PPC_GOT_DTPREL16_HI, BFD_RELOC_PPC_GOT_DTPREL16_HA, + BFD_RELOC_PPC64_TLSGD, + BFD_RELOC_PPC64_TLSLD, + BFD_RELOC_PPC64_TLSLE, + BFD_RELOC_PPC64_TLSIE, + BFD_RELOC_PPC64_TLSM, + BFD_RELOC_PPC64_TLSML, BFD_RELOC_PPC64_TPREL16_DS, BFD_RELOC_PPC64_TPREL16_LO_DS, BFD_RELOC_PPC64_TPREL16_HIGH, diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index b77ff0c..a29cf5b 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -190,12 +190,12 @@ xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] = xcoff_reloc_type_fail, /* (0x1d) */ xcoff_reloc_type_fail, /* (0x1e) */ xcoff_reloc_type_fail, /* (0x1f) */ - xcoff_reloc_type_fail, /* R_TLS (0x20) */ - xcoff_reloc_type_fail, /* R_TLS_IE (0x21) */ - xcoff_reloc_type_fail, /* R_TLS_LD (0x22) */ - xcoff_reloc_type_fail, /* R_TLS_LE (0x23) */ - xcoff_reloc_type_fail, /* R_TLSM (0x24) */ - xcoff_reloc_type_fail, /* R_TLSML (0x25) */ + xcoff_reloc_type_tls, /* R_TLS (0x20) */ + xcoff_reloc_type_tls, /* R_TLS_IE (0x21) */ + xcoff_reloc_type_tls, /* R_TLS_LD (0x22) */ + xcoff_reloc_type_tls, /* R_TLS_LE (0x23) */ + xcoff_reloc_type_tls, /* R_TLSM (0x24) */ + xcoff_reloc_type_tls, /* R_TLSML (0x25) */ xcoff_reloc_type_fail, /* (0x26) */ xcoff_reloc_type_fail, /* (0x27) */ xcoff_reloc_type_fail, /* (0x28) */ @@ -1064,22 +1064,95 @@ reloc_howto_type xcoff_howto_table[] = EMPTY_HOWTO (0x1f), /* 0x20: General-dynamic TLS relocation. */ - EMPTY_HOWTO (R_TLS), + HOWTO (R_TLS, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x21: Initial-exec TLS relocation. */ - EMPTY_HOWTO (R_TLS_IE), + HOWTO (R_TLS_IE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_IE", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x22: Local-dynamic TLS relocation. */ - EMPTY_HOWTO (R_TLS_LD), + HOWTO (R_TLS_LD, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_LD", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x23: Local-exec TLS relocation. */ - EMPTY_HOWTO (R_TLS_LE), + HOWTO (R_TLS_LE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_LE", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x24: TLS relocation. */ - EMPTY_HOWTO(R_TLSM), + HOWTO (R_TLSM, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLSM", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* 0x25: TLS module relocation. */ - EMPTY_HOWTO(R_TLSML), + HOWTO (R_TLSML, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLSM", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ EMPTY_HOWTO(0x26), EMPTY_HOWTO(0x27), @@ -1180,6 +1253,18 @@ _bfd_xcoff_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &xcoff_howto_table[0]; case BFD_RELOC_NONE: return &xcoff_howto_table[0xf]; + case BFD_RELOC_PPC_TLSGD: + return &xcoff_howto_table[0x20]; + case BFD_RELOC_PPC_TLSIE: + return &xcoff_howto_table[0x21]; + case BFD_RELOC_PPC_TLSLD: + return &xcoff_howto_table[0x22]; + case BFD_RELOC_PPC_TLSLE: + return &xcoff_howto_table[0x23]; + case BFD_RELOC_PPC_TLSM: + return &xcoff_howto_table[0x24]; + case BFD_RELOC_PPC_TLSML: + return &xcoff_howto_table[0x25]; default: return NULL; } @@ -3127,6 +3212,88 @@ xcoff_reloc_type_crel (bfd *input_bfd ATTRIBUTE_UNUSED, return TRUE; } +bfd_boolean +xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + struct internal_reloc *rel ATTRIBUTE_UNUSED, + struct internal_syment *sym ATTRIBUTE_UNUSED, + struct reloc_howto_struct *howto, + bfd_vma val, + bfd_vma addend, + bfd_vma *relocation, + bfd_byte *contents ATTRIBUTE_UNUSED) +{ + struct xcoff_link_hash_entry *h; + + if (0 > rel->r_symndx) + return FALSE; + + h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx]; + + /* FIXME: R_TLSML is targeting a internal TOC symbol, which will + make the following checks failing. It should be moved with + R_TLSM bellow once it works. */ + if (howto->type == R_TLSML) + { + *relocation = 0; + return TRUE; + } + + /* FIXME: h is sometimes null, if the TLS symbol is not exported. */ + if (!h) + { + _bfd_error_handler + (_("%pB: TLS relocation at (0x%" BFD_VMA_FMT "x) over " + "internal symbols (C_HIDEXT) not yet possible\n"), + input_bfd, rel->r_vaddr); + return FALSE; + } + + + /* TLS relocations must target a TLS symbol. */ + if (h->smclas != XMC_TL && h->smclas != XMC_UL) + { + _bfd_error_handler + (_("%pB: TLS relocation at (0x%" BFD_VMA_FMT "x) over " + "non-TLS symbol %s (0x%x)\n"), + input_bfd, rel->r_vaddr, h->root.root.string, h->smclas); + return FALSE; + } + + /* Local TLS relocations must target a local symbol, ie + non-imported. */ + if ((rel->r_type == R_TLS_LD || rel->r_type == R_TLS_LE) + && (((h->flags & XCOFF_DEF_REGULAR) == 0 + && (h->flags & XCOFF_DEF_DYNAMIC) != 0) + || (h->flags & XCOFF_IMPORT) != 0)) + { + _bfd_error_handler + (_("%pB: TLS local relocation at (0x%" BFD_VMA_FMT "x) over " + "imported symbol %s\n"), + input_bfd, rel->r_vaddr, h->root.root.string); + return FALSE; + } + + /* R_TLSM and R_TLSML are relocations used by the loader. + The value must be 0. + FIXME: move R_TLSML here. */ + if (howto->type == R_TLSM) + { + *relocation = 0; + return TRUE; + } + + /* Other TLS relocations aims to put offsets from TLS pointers + starting at -0x7c00 (or -0x7800 in XCOFF64). It becomes a + simple R_POS relocation as long as .tdata and .tbss addresses + start at the same value. This is done in aix ld scripts. + TODO: implement optimization when tls size is < 62K. */ + *relocation = val + addend; + + return TRUE; +} + static bfd_boolean xcoff_complain_overflow_dont_func (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val ATTRIBUTE_UNUSED, @@ -3335,13 +3502,6 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd, quite figure out when this is useful. These relocs are not defined by the PowerOpen ABI. - R_TLS - R_TLS_IE - R_TLS_LD - R_TLSLE - - Not yet implemented. - Supported r_type's R_POS: @@ -3437,6 +3597,25 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd, fixed address which may be modified to a relative branch. The PowerOpen ABI does not define this relocation type. + R_TLS: + Thread-local storage relocation using general-dynamic + model. + + R_TLS_IE: + Thread-local storage relocation using initial-exec model. + + R_TLS_LD: + Thread-local storage relocation using local-dynamic model. + + R_TLS_LE: + Thread-local storage relocation using local-exec model. + + R_TLS: + Tread-local storage relocation used by the loader. + + R_TLSM: + Tread-local storage relocation used by the loader. + R_TOCU: Upper TOC relative relocation. The value is the high-order 16 bit of a TOC relative relocation. diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 55a6821..f8e6849 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -212,12 +212,12 @@ xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] = xcoff_reloc_type_fail, /* (0x1d) */ xcoff_reloc_type_fail, /* (0x1e) */ xcoff_reloc_type_fail, /* (0x1f) */ - xcoff_reloc_type_fail, /* R_TLS (0x20) */ - xcoff_reloc_type_fail, /* R_TLS_IE (0x21) */ - xcoff_reloc_type_fail, /* R_TLS_LD (0x22) */ - xcoff_reloc_type_fail, /* R_TLS_LE (0x23) */ - xcoff_reloc_type_fail, /* R_TLSM (0x24) */ - xcoff_reloc_type_fail, /* R_TLSML (0x25) */ + xcoff_reloc_type_tls, /* R_TLS (0x20) */ + xcoff_reloc_type_tls, /* R_TLS_IE (0x21) */ + xcoff_reloc_type_tls, /* R_TLS_LD (0x22) */ + xcoff_reloc_type_tls, /* R_TLS_LE (0x23) */ + xcoff_reloc_type_tls, /* R_TLSM (0x24) */ + xcoff_reloc_type_tls, /* R_TLSML (0x25) */ xcoff_reloc_type_fail, /* (0x26) */ xcoff_reloc_type_fail, /* (0x27) */ xcoff_reloc_type_fail, /* (0x28) */ @@ -1230,24 +1230,95 @@ reloc_howto_type xcoff64_howto_table[] = 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 0x20: General-dynamic TLS relocation. */ - EMPTY_HOWTO (R_TLS), + HOWTO (R_TLS, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x21: Initial-exec TLS relocation. */ - EMPTY_HOWTO (R_TLS_IE), + HOWTO (R_TLS_IE, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_IE", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x22: Local-dynamic TLS relocation. */ - EMPTY_HOWTO (R_TLS_LD), + HOWTO (R_TLS_LD, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_LD", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x23: Local-exec TLS relocation. */ - EMPTY_HOWTO (R_TLS_LE), + HOWTO (R_TLS_LE, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLS_LE", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x24: TLS relocation. */ - EMPTY_HOWTO(R_TLSM), + HOWTO (R_TLSM, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLSM", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ /* 0x25: TLS module relocation. */ - EMPTY_HOWTO(R_TLSML), + HOWTO (R_TLSML, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0, /* special_function */ + "R_TLSM", /* name */ + TRUE, /* partial_inplace */ + MINUS_ONE, /* src_mask */ + MINUS_ONE, /* dst_mask */ + FALSE), /* pcrel_offset */ EMPTY_HOWTO(0x26), EMPTY_HOWTO(0x27), @@ -1355,6 +1426,18 @@ xcoff64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, return &xcoff64_howto_table[0]; case BFD_RELOC_NONE: return &xcoff64_howto_table[0xf]; + case BFD_RELOC_PPC64_TLSGD: + return &xcoff64_howto_table[0x20]; + case BFD_RELOC_PPC64_TLSIE: + return &xcoff64_howto_table[0x21]; + case BFD_RELOC_PPC64_TLSLD: + return &xcoff64_howto_table[0x22]; + case BFD_RELOC_PPC64_TLSLE: + return &xcoff64_howto_table[0x23]; + case BFD_RELOC_PPC64_TLSM: + return &xcoff64_howto_table[0x24]; + case BFD_RELOC_PPC64_TLSML: + return &xcoff64_howto_table[0x25]; default: return NULL; } diff --git a/bfd/coffcode.h b/bfd/coffcode.h index b0ca266..bcd34d4 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -548,6 +548,14 @@ sec_to_styp_flags (const char *sec_name, flagword sec_flags) } #endif #ifdef RS6000COFF_C + else if (!strcmp (sec_name, _TDATA)) + { + styp_flags = STYP_TDATA; + } + else if (!strcmp (sec_name, _TBSS)) + { + styp_flags = STYP_TBSS; + } else if (!strcmp (sec_name, _PAD)) { styp_flags = STYP_PAD; @@ -787,6 +795,22 @@ styp_to_sec_flags (bfd *abfd, else if (styp_flags & STYP_PAD) sec_flags = 0; #ifdef RS6000COFF_C + else if (styp_flags & STYP_TDATA) + { + if (sec_flags & SEC_NEVER_LOAD) + sec_flags |= SEC_DATA | SEC_THREAD_LOCAL | SEC_COFF_SHARED_LIBRARY; + else + sec_flags |= SEC_DATA | SEC_THREAD_LOCAL | SEC_LOAD | SEC_ALLOC; + } + else if (styp_flags & STYP_TBSS) + { +#ifdef BSS_NOLOAD_IS_SHARED_LIBRARY + if (sec_flags & SEC_NEVER_LOAD) + sec_flags |= SEC_ALLOC | SEC_THREAD_LOCAL | SEC_COFF_SHARED_LIBRARY; + else +#endif + sec_flags |= SEC_ALLOC | SEC_THREAD_LOCAL; + } else if (styp_flags & STYP_EXCEPT) sec_flags |= SEC_LOAD; else if (styp_flags & STYP_LOADER) @@ -3168,10 +3192,15 @@ coff_compute_section_file_positions (bfd * abfd) 0 .text 000054cc 10000128 10000128 00000128 2**5 CONTENTS, ALLOC, LOAD, CODE + + Don't perform the above tweak if the previous one is .tdata, + as it will increase the memory allocated for every threads + created and not just improve performances with gdb. */ - if (!strcmp (current->name, _TEXT) - || !strcmp (current->name, _DATA)) + if ((!strcmp (current->name, _TEXT) + || !strcmp (current->name, _DATA)) + && (previous == NULL || strcmp(previous->name, _TDATA))) { bfd_vma align = 4096; bfd_vma sofar_off = sofar % align; @@ -3381,6 +3410,10 @@ coff_write_object_contents (bfd * abfd) asection *text_sec = NULL; asection *data_sec = NULL; asection *bss_sec = NULL; +#ifdef RS6000COFF_C + asection *tdata_sec = NULL; + asection *tbss_sec = NULL; +#endif struct internal_filehdr internal_f; struct internal_aouthdr internal_a; #ifdef COFF_LONG_SECTION_NAMES @@ -3603,6 +3636,13 @@ coff_write_object_contents (bfd * abfd) data_sec = current; else if (!strcmp (current->name, _BSS)) bss_sec = current; +#ifdef RS6000COFF_C + else if (!strcmp (current->name, _TDATA)) + tdata_sec = current; + else if (!strcmp (current->name, _TBSS)) + tbss_sec = current; +#endif + #ifdef COFF_ENCODE_ALIGNMENT COFF_ENCODE_ALIGNMENT(section, current->alignment_power); @@ -4041,6 +4081,29 @@ coff_write_object_contents (bfd * abfd) else internal_a.o_snbss = 0; + if (tdata_sec != NULL) + { + internal_a.o_sntdata = tdata_sec->target_index; + /* TODO: o_flags should be set to RS6K_AOUTHDR_TLS_LE + if there is at least one R_TLS_LE relocations. */ + internal_a.o_flags = 0; +#ifdef XCOFF64 + internal_a.o_x64flags = 0; +#endif + } + else + { + internal_a.o_sntdata = 0; + internal_a.o_flags = 0; +#ifdef XCOFF64 + internal_a.o_x64flags = 0; +#endif + } + if (tbss_sec != NULL) + internal_a.o_sntbss = tbss_sec->target_index; + else + internal_a.o_sntbss = 0; + toc = xcoff_data (abfd)->toc; internal_a.o_toc = toc; internal_a.o_sntoc = xcoff_data (abfd)->sntoc; diff --git a/bfd/coffswap.h b/bfd/coffswap.h index b97b66c..63a0026 100644 --- a/bfd/coffswap.h +++ b/bfd/coffswap.h @@ -695,9 +695,16 @@ coff_swap_aouthdr_out (bfd * abfd, void * in, void * out) H_PUT_32 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack); H_PUT_32 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata); #endif - memset (aouthdr_out->o_resv2, 0, sizeof aouthdr_out->o_resv2); + /* TODO: set o_*psize dynamically */ + H_PUT_8 (abfd, 0, aouthdr_out->o_textpsize); + H_PUT_8 (abfd, 0, aouthdr_out->o_datapsize); + H_PUT_8 (abfd, 0, aouthdr_out->o_stackpsize); + H_PUT_8 (abfd, aouthdr_in->o_flags, aouthdr_out->o_flags); + H_PUT_16 (abfd, aouthdr_in->o_sntdata, aouthdr_out->o_sntdata); + H_PUT_16 (abfd, aouthdr_in->o_sntbss, aouthdr_out->o_sntbss); + H_PUT_32 (abfd, 0, aouthdr_out->o_debugger); #ifdef XCOFF64 - memset (aouthdr_out->o_debugger, 0, sizeof aouthdr_out->o_debugger); + H_PUT_16 (abfd, aouthdr_in->o_x64flags, aouthdr_out->o_x64flags); memset (aouthdr_out->o_resv3, 0, sizeof aouthdr_out->o_resv3); #endif #endif diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 62b6bf8..9cb079e 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1564,6 +1564,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC_TLS", "BFD_RELOC_PPC_TLSGD", "BFD_RELOC_PPC_TLSLD", + "BFD_RELOC_PPC_TLSLE", + "BFD_RELOC_PPC_TLSIE", + "BFD_RELOC_PPC_TLSM", + "BFD_RELOC_PPC_TLSML", "BFD_RELOC_PPC_DTPMOD", "BFD_RELOC_PPC_TPREL16", "BFD_RELOC_PPC_TPREL16_LO", @@ -1591,6 +1595,12 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC_GOT_DTPREL16_LO", "BFD_RELOC_PPC_GOT_DTPREL16_HI", "BFD_RELOC_PPC_GOT_DTPREL16_HA", + "BFD_RELOC_PPC64_TLSGD", + "BFD_RELOC_PPC64_TLSLD", + "BFD_RELOC_PPC64_TLSLE", + "BFD_RELOC_PPC64_TLSIE", + "BFD_RELOC_PPC64_TLSM", + "BFD_RELOC_PPC64_TLSML", "BFD_RELOC_PPC64_TPREL16_DS", "BFD_RELOC_PPC64_TPREL16_LO_DS", "BFD_RELOC_PPC64_TPREL16_HIGH", diff --git a/bfd/libxcoff.h b/bfd/libxcoff.h index 229e47c..bffdee2 100644 --- a/bfd/libxcoff.h +++ b/bfd/libxcoff.h @@ -234,6 +234,7 @@ extern xcoff_reloc_function xcoff_reloc_type_rel; extern xcoff_reloc_function xcoff_reloc_type_toc; extern xcoff_reloc_function xcoff_reloc_type_ba; extern xcoff_reloc_function xcoff_reloc_type_crel; +extern xcoff_reloc_function xcoff_reloc_type_tls; /* Structure to describe dwarf sections. Useful to convert from XCOFF section name to flag and vice-versa. diff --git a/bfd/reloc.c b/bfd/reloc.c index 6864521..6fae177 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2944,6 +2944,14 @@ ENUMX ENUMX BFD_RELOC_PPC_TLSLD ENUMX + BFD_RELOC_PPC_TLSLE +ENUMX + BFD_RELOC_PPC_TLSIE +ENUMX + BFD_RELOC_PPC_TLSM +ENUMX + BFD_RELOC_PPC_TLSML +ENUMX BFD_RELOC_PPC_DTPMOD ENUMX BFD_RELOC_PPC_TPREL16 @@ -2998,6 +3006,18 @@ ENUMX ENUMX BFD_RELOC_PPC_GOT_DTPREL16_HA ENUMX + BFD_RELOC_PPC64_TLSGD +ENUMX + BFD_RELOC_PPC64_TLSLD +ENUMX + BFD_RELOC_PPC64_TLSLE +ENUMX + BFD_RELOC_PPC64_TLSIE +ENUMX + BFD_RELOC_PPC64_TLSM +ENUMX + BFD_RELOC_PPC64_TLSML +ENUMX BFD_RELOC_PPC64_TPREL16_DS ENUMX BFD_RELOC_PPC64_TPREL16_LO_DS diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c index f0d6c8d..f0dd0e9 100644 --- a/bfd/xcofflink.c +++ b/bfd/xcofflink.c @@ -1814,6 +1814,12 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info) csect = bfd_make_section_anyway_with_flags (abfd, ".td", SEC_ALLOC); } + else if (aux.x_csect.x_smclas == XMC_UL) + { + /* This is a thread-local unitialized csect. */ + csect = bfd_make_section_anyway_with_flags (abfd, ".tbss", + SEC_ALLOC | SEC_THREAD_LOCAL); + } else csect = bfd_make_section_anyway_with_flags (abfd, ".bss", SEC_ALLOC); @@ -2697,6 +2703,14 @@ xcoff_need_ldrel_p (struct bfd_link_info *info, struct internal_reloc *rel, return FALSE; } return TRUE; + + case R_TLS: + case R_TLS_LE: + case R_TLS_IE: + case R_TLS_LD: + case R_TLSM: + case R_TLSML: + return TRUE; } } @@ -4060,6 +4074,10 @@ xcoff_create_ldrel (bfd *output_bfd, struct xcoff_final_link_info *flinfo, ldrel.l_symndx = 1; else if (strcmp (secname, ".bss") == 0) ldrel.l_symndx = 2; + else if (strcmp (secname, ".tdata") == 0) + ldrel.l_symndx = -1; + else if (strcmp (secname, ".tbss") == 0) + ldrel.l_symndx = -2; else { _bfd_error_handler diff --git a/gas/ChangeLog b/gas/ChangeLog index 3713209..01161d5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,28 @@ 2021-03-12 Clément Chigot <clement.chigot@atos.net> + * config/tc-ppc.c (ppc_xcoff_text_section, ppc_xcoff_data_section, + (ppc_xcoff_bss_section, ppc_xcoff_tdata_section, + (ppc_xcoff_tbss_section): New variables. + (ppc_text_subsegment, ppc_text_csects, ppc_data_subgments, + (ppc_data_csects): Removed. + (ppc_xcoff_section_is_initialized, ppc_init_xcoff_section, + ppc_xcoff_parse_cons): New functions. + (md_being): Initialize XCOFF sections. + (ppc_xcoff_suffix): Add support for TLS relocations + (fixup_size, md_apply_fix): Add support for new BFD_RELOC. + (ppc_change_csect): Handle XMC_TL, XMC_UL. Correctly, add XMC_BS + to .bss section. Handle new XCOFF section variables. + (ppc_comm): Likewise. + (ppc_toc): Likewise. + (ppc_symbol_new_hook): Likewise. + (ppc_frob_symbol): Likewise. + (ppc_fix_adjustable): Add tbss support. + * config/tc-ppc.h (TC_PARSE_CONS_EXPRESSION): New define. + (ppc_xcoff_parse_cons): Add prototype. + (struct ppc_xcoff_section): New structure. + +2021-03-12 Clément Chigot <clement.chigot@atos.net> + * config/tc-ppc.c (ppc_xcoff_suffix): New function. (MAP, MAP32, MAP64): New macros for XCOFF. (ppc_xcoff_fixup_addis): New function. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5ae9020..0c78b93 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -992,21 +992,41 @@ static bfd_boolean msolaris = SOLARIS_P; /* The RS/6000 assembler uses the .csect pseudo-op to generate code using a bunch of different sections. These assembler sections, - however, are all encompassed within the .text or .data sections of - the final output file. We handle this by using different - subsegments within these main segments. */ - -/* Next subsegment to allocate within the .text segment. */ -static subsegT ppc_text_subsegment = 2; - -/* Linked list of csects in the text section. */ -static symbolS *ppc_text_csects; - -/* Next subsegment to allocate within the .data segment. */ -static subsegT ppc_data_subsegment = 2; + however, are all encompassed within the .text, .data or .bss sections + of the final output file. We handle this by using different + subsegments within these main segments. + .tdata and .tbss sections only have one type of csects for now, + but it's better to follow the same construction like the others. */ + +struct ppc_xcoff_section ppc_xcoff_text_section; +struct ppc_xcoff_section ppc_xcoff_data_section; +struct ppc_xcoff_section ppc_xcoff_bss_section; +struct ppc_xcoff_section ppc_xcoff_tdata_section; +struct ppc_xcoff_section ppc_xcoff_tbss_section; + +/* Return true if the ppc_xcoff_section structure is already + initialized. */ +static bfd_boolean +ppc_xcoff_section_is_initialized (struct ppc_xcoff_section *section) +{ + return section->segment != NULL; +} -/* Linked list of csects in the data section. */ -static symbolS *ppc_data_csects; +/* Initialize a ppc_xcoff_section. + Dummy symbols are used to ensure the position of .text over .data + and .tdata. These symbols won't be output. */ +static void +ppc_init_xcoff_section (struct ppc_xcoff_section *s, segT seg, + bfd_boolean need_dummy) +{ + s->segment = seg; + s->next_subsegment = 2; + if (need_dummy) + { + s->csects = symbol_make ("dummy\001"); + symbol_get_tc (s->csects)->within = s->csects; + } +} /* The current csect. */ static symbolS *ppc_current_csect; @@ -1858,13 +1878,12 @@ md_begin (void) #ifdef OBJ_XCOFF ppc_coff_debug_section = coff_section_from_bfd_index (stdoutput, N_DEBUG); - /* Create dummy symbols to serve as initial csects. This forces the - text csects to precede the data csects. These symbols will not - be output. */ - ppc_text_csects = symbol_make ("dummy\001"); - symbol_get_tc (ppc_text_csects)->within = ppc_text_csects; - ppc_data_csects = symbol_make ("dummy\001"); - symbol_get_tc (ppc_data_csects)->within = ppc_data_csects; + /* Create XCOFF sections with .text in first, as it's creating dummy symbols + to serve as initial csects. This forces the text csects to precede the + data csects. These symbols will not be output. */ + ppc_init_xcoff_section (&ppc_xcoff_text_section, text_section, TRUE); + ppc_init_xcoff_section (&ppc_xcoff_data_section, data_section, TRUE); + ppc_init_xcoff_section (&ppc_xcoff_bss_section, bss_section, FALSE); #endif } @@ -2674,6 +2693,16 @@ ppc_xcoff_suffix (char **str_p) static const struct map_bfd mapping[] = { MAP ("l", BFD_RELOC_PPC_TOC16_LO), MAP ("u", BFD_RELOC_PPC_TOC16_HI), + MAP32 ("ie", BFD_RELOC_PPC_TLSIE), + MAP32 ("ld", BFD_RELOC_PPC_TLSLD), + MAP32 ("le", BFD_RELOC_PPC_TLSLE), + MAP32 ("m", BFD_RELOC_PPC_TLSM), + MAP32 ("ml", BFD_RELOC_PPC_TLSML), + MAP64 ("ie", BFD_RELOC_PPC64_TLSIE), + MAP64 ("ld", BFD_RELOC_PPC64_TLSLD), + MAP64 ("le", BFD_RELOC_PPC64_TLSLE), + MAP64 ("m", BFD_RELOC_PPC64_TLSM), + MAP64 ("ml", BFD_RELOC_PPC64_TLSML), }; if (*str++ != '@') @@ -2726,6 +2755,24 @@ ppc_xcoff_fixup_addis (char *rt_e, char *d_e, char *ra_e) free (save_ra); } +/* Support @ie, etc. on constants emitted via .short, .int etc. */ + +bfd_reloc_code_real_type +ppc_xcoff_parse_cons (expressionS *exp, unsigned int nbytes) +{ + expression (exp); + if (nbytes >= 2 && *input_line_pointer == '@') + return ppc_xcoff_suffix (&input_line_pointer); + + /* There isn't any @ symbol for default TLS relocations (R_TLS). */ + if (exp->X_add_symbol != NULL + && (symbol_get_tc (exp->X_add_symbol)->symbol_class == XMC_TL + || symbol_get_tc (exp->X_add_symbol)->symbol_class == XMC_UL)) + return (ppc_obj64 ? BFD_RELOC_PPC64_TLSGD: BFD_RELOC_PPC_TLSGD); + + return BFD_RELOC_NONE; +} + #endif /* OBJ_XCOFF */ #if defined (OBJ_XCOFF) || defined (OBJ_ELF) @@ -3052,6 +3099,10 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative) case BFD_RELOC_PPC_TLS: case BFD_RELOC_PPC_TLSGD: case BFD_RELOC_PPC_TLSLD: + case BFD_RELOC_PPC_TLSLE: + case BFD_RELOC_PPC_TLSIE: + case BFD_RELOC_PPC_TLSM: + case BFD_RELOC_PPC_TLSML: case BFD_RELOC_PPC_VLE_HA16A: case BFD_RELOC_PPC_VLE_HA16D: case BFD_RELOC_PPC_VLE_HI16A: @@ -3111,6 +3162,12 @@ fixup_size (bfd_reloc_code_real_type reloc, bfd_boolean *pc_relative) case BFD_RELOC_PPC64_TPREL34: case BFD_RELOC_PPC64_DTPREL34: case BFD_RELOC_PPC64_TOC: + case BFD_RELOC_PPC64_TLSGD: + case BFD_RELOC_PPC64_TLSLD: + case BFD_RELOC_PPC64_TLSLE: + case BFD_RELOC_PPC64_TLSIE: + case BFD_RELOC_PPC64_TLSM: + case BFD_RELOC_PPC64_TLSML: size = 8; break; @@ -4205,7 +4262,9 @@ static bfd_boolean ppc_stab_symbol; /* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common symbols in the .bss segment as though they were local common symbols, and uses a different smclas. The native Aix 4.3.3 assembler - aligns .comm and .lcomm to 4 bytes. */ + aligns .comm and .lcomm to 4 bytes. + Symbols having a XMC_UL storage class are uninialized thread-local + data. */ static void ppc_comm (int lcomm) @@ -4220,6 +4279,7 @@ ppc_comm (int lcomm) symbolS *lcomm_sym = NULL; symbolS *sym; char *pfrag; + struct ppc_xcoff_section *section; endc = get_symbol_name (&name); end_name = input_line_pointer; @@ -4312,7 +4372,23 @@ ppc_comm (int lcomm) return; } - record_alignment (bss_section, align); + if (symbol_get_tc (sym)->symbol_class == XMC_UL + || (lcomm && symbol_get_tc (lcomm_sym)->symbol_class == XMC_UL)) + { + section = &ppc_xcoff_tbss_section; + if (!ppc_xcoff_section_is_initialized (section)) + { + ppc_init_xcoff_section (section, + subseg_new (".tbss", 0), FALSE); + bfd_set_section_flags (section->segment, + SEC_ALLOC | SEC_THREAD_LOCAL); + seg_info (section->segment)->bss = 1; + } + } + else + section = &ppc_xcoff_bss_section; + + record_alignment (section->segment, align); if (! lcomm || ! S_IS_DEFINED (lcomm_sym)) @@ -4333,14 +4409,14 @@ ppc_comm (int lcomm) def_size = 0; } - subseg_set (bss_section, 1); + subseg_set (section->segment, 1); frag_align (align, 0, 0); symbol_set_frag (def_sym, frag_now); pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, def_sym, def_size, (char *) NULL); *pfrag = 0; - S_SET_SEGMENT (def_sym, bss_section); + S_SET_SEGMENT (def_sym, section->segment); symbol_get_tc (def_sym)->align = align; } else if (lcomm) @@ -4356,7 +4432,7 @@ ppc_comm (int lcomm) if (lcomm) { /* Make sym an offset from lcomm_sym. */ - S_SET_SEGMENT (sym, bss_section); + S_SET_SEGMENT (sym, section->segment); symbol_set_frag (sym, symbol_get_frag (lcomm_sym)); S_SET_VALUE (sym, symbol_get_frag (lcomm_sym)->fr_offset); symbol_get_frag (lcomm_sym)->fr_offset += size; @@ -4414,7 +4490,7 @@ ppc_change_csect (symbolS *sym, offsetT align) subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg); else { - symbolS **list_ptr; + struct ppc_xcoff_section *section; int after_toc; int hold_chunksize; symbolS *list; @@ -4436,10 +4512,7 @@ ppc_change_csect (symbolS *sym, offsetT align) case XMC_SV: case XMC_TI: case XMC_TB: - S_SET_SEGMENT (sym, text_section); - symbol_get_tc (sym)->subseg = ppc_text_subsegment; - ++ppc_text_subsegment; - list_ptr = &ppc_text_csects; + section = &ppc_xcoff_text_section; is_code = 1; break; case XMC_RW: @@ -4448,21 +4521,48 @@ ppc_change_csect (symbolS *sym, offsetT align) case XMC_TE: case XMC_DS: case XMC_UA: - case XMC_BS: case XMC_UC: + section = &ppc_xcoff_data_section; if (ppc_toc_csect != NULL && (symbol_get_tc (ppc_toc_csect)->subseg + 1 - == ppc_data_subsegment)) + == section->next_subsegment)) after_toc = 1; - S_SET_SEGMENT (sym, data_section); - symbol_get_tc (sym)->subseg = ppc_data_subsegment; - ++ppc_data_subsegment; - list_ptr = &ppc_data_csects; + break; + case XMC_BS: + section = &ppc_xcoff_bss_section; + break; + case XMC_TL: + section = &ppc_xcoff_tdata_section; + /* Create .tdata section if not yet done. */ + if (!ppc_xcoff_section_is_initialized (section)) + { + ppc_init_xcoff_section (section, subseg_new (".tdata", 0), + TRUE); + bfd_set_section_flags (section->segment, SEC_ALLOC + | SEC_LOAD | SEC_RELOC | SEC_DATA + | SEC_THREAD_LOCAL); + } + break; + case XMC_UL: + section = &ppc_xcoff_tbss_section; + /* Create .tbss section if not yet done. */ + if (!ppc_xcoff_section_is_initialized (section)) + { + ppc_init_xcoff_section (section, subseg_new (".tbss", 0), + FALSE); + bfd_set_section_flags (section->segment, SEC_ALLOC | + SEC_THREAD_LOCAL); + seg_info (section->segment)->bss = 1; + } break; default: abort (); } + S_SET_SEGMENT (sym, section->segment); + symbol_get_tc (sym)->subseg = section->next_subsegment; + ++section->next_subsegment; + /* We set the obstack chunk size to a small value before changing subsegments, so that we don't use a lot of memory space for what may be a small section. */ @@ -4490,7 +4590,7 @@ ppc_change_csect (symbolS *sym, offsetT align) symbol_get_tc (sym)->output = 1; symbol_get_tc (sym)->within = sym; - for (list = *list_ptr; + for (list = section->csects; symbol_get_tc (list)->next != (symbolS *) NULL; list = symbol_get_tc (list)->next) ; @@ -5329,8 +5429,8 @@ ppc_toc (int ignore ATTRIBUTE_UNUSED) symbolS *sym; symbolS *list; - subseg = ppc_data_subsegment; - ++ppc_data_subsegment; + subseg = ppc_xcoff_data_section.next_subsegment; + ++ppc_xcoff_data_section.next_subsegment; subseg_new (segment_name (data_section), subseg); ppc_toc_frag = frag_now; @@ -5345,7 +5445,7 @@ ppc_toc (int ignore ATTRIBUTE_UNUSED) ppc_toc_csect = sym; - for (list = ppc_data_csects; + for (list = ppc_xcoff_data_section.csects; symbol_get_tc (list)->next != (symbolS *) NULL; list = symbol_get_tc (list)->next) ; @@ -5711,12 +5811,16 @@ ppc_symbol_new_hook (symbolS *sym) tc->symbol_class = XMC_TC0; else if (strcmp (s, "TE]") == 0) tc->symbol_class = XMC_TE; + else if (strcmp (s, "TL]") == 0) + tc->symbol_class = XMC_TL; break; case 'U': if (strcmp (s, "UA]") == 0) tc->symbol_class = XMC_UA; else if (strcmp (s, "UC]") == 0) tc->symbol_class = XMC_UC; + else if (strcmp (s, "UL]") == 0) + tc->symbol_class = XMC_UL; break; case 'X': if (strcmp (s, "XO]") == 0) @@ -5858,12 +5962,15 @@ ppc_frob_symbol (symbolS *sym) } a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_SD; } - else if (S_GET_SEGMENT (sym) == bss_section) + else if (S_GET_SEGMENT (sym) == bss_section + || S_GET_SEGMENT (sym) == ppc_xcoff_tbss_section.segment) { /* This is a common symbol. */ a->x_csect.x_scnlen.l = symbol_get_frag (sym)->fr_offset; a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM; - if (S_IS_EXTERNAL (sym)) + if (S_GET_SEGMENT (sym) == ppc_xcoff_tbss_section.segment) + symbol_get_tc (sym)->symbol_class = XMC_UL; + else if (S_IS_EXTERNAL (sym)) symbol_get_tc (sym)->symbol_class = XMC_RW; else symbol_get_tc (sym)->symbol_class = XMC_BS; @@ -5917,9 +6024,11 @@ ppc_frob_symbol (symbolS *sym) /* This is a normal symbol definition. x_scnlen is the symbol index of the containing csect. */ if (S_GET_SEGMENT (sym) == text_section) - csect = ppc_text_csects; + csect = ppc_xcoff_text_section.csects; else if (S_GET_SEGMENT (sym) == data_section) - csect = ppc_data_csects; + csect = ppc_xcoff_data_section.csects; + else if (S_GET_SEGMENT (sym) == ppc_xcoff_tdata_section.segment) + csect = ppc_xcoff_tdata_section.csects; else abort (); @@ -6201,6 +6310,7 @@ ppc_fix_adjustable (fixS *fix) && tc->symbol_class != XMC_TC && tc->symbol_class != XMC_TE && symseg != bss_section + && symseg != ppc_xcoff_tbss_section.segment /* Don't adjust if this is a reloc in the toc section. */ && (symseg != data_section || ppc_toc_csect == NULL @@ -7134,6 +7244,37 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) #endif #ifdef OBJ_XCOFF + case BFD_RELOC_PPC_TLSGD: + case BFD_RELOC_PPC_TLSLD: + case BFD_RELOC_PPC_TLSLE: + case BFD_RELOC_PPC_TLSIE: + case BFD_RELOC_PPC_TLSM: + case BFD_RELOC_PPC64_TLSGD: + case BFD_RELOC_PPC64_TLSLD: + case BFD_RELOC_PPC64_TLSLE: + case BFD_RELOC_PPC64_TLSIE: + case BFD_RELOC_PPC64_TLSM: + gas_assert (fixP->fx_addsy != NULL); + S_SET_THREAD_LOCAL (fixP->fx_addsy); + fieldval = 0; + break; + + /* TLSML relocations are targeting a XMC_TC symbol named + "_$TLSML". We can't check earlier because the relocation + can target any symbol name which will be latter .rename + to "_$TLSML". */ + case BFD_RELOC_PPC_TLSML: + case BFD_RELOC_PPC64_TLSML: + gas_assert (fixP->fx_addsy != NULL); + if (strcmp (symbol_get_tc (fixP->fx_addsy)->real_name, "_$TLSML") != 0) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("R_TLSML relocation doesn't target a " + "symbol named \"_$TLSML\". %s"), S_GET_NAME(fixP->fx_addsy)); + } + fieldval = 0; + break; + case BFD_RELOC_NONE: #endif case BFD_RELOC_CTOR: diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index 9e2f174..d38c7d4 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -189,6 +189,23 @@ do { \ extern void ppc_xcoff_end (void); #define md_end ppc_xcoff_end +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + ppc_xcoff_parse_cons (EXP, NBYTES) +extern bfd_reloc_code_real_type ppc_xcoff_parse_cons (expressionS *, + unsigned int); +/* XCOFF format allows only few predefined sections. Gather all + information in a common structure. */ +struct ppc_xcoff_section { + /* Main segment of the section. */ + segT segment; + + /* Next subsegment to allocate within the segment. */ + subsegT next_subsegment; + + /* Linked list of csects in the section. */ + symbolS *csects; +}; + #endif /* OBJ_XCOFF */ #define tc_new_dot_label(sym) ppc_new_dot_label (sym) diff --git a/include/ChangeLog b/include/ChangeLog index c736323..3a40b16 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,5 +1,17 @@ 2021-03-12 Clément Chigot <clement.chigot@atos.net> + * coff/internal.h (struct internal_aouthdr): Add new fields. + * coff/rs6000.h (AOUTHDRÃ): Add new fields. + * coff/rs6k64.h (struct external_filehdr): Likewise. + * coff/xcoff.h (_TDATA), _TBSS): New defines + (RS6K_AOUTHDR_TLS_LE, RS6K_AOUTHDR_RAS, RS6K_AOUTHDR_ALGNTDATA, + RS6K_AOUTHDR_SHR_SYMTAB, RS6K_AOUTHDR_FORK_POLICY, + RS6K_AOUTHDR_FORK_COR): New defines. + (XMC_TU): Removed. + (XMC_UL): New define. + +2021-03-12 Clément Chigot <clement.chigot@atos.net> + * coff/xcoff.h (R_RTB): Remove. (R_TRL): Fix value. diff --git a/include/coff/internal.h b/include/coff/internal.h index 1655181..1b5b45c 100644 --- a/include/coff/internal.h +++ b/include/coff/internal.h @@ -263,8 +263,13 @@ struct internal_aouthdr short o_algndata; /* max alignment for data */ short o_modtype; /* Module type field, 1R,RE,RO */ short o_cputype; /* Encoded CPU type */ - bfd_vma o_maxstack; /* max stack size allowed. */ - bfd_vma o_maxdata; /* max data size allowed. */ + bfd_vma o_maxstack; /* max stack size allowed. */ + bfd_vma o_maxdata; /* max data size allowed. */ + char o_flags; /* Flags and TLS alignment */ + short o_sntdata; /* section number for tdata */ + short o_sntbss; /* section number for tbss */ + short o_x64flags; /* XCOFF64 flags */ + /* ECOFF stuff */ bfd_vma bss_start; /* Base of bss section. */ diff --git a/include/coff/rs6000.h b/include/coff/rs6000.h index 280a81f..ff2de53 100644 --- a/include/coff/rs6000.h +++ b/include/coff/rs6000.h @@ -48,28 +48,34 @@ struct external_filehdr { typedef struct { - unsigned char magic[2]; /* type of file */ - unsigned char vstamp[2]; /* version stamp */ - unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ - unsigned char dsize[4]; /* initialized data " " */ - unsigned char bsize[4]; /* uninitialized data " " */ - unsigned char entry[4]; /* entry pt. */ - unsigned char text_start[4]; /* base of text used for this file */ - unsigned char data_start[4]; /* base of data used for this file */ - unsigned char o_toc[4]; /* address of TOC */ - unsigned char o_snentry[2]; /* section number of entry point */ - unsigned char o_sntext[2]; /* section number of .text section */ - unsigned char o_sndata[2]; /* section number of .data section */ - unsigned char o_sntoc[2]; /* section number of TOC */ - unsigned char o_snloader[2]; /* section number of .loader section */ - unsigned char o_snbss[2]; /* section number of .bss section */ - unsigned char o_algntext[2]; /* .text alignment */ - unsigned char o_algndata[2]; /* .data alignment */ - unsigned char o_modtype[2]; /* module type (??) */ - unsigned char o_cputype[2]; /* cpu type */ - unsigned char o_maxstack[4]; /* max stack size (??) */ - unsigned char o_maxdata[4]; /* max data size (??) */ - unsigned char o_resv2[12]; /* reserved */ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */ + unsigned char dsize[4]; /* initialized data " " */ + unsigned char bsize[4]; /* uninitialized data " " */ + unsigned char entry[4]; /* entry pt. */ + unsigned char text_start[4]; /* base of text used for this file */ + unsigned char data_start[4]; /* base of data used for this file */ + unsigned char o_toc[4]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ + unsigned char o_cputype[2]; /* cpu type */ + unsigned char o_maxstack[4]; /* max stack size (??) */ + unsigned char o_maxdata[4]; /* max data size (??) */ + unsigned char o_debugger[4]; /* reserved */ + unsigned char o_textpsize[1]; /* text page size */ + unsigned char o_datapsize[1]; /* data page size */ + unsigned char o_stackpsize[1]; /* stack page size */ + unsigned char o_flags[1]; /* Flags and TLS alignment */ + unsigned char o_sntdata[2]; /* section number of .tdata section */ + unsigned char o_sntbss[2]; /* section number of .tbss section */ } AOUTHDR; diff --git a/include/coff/rs6k64.h b/include/coff/rs6k64.h index 1faf8e5..53adf4b 100644 --- a/include/coff/rs6k64.h +++ b/include/coff/rs6k64.h @@ -39,32 +39,38 @@ struct external_filehdr /********************** AOUT "OPTIONAL HEADER" **********************/ -typedef struct +typedef struct { - unsigned char magic[2]; /* type of file */ - unsigned char vstamp[2]; /* version stamp */ - unsigned char o_debugger[4]; /* reserved */ - unsigned char text_start[8]; /* base of text used for this file */ - unsigned char data_start[8]; /* base of data used for this file */ - unsigned char o_toc[8]; /* address of TOC */ - unsigned char o_snentry[2]; /* section number of entry point */ - unsigned char o_sntext[2]; /* section number of .text section */ - unsigned char o_sndata[2]; /* section number of .data section */ - unsigned char o_sntoc[2]; /* section number of TOC */ - unsigned char o_snloader[2]; /* section number of .loader section */ - unsigned char o_snbss[2]; /* section number of .bss section */ - unsigned char o_algntext[2]; /* .text alignment */ - unsigned char o_algndata[2]; /* .data alignment */ - unsigned char o_modtype[2]; /* module type (??) */ + unsigned char magic[2]; /* type of file */ + unsigned char vstamp[2]; /* version stamp */ + unsigned char o_debugger[4]; /* reserved */ + unsigned char text_start[8]; /* base of text used for this file */ + unsigned char data_start[8]; /* base of data used for this file */ + unsigned char o_toc[8]; /* address of TOC */ + unsigned char o_snentry[2]; /* section number of entry point */ + unsigned char o_sntext[2]; /* section number of .text section */ + unsigned char o_sndata[2]; /* section number of .data section */ + unsigned char o_sntoc[2]; /* section number of TOC */ + unsigned char o_snloader[2]; /* section number of .loader section */ + unsigned char o_snbss[2]; /* section number of .bss section */ + unsigned char o_algntext[2]; /* .text alignment */ + unsigned char o_algndata[2]; /* .data alignment */ + unsigned char o_modtype[2]; /* module type (??) */ unsigned char o_cputype[2]; /* cpu type */ - unsigned char o_resv2[4]; /* reserved */ - unsigned char tsize[8]; /* text size bytes, padded to FW bdry */ - unsigned char dsize[8]; /* initialized data " " */ - unsigned char bsize[8]; /* uninitialized data " " */ - unsigned char entry[8]; /* entry pt. */ - unsigned char o_maxstack[8]; /* max stack size (??) */ - unsigned char o_maxdata[8]; /* max data size (??) */ - unsigned char o_resv3[16]; /* reserved */ + unsigned char o_textpsize[1]; /* text page size */ + unsigned char o_datapsize[1]; /* data page size */ + unsigned char o_stackpsize[1]; /* stack page size */ + unsigned char o_flags[1]; /* Flags and TLS alignment */ + unsigned char tsize[8]; /* text size bytes, padded to FW bdry */ + unsigned char dsize[8]; /* initialized data " " */ + unsigned char bsize[8]; /* uninitialized data " " */ + unsigned char entry[8]; /* entry pt. */ + unsigned char o_maxstack[8]; /* max stack size (??) */ + unsigned char o_maxdata[8]; /* max data size (??) */ + unsigned char o_sntdata[2]; /* section number of .tdata section */ + unsigned char o_sntbss[2]; /* section number of .tbss section */ + unsigned char o_x64flags[2]; /* XCOFF64 flags */ + unsigned char o_resv3[10]; /* reserved */ } AOUTHDR; diff --git a/include/coff/xcoff.h b/include/coff/xcoff.h index 36651d4..05e9160 100644 --- a/include/coff/xcoff.h +++ b/include/coff/xcoff.h @@ -46,6 +46,8 @@ #define _TEXT ".text" #define _DATA ".data" #define _BSS ".bss" +#define _TDATA ".tdata" +#define _TBSS ".tbss" #define _PAD ".pad" #define _LOADER ".loader" #define _EXCEPT ".except" @@ -93,8 +95,19 @@ #define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */ #define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */ -/* XCOFF relocation types. - The relocations are described in the function +/* Flags for aouthdr o_flags */ +#define RS6K_AOUTHDR_TLS_LE 0x80 /* TLS local-exec code was generated */ +#define RS6K_AOUTHDR_RAS 0x40 /* kernel module is key & recovery safe */ +#define RS6K_AOUTHDR_ALGNTDATA 0xf /* TLS alignment */ + +/* Flags for aouthdr o_x64flags */ +#define RS6K_AOUTHDR_SHR_SYMTAB 0x8000 +#define RS6K_AOUTHDR_FORK_POLICY 0x4000 +#define RS6K_AOUTHDR_FORK_COR 0x2000 + + +/* XCOFF relocation types. + The relocations are described in the function xcoff[64]_ppc_relocate_section in coff64-rs6000.c and coff-rs6000.c */ #define R_POS (0x00) @@ -171,7 +184,7 @@ #define XMC_SV3264 18 /* Read-only 32 or 64 bit supervisor call */ /* 19 ??? */ #define XMC_TL 20 /* Read-write initialized TLS data */ -#define XMC_TU 21 /* Read-write uninitialized TLS data */ +#define XMC_UL 21 /* Read-write uninitialized TLS data */ #define XMC_TE 22 /* Same as XMC_TC but mapped after it */ /* The ldhdr structure. This appears at the start of the .loader diff --git a/ld/ChangeLog b/ld/ChangeLog index 024ea0d..35c5e20 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,20 @@ 2021-03-12 Clément Chigot <clement.chigot@atos.net> + * emultempl/aix.em: Ensure .tdata section is removed + if empty, even with -r flag. + * scripttempl/aix.sc: Handle TLS sections. + * testsuite/ld-powerpc/aix52.exp: Add new tests. + * testsuite/ld-powerpc/aix-tls-reloc-32.d: New test. + * testsuite/ld-powerpc/aix-tls-reloc-64.d: New test. + * testsuite/ld-powerpc/aix-tls-reloc.ex: New test. + * testsuite/ld-powerpc/aix-tls-reloc.s: New test. + * testsuite/ld-powerpc/aix-tls-section-32.d: New test. + * testsuite/ld-powerpc/aix-tls-section-64.d: New test. + * testsuite/ld-powerpc/aix-tls-section.ex: New test. + * testsuite/ld-powerpc/aix-tls-section.s: New test. + +2021-03-12 Clément Chigot <clement.chigot@atos.net> + * scripttempl/aix.sc: Add .te to .data section. * testsuite/ld-powerpc/aix52.exp: Add test structure for AIX7+. Add aix-largetoc-1 test. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index d578b6e..e098f2a 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -969,6 +969,44 @@ gld${EMULATION_NAME}_before_allocation (void) sec->flags |= SEC_KEEP; } + /* Make sure .tdata is removed if empty, even with -r flag. + .tdata is always being generated because its size is needed + to cumpute .data address. */ + if (bfd_link_relocatable (&link_info)) + { + static const char *const thread_sections[] = { + ".tdata", + ".tbss" + }; + + /* Run lang_size_sections (if not already done). */ + if (expld.phase != lang_mark_phase_enum) + { + expld.phase = lang_mark_phase_enum; + expld.dataseg.phase = exp_seg_none; + one_lang_size_sections_pass (NULL, FALSE); + lang_reset_memory_regions (); + } + + for (i = 0; i < ARRAY_SIZE (thread_sections); i++) + { + asection *sec; + + sec = bfd_get_section_by_name (link_info.output_bfd, + thread_sections[i]); + + if (sec != NULL && sec->rawsize == 0 + && (sec->flags & SEC_KEEP) == 0 + && !bfd_section_removed_from_list (link_info.output_bfd, + sec)) + { + sec->flags |= SEC_EXCLUDE; + bfd_section_list_remove (link_info.output_bfd, sec); + link_info.output_bfd->section_count--; + } + } + } + before_allocation_default (); } diff --git a/ld/scripttempl/aix.sc b/ld/scripttempl/aix.sc index aa129d9..3e4d7c0 100644 --- a/ld/scripttempl/aix.sc +++ b/ld/scripttempl/aix.sc @@ -37,7 +37,35 @@ SECTIONS ${RELOCATING+PROVIDE (_etext = .);} } - . = ALIGN (ALIGN (0x10000000) + (. & 0xfff), 32); + /* .tdata and .tbss addresses are representing the offset from + the TLS pointer. It starts at -0x7800 for 64bit and -0x7c00 + for 32bit. + TODO: 32bit should have -0x7c00 but it works like this for + now. + The other particularity is that they must be before .data + sections. But .data must be aligned correctly as if the + addresses were contiguous. This means that the correct + address must be restored, taking into account: the size of + .text, its alignment 2^5, the size of .tdata and its + aligment 2^4. */ + .tdata -0x7800 : { + *(.tdata) + *(.tl) + } + + .tbss : { + *(.tbss) + *(.ul) + } + + . = ${RELOCATING+(ALIGN (0x10000000 + SIZEOF_HEADERS, 32)) + }SIZEOF(.text); + . = ALIGN (.,32); + . = . + SIZEOF(.tdata); + . = ALIGN (.,16); + + /* .data starting address must be in a different segment than + the .text addresses. Thus, 0x10000000 is added. */ + . = ALIGN (0x10000000) + (. & 0xfff); .data . : { ${RELOCATING+PROVIDE (_data = .);} *(.data) diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-32.d b/ld/testsuite/ld-powerpc/aix-tls-reloc-32.d new file mode 100644 index 0000000..5103de5 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-reloc-32.d @@ -0,0 +1,35 @@ +#source: aix-tls-reloc.s +#as: -a32 +#ld: -b32 -shared -bE:aix-tls-reloc.ex +#objdump: -dr +#target: [is_xcoff_format] + +.* + +Disassembly of section \.text: + +.* <\.foo>: +.*: 80 82 00 00 l r4,0\(r2\) +.*: R_TOC gd-.* +.*: 80 62 00 04 l r3,4\(r2\) +.*: R_TOC .gd-.* +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __tls_get_addr +.*: 80 62 00 0c l r3,12\(r2\) +.*: R_TOC _\$TLSML-.* +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __tls_get_mod +.*: 80 82 00 08 l r4,8\(r2\) +.*: R_TOC ld-.* +.*: 7c a3 22 14 cax r5,r3,r4 +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __get_tpointer +.*: 80 82 00 10 l r4,16\(r2\) +.*: R_TOC ie-.* +.*: 7c a3 22 14 cax r5,r3,r4 +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __get_tpointer +.*: 80 82 00 14 l r4,20\(r2\) +.*: R_TOC le-.* +.*: 7c a3 22 14 cax r5,r3,r4 +.* diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc-64.d b/ld/testsuite/ld-powerpc/aix-tls-reloc-64.d new file mode 100644 index 0000000..71f6302 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-reloc-64.d @@ -0,0 +1,31 @@ +#source: aix-tls-reloc.s +#as: -a32 +#ld: -b32 -shared -bE:aix-tls-reloc.ex +#objdump: -dr +#target: [is_xcoff_format] + +.* + +Disassembly of section \.text: + +.* <\.foo>: +.*: e8 82 00 00 ld r4,0\(r2\) +.*: R_TOC gd-.* +.*: e8 62 00 08 ld r3,8\(r2\) +.*: R_TOC .gd-.* +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __tls_get_addr +.*: e8 62 00 18 ld r3,24\(r2\) +.*: R_TOC _\$TLSML-.* +.*: 48 00 00 03 bla 0 <\.foo-.*> +.*: R_BA_26 __tls_get_mod +.*: 80 82 00 10 lwz r4,16\(r2\) +.*: R_TOC ld-.* +.*: 7c a3 22 14 add r5,r3,r4 +.*: e8 82 00 20 ld r4,32\(r2\) +.*: R_TOC ie-.* +.*: 7c a4 6a 14 add r5,r4,r13 +.*: e8 82 00 28 ld r4,40\(r2\) +.*: R_TOC le-.* +.*: 7c a3 6a 14 add r5,r3,r13 +.* diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc.ex b/ld/testsuite/ld-powerpc/aix-tls-reloc.ex new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-reloc.ex @@ -0,0 +1 @@ +foo diff --git a/ld/testsuite/ld-powerpc/aix-tls-reloc.s b/ld/testsuite/ld-powerpc/aix-tls-reloc.s new file mode 100644 index 0000000..62ef73c --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-reloc.s @@ -0,0 +1,65 @@ + .globl bar[TL] + .csect bar[TL] + .long 1 + + .toc + .tc gd[TC],bar[TL] + .tc .gd[TC],bar[TL]@m + .tc ld[TC],bar[TL]@ld + .tc mh[TC],mh[TC]@ml + .tc ie[TC],bar[TL]@ie + .tc le[TC],bar[TL]@le + + .globl foo + .globl .foo + .csect foo[DS],3 +foo: + .if size == 32 + .long .foo, TOC[tc0], 0 + .else + .llong .foo, TOC[tc0], 0 + .endif + + .csect foo[PR] +.foo: + #GD + .if size == 32 + lwz 4, gd[TC](2) + lwz 3, .gd[TC](2) + .else + ld 4, gd[TC](2) + ld 3, .gd[TC](2) + .endif + bla __tls_get_addr + + #LD + .if size == 32 + lwz 3, mh[TC](2) + .else + ld 3, mh[TC](2) + .endif + bla __tls_get_mod + lwz 4, ld[TC](2) + add 5,3,4 + + #IE + .if size == 32 + bla __get_tpointer + lwz 4, ie[TC](2) + add 5,3,4 + .else + ld 4, ie[TC](2) + add 5,4,13 + .endif + + #LE + .if size == 32 + bla __get_tpointer + lwz 4, le[TC](2) + add 5,3,4 + .else + ld 4, le[TC](2) + add 5,3,13 + .endif + +.rename mh[TC], "_$TLSML" # Symbol for the module handle diff --git a/ld/testsuite/ld-powerpc/aix-tls-section-32.d b/ld/testsuite/ld-powerpc/aix-tls-section-32.d new file mode 100644 index 0000000..16b9686 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-section-32.d @@ -0,0 +1,15 @@ +#source: aix-tls-section.s +#as: -a32 +#ld: -b32 -shared -bE:aix-tls-section.ex +#objdump: -hw +#target: [is_xcoff_format] + +.* + +Sections: +.* + 0 \.text .* .* .* .* .* ALLOC, LOAD, CODE + 1 \.tdata 00000008 ffff8800 ffff8800 .* .* CONTENTS, ALLOC, LOAD, DATA, THREAD_LOCAL + 2 \.tbss 00000008 ffff8808 ffff8808 .* .* ALLOC, THREAD_LOCAL + 3 \.data .* .* .* .* .* ALLOC, LOAD, DATA +#... diff --git a/ld/testsuite/ld-powerpc/aix-tls-section-64.d b/ld/testsuite/ld-powerpc/aix-tls-section-64.d new file mode 100644 index 0000000..dceeaaf --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-section-64.d @@ -0,0 +1,15 @@ +#source: aix-tls-section.s +#as: -a64 +#ld: -b64 -shared -bE:aix-tls-section.ex +#objdump: -hw +#target: [is_xcoff_format] + +.* + +Sections\: +.* + 0 \.text .* .* .* .* .* ALLOC, LOAD, CODE + 1 \.tdata 00000008 ffffffffffff8800 ffffffffffff8800 .* .* CONTENTS, ALLOC, LOAD, DATA, THREAD_LOCAL + 2 \.tbss 00000008 ffffffffffff8808 ffffffffffff8808 .* .* ALLOC, THREAD_LOCAL + 3 \.data .* .* .* .* .* ALLOC, LOAD, DATA +#... diff --git a/ld/testsuite/ld-powerpc/aix-tls-section.ex b/ld/testsuite/ld-powerpc/aix-tls-section.ex new file mode 100644 index 0000000..3bd1f0e --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-section.ex @@ -0,0 +1,2 @@ +foo +bar diff --git a/ld/testsuite/ld-powerpc/aix-tls-section.s b/ld/testsuite/ld-powerpc/aix-tls-section.s new file mode 100644 index 0000000..30c328f --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-tls-section.s @@ -0,0 +1,8 @@ + /* .tbss */ + .comm foo[UL],8 + .lcomm foo2_l,8,foo2[UL] + + /* .tdata */ + .globl bar[TL] + .csect bar[TL] + .long 1 diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp index 3dfbae0..0e68b6a 100644 --- a/ld/testsuite/ld-powerpc/aix52.exp +++ b/ld/testsuite/ld-powerpc/aix52.exp @@ -275,6 +275,16 @@ set aix7tests { "" {aix-largetoc-1.s} {{objdump -dr aix-largetoc-1-SIZE.d}} "aix-largetoc-1.so"} + + {"TLS relocations" "-shared -bE:aix-tls-reloc.ex" + "" {aix-tls-reloc.s} + {{objdump -dr aix-tls-reloc-SIZE.d}} + "aix-tls-reloc.so"} + + {"TLS section" "-shared -bE:aix-tls-section.ex" + "" {aix-tls-section.s} + {{objdump -hw aix-tls-section-SIZE.d}} + "aix-tls-section.so"} } foreach test $aix7tests { |