aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2021-03-11 11:08:19 +0100
committerAlan Modra <amodra@gmail.com>2021-03-12 22:47:33 +1030
commit1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416 (patch)
tree9eb377958bf1f1c763cca583f314a8dc9d9249c6 /bfd
parent4a403be0c1b4540e22c8c608ea0bfecbf0f85e51 (diff)
downloadbinutils-1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416.zip
binutils-1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416.tar.gz
binutils-1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog29
-rw-r--r--bfd/bfd-in2.h10
-rw-r--r--bfd/coff-rs6000.c217
-rw-r--r--bfd/coff64-rs6000.c109
-rw-r--r--bfd/coffcode.h67
-rw-r--r--bfd/coffswap.h11
-rw-r--r--bfd/libbfd.h10
-rw-r--r--bfd/libxcoff.h1
-rw-r--r--bfd/reloc.c20
-rw-r--r--bfd/xcofflink.c18
10 files changed, 456 insertions, 36 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