aboutsummaryrefslogtreecommitdiff
path: root/ld
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 /ld
parent4a403be0c1b4540e22c8c608ea0bfecbf0f85e51 (diff)
downloadgdb-1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416.zip
gdb-1b2cb8e2ee578e68389c9201bfdfa8cd67c3b416.tar.gz
gdb-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 'ld')
-rw-r--r--ld/ChangeLog15
-rw-r--r--ld/emultempl/aix.em38
-rw-r--r--ld/scripttempl/aix.sc30
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-reloc-32.d35
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-reloc-64.d31
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-reloc.ex1
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-reloc.s65
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-section-32.d15
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-section-64.d15
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-section.ex2
-rw-r--r--ld/testsuite/ld-powerpc/aix-tls-section.s8
-rw-r--r--ld/testsuite/ld-powerpc/aix52.exp10
12 files changed, 264 insertions, 1 deletions
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 {