aix: implement TLS relocation for gas and ld

Add support for TLS in XCOFF. Amongst the things done by this commit:
 - Update XCOFF auxialiary header to match new version and allow TLS
   sections.
 - Add TLS sections (.tdata and .tbss) support in gas and ld.
 - Add support for the TLS relocations in gas and ld.
   Two different types BFD_RELOC are created for PPC and PPC64 as
   the size is a pointer, thus distinct in 32 or 64bit.

The addresses given by ld to .tdata and .tbss is a bit special. In
XCOFF, these addresses are actually offsets from the TLS pointer
computed at runtime. AIX assembly and linker does the same. In
top of that, the .tdata must be before .data (this is mandatory for AIX
loader). Thus, the aix ld script is recomputing "." before .data to restore
its original value. There might be a simpler way, but this one is working.

Optimisation linked to TLS relocations aren't yet implemented.

bfd/
	* 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.
gas/
	* 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.
ld/
	* 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.
include/
	* 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.
This commit is contained in:
Clément Chigot
2021-03-11 11:08:19 +01:00
committed by Alan Modra
parent 4a403be0c1
commit 1b2cb8e2ee
30 changed files with 1037 additions and 131 deletions

View File

@@ -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;