From 1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= Date: Thu, 11 Mar 2021 11:08:19 +0100 Subject: aix: implement TLS relocation for gas and ld MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- include/ChangeLog | 12 +++++++++++ include/coff/internal.h | 9 +++++++-- include/coff/rs6000.h | 50 +++++++++++++++++++++++++-------------------- include/coff/rs6k64.h | 54 +++++++++++++++++++++++++++---------------------- include/coff/xcoff.h | 19 ++++++++++++++--- 5 files changed, 93 insertions(+), 51 deletions(-) (limited to 'include') 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 + * 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 + * 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 -- cgit v1.1