Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v1 3/3] Add test cases for all TLS support in AIX
@ 2026-09-03  8:54 Aditya Vidyadhar Kamath
  2026-09-03  9:07 ` Aditya Kamath
  0 siblings, 1 reply; 2+ messages in thread
From: Aditya Vidyadhar Kamath @ 2026-09-03  8:54 UTC (permalink / raw)
  To: ulrich.weigand, simon.marchi, tom
  Cc: gdb-patches, Aditya.Kamath1, sangamesh.swamy, Aditya Vidyadhar Kamath

From: Aditya Vidyadhar Kamath <aditya.kamath1@ibm.com>

This patch adds test cases to all the 4 types of TLS variables in a shared library
on AIX.

which is
1: local-exec
2: initial-exec
3: global-dynamic
4: local-dynamic

le_var1 and le_var2 are local-exec in the main executable.
gd_var1 and gd_var2 are initial exec if the compiler chose R_TLS_IE via compiler options otherwise is local dynamic.
gd_var1, gd_var2 are local dynamic.
ld_only_var is local dynamic since it is used in the shared library only and not in main executable.
[See: powerpc-aix-tls-main.c]

This test prints all of them and checks if we can access them in AIX.

When we run this on AIX we get,
gmake check RUNTESTFLAGS='gdb.threads/thread_events.exp  CC_FOR_TARGET="/opt/freeware/bin/gcc" CXX_FOR_TARGET="/opt/freeware/bin/g++" CXXFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64" CFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64"'

Running target unix
Using /opt/freeware/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /opt/freeware/share/dejagnu/config/unix.exp as generic interface file for target.
Using /current_gdb/binutils-gdb/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
Running /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_events.exp ...

                === gdb Summary ===

# of expected passes            11
/current_gdb/binutils-gdb/gdb/gdb version  19.0.50.20260819-git -nw -nx -q -iex "set height 0" -iex "set width 0" -data-directory /current_gdb/binutils-gdb/gdb/data-directory -iex "set interactive-mode on" 


---
 gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c  |  66 ++++++++
 gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c |  69 ++++++++
 gdb/testsuite/gdb.arch/powerpc-aix-tls.exp    | 147 ++++++++++++++++++
 3 files changed, 282 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls.exp

diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c b/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
new file mode 100644
index 00000000000..3f34d2e570b
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Global-dynamic TLS variables exported from this shared library.
+   The main executable accesses these (R_TLS + R_TLSM relocs), which means
+   the TOC slots will be emitted in the main executable's .loader section.
+   Within this library the compiler may use local-dynamic or initial-exec
+   depending on flags, but the main exe always uses global-dynamic for
+   cross-module symbols.  */
+
+/* gd_var1 and gd_var2 are exported TLS variables that the main executable
+   imports via global-dynamic.  They are also accessed here via local-dynamic
+   so that R_TLS_LD + R_TLSML relocs appear in this library's .loader.  */
+__thread int gd_var1 = 10;
+__thread int gd_var2 = 20;
+
+/* ld_only_var is a local-dynamic variable that is ONLY accessed from within
+   this shared library (never referenced in the main executable).  This
+   exercises the access-dependency limitation: GDB must be able to resolve it
+   even though there is no R_TLS/R_TLSM slot for it in the main exe's loader
+   section.  */
+__thread int ld_only_var = 30;
+
+/* Access gd_var1, gd_var2 and ld_only_var from within the library so that
+   the compiler emits R_TLS_LD / R_TLSML relocs into this .so's .loader
+   section.  Force local-dynamic model explicitly.  */
+int
+lib_set_tls_vars (int a, int b, int c)
+{
+  gd_var1    = a;
+  gd_var2    = b;
+  ld_only_var = c;
+  return gd_var1 + gd_var2 + ld_only_var;
+}
+
+int
+lib_get_gd_var1 (void)
+{
+  return gd_var1;
+}
+
+int
+lib_get_gd_var2 (void)
+{
+  return gd_var2;
+}
+
+int
+lib_get_ld_only (void)
+{
+  return ld_only_var;
+}
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c b/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
new file mode 100644
index 00000000000..1a8a5561e71
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* This test exercises all four XCOFF TLS models on 64-bit AIX:
+   - local-exec  (variables in the main executable, TP-relative offset)
+   - initial-exec (R_TLS_IE  in which the compiler uses this for extern __thread
+                   variables in the main exe when linked without -brtl)
+   - global-dynamic (R_TLS + R_TLSM in which cross-module access to variables
+                     in a shared library)
+   - local-dynamic  (R_TLS_LD + R_TLSML The within-module access inside the
+                     shared library; also exercises the access-dependency
+                     case for ld_only_var which is never accessed here)  */
+
+/* local-exec TLS variables: defined in the main executable.  */
+__thread int le_var1 = 100;
+__thread int le_var2 = 200;
+
+/* Declaration of TLS variables from the shared library.
+   The compiler uses global-dynamic model for these cross-module accesses,
+   emitting R_TLS + R_TLSM pairs in the .loader section.  */
+extern __thread int gd_var1;
+extern __thread int gd_var2;
+/* ld_only_var is intentionally NOT declared here we only look it up via
+   GDB's symbol lookup to exercise the access-dependency fallback.  This
+   is an edge case.  */ 
+
+extern int lib_set_tls_vars (int, int, int);
+extern int lib_get_gd_var1 (void);
+extern int lib_get_gd_var2 (void);
+extern int lib_get_ld_only (void);
+
+volatile int sink;
+
+int
+main (void)
+{
+  /* Set local-exec variables to known values.  */
+  le_var1 = 11;
+  le_var2 = 22;
+
+  /* Access cross-module globals -- forces R_TLS + R_TLSM into the main
+     executable's .loader section for gd_var1 and gd_var2.  */
+  gd_var1 = 33;
+  gd_var2 = 44;
+
+  /* Call into the library so the library-side TLS is initialised.  This
+     also exercises the local-dynamic model inside the shared library (the
+     compiler will use R_TLS_LD for within-module accesses to gd_var1,
+     gd_var2, and ld_only_var inside the .so).  */
+  lib_set_tls_vars (33, 44, 55);
+
+  sink = le_var1 + le_var2 + gd_var1 + gd_var2; /* breakpoint here */
+
+  return sink;
+}
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp b/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp
new file mode 100644
index 00000000000..824884dffc9
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp
@@ -0,0 +1,147 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test GDB TLS variable access on 64-bit AIX (XCOFF) covering all four
+# TLS models:
+#
+#   1. local-exec [le_var1, le_var2 variables defined in the main executable]
+#      GDB reads the XCOFF symbol value directly as a TP-relative offset.
+#
+#   2. initial-exec [gd_var1, gd_var2 accessed from the main executable]
+#      If the compiler chose R_TLS_IE for cross-module accesses
+#      GDB reads the TOC slot and adds it to TP.
+#
+#   3. global-dynamic [gd_var1, gd_var2 via R_TLS + R_TLSM]
+#      GDB reads the module-id from the R_TLSM slot, looks up
+#      thread_vector[mod_id] to find the TLS block base, and adds the per-variable
+#      offset from the R_TLS slot.
+#
+#   4. local-dynamic [ld_only_var which is only accessed from inside the .so of this test case]
+#      GDB reads the module-id from the R_TLSML slot in the .so, looks
+#      up thread_vector[mod_id], and adds the within-module offset from R_TLS_LD.
+#      ld_only_var is never referenced in the main executable, so there
+#      is no per-variable TOC slot for it in the main executbale; So GDB must use
+#      the access-dependency fallback path which is rs6000_aix_compute_tls_address ().
+
+require {istarget "powerpc*-*-aix*"}
+
+standard_testfile powerpc-aix-tls-main.c
+set srcfile_lib powerpc-aix-tls-lib.c
+set binfile_lib [standard_output_file powerpc-aix-tls-lib.so]
+
+# Build shared library
+# On AIX with GCC the standard gdb_compile_shlib helper appends
+# "-Wl,-soname,<name>" which the AIX ld interprets as an input file
+# (COFF mismatch error).  Instead we do the two-step compile+link
+# manually. First compile the .c to a -fPIC .o, then link it to a .so
+# with -shared -Wl,-bexpall -lpthread (needed for __tls_get_addr).
+set lib_obj [standard_output_file powerpc-aix-tls-lib.c.o]
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile_lib}" \
+		  "${lib_obj}" \
+		  object \
+		  {debug additional_flags=-fPIC}] != "" } {
+    unsupported "failed to compile shared library object"
+    return
+}
+if { [gdb_compile "${lib_obj}" \
+		  "${binfile_lib}" \
+		  executable \
+		  {debug additional_flags=-shared \
+		         additional_flags=-Wl,-bexpall \
+		         additional_flags=-lpthread}] != "" } {
+    unsupported "failed to link shared library"
+    return
+}
+
+# Build main executable linked against the shared library
+# Pass the .so directly to gcc; on AIX with GCC the shared lib goes on
+# the link command line as a regular file argument.
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
+		  "${binfile}" \
+		  executable \
+		  [list debug \
+		       additional_flags=${binfile_lib} \
+		       additional_flags=-lpthread]] != "" } {
+    unsupported "failed to compile test executable"
+    return
+}
+
+# Helper: assert that printing VAR_EXPR from the inferior gives EXPECTED.
+proc check_tls_var { var_expr expected test_name } {
+    gdb_test "print $var_expr" "= $expected" $test_name
+}
+
+clean_restart ${testfile}
+gdb_load_shlib ${binfile_lib}
+
+if {![runto_main]} {
+    return
+}
+
+# Set breakpoint at the labelled line in main.
+set bp_line [gdb_get_line_number "breakpoint here" \
+			"${srcdir}/${subdir}/${srcfile}"]
+gdb_breakpoint $bp_line
+gdb_continue_to_breakpoint "run to breakpoint"
+
+# local-exec testing
+# le_var1 and le_var2 are defined in the main executable.  At this point
+# they have been set to 11 and 22 respectively.
+with_test_prefix "local-exec" {
+    check_tls_var le_var1 11 "le_var1 == 11"
+    check_tls_var le_var2 22 "le_var2 == 22"
+
+    gdb_test "info address le_var1" \
+	"Symbol \"le_var1\" is a thread-local variable.*" \
+	"info address le_var1"
+}
+
+# initial-exec / global-dynamic testing
+# gd_var1 and gd_var2 are defined in the shared library and accessed
+# from the main executable.  Depending on the compiler's TLS dialect
+# the main exe will use either R_TLS_IE = initial-exec or R_TLS+R_TLSM
+# global-dynamic.  Both must produce the correct values 33 and 44.
+with_test_prefix "gd-from-main" {
+    check_tls_var gd_var1 33 "gd_var1 == 33"
+    check_tls_var gd_var2 44 "gd_var2 == 44"
+
+    gdb_test "info address gd_var1" \
+	"Symbol \"gd_var1\" is a thread-local variable.*" \
+	"info address gd_var1"
+}
+
+# local-dynamic testing
+# ld_only_var is accessed solely from within the shared library using
+# local-dynamic model R_TLS_LD + R_TLSML.  lib_set_tls_vars set it to
+# 55.  Because ld_only_var is not referenced in the main executable there
+# is no per-variable TOC slot for it in the main exe's .loader section;
+# The fallback code must be used here which is rs6000_aix_compute_tls_address ()
+with_test_prefix "local-dynamic" {
+    check_tls_var ld_only_var 55 "ld_only_var == 55"
+
+    gdb_test "info address ld_only_var" \
+	"Symbol \"ld_only_var\" is a thread-local variable.*" \
+	"info address ld_only_var"
+}
+
+# Library-side local-dynamic - verify via library accessor
+# Cross-check by calling the library function that reads the same variable.
+with_test_prefix "lib-accessor" {
+    gdb_test "print lib_get_gd_var1()" "= 33" "lib_get_gd_var1"
+    gdb_test "print lib_get_gd_var2()" "= 44" "lib_get_gd_var2"
+    gdb_test "print lib_get_ld_only()" "= 55"  "lib_get_ld_only"
+}
-- 
2.51.2


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re:  [PATCH v1 3/3] Add test cases for all TLS support in AIX
  2026-09-03  8:54 [PATCH v1 3/3] Add test cases for all TLS support in AIX Aditya Vidyadhar Kamath
@ 2026-09-03  9:07 ` Aditya Kamath
  0 siblings, 0 replies; 2+ messages in thread
From: Aditya Kamath @ 2026-09-03  9:07 UTC (permalink / raw)
  To: Aditya Vidyadhar Kamath, Ulrich Weigand, simon.marchi, tom
  Cc: gdb-patches, SANGAMESH MALLAYYA

[-- Attachment #1: Type: text/plain, Size: 15971 bytes --]

>gd_var1 and gd_var2 are initial exec if the compiler chose R_TLS_IE via compiler options otherwise is local dynamic.
>gd_var1, gd_var2 are local dynamic.

gd_var1 and gd_var2 are global dynamic actually. The local dynamic in both these lines I need to change to global dynamic. I will git amend the same once I get feedback. Just wanted to let you know.


From: Aditya Vidyadhar Kamath <akamath996@gmail.com>
Date: Thursday, 3 September 2026 at 2:25 PM
To: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>; simon.marchi@polymtl.ca <simon.marchi@polymtl.ca>; tom@tromey.com <tom@tromey.com>
Cc: gdb-patches@sourceware.org <gdb-patches@sourceware.org>; Aditya Kamath <Aditya.Kamath1@ibm.com>; SANGAMESH MALLAYYA <sangamesh.swamy@in.ibm.com>; Aditya Kamath <Aditya.Kamath1@ibm.com>
Subject: [EXTERNAL] [PATCH v1 3/3] Add test cases for all TLS support in AIX

From: Aditya Vidyadhar Kamath <aditya.kamath1@ibm.com>

This patch adds test cases to all the 4 types of TLS variables in a shared library
on AIX.

which is
1: local-exec
2: initial-exec
3: global-dynamic
4: local-dynamic

le_var1 and le_var2 are local-exec in the main executable.
gd_var1 and gd_var2 are initial exec if the compiler chose R_TLS_IE via compiler options otherwise is local dynamic.
gd_var1, gd_var2 are local dynamic.
ld_only_var is local dynamic since it is used in the shared library only and not in main executable.
[See: powerpc-aix-tls-main.c]

This test prints all of them and checks if we can access them in AIX.

When we run this on AIX we get,
gmake check RUNTESTFLAGS='gdb.threads/thread_events.exp  CC_FOR_TARGET="/opt/freeware/bin/gcc" CXX_FOR_TARGET="/opt/freeware/bin/g++" CXXFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64" CFLAGS_FOR_TARGET="-O0 -w -g -gdwarf -maix64"'

Running target unix
Using /opt/freeware/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /opt/freeware/share/dejagnu/config/unix.exp as generic interface file for target.
Using /current_gdb/binutils-gdb/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file.
Running /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_events.exp ...

                === gdb Summary ===

# of expected passes            11
/current_gdb/binutils-gdb/gdb/gdb version  19.0.50.20260819-git -nw -nx -q -iex "set height 0" -iex "set width 0" -data-directory /current_gdb/binutils-gdb/gdb/data-directory -iex "set interactive-mode on"


---
 gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c  |  66 ++++++++
 gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c |  69 ++++++++
 gdb/testsuite/gdb.arch/powerpc-aix-tls.exp    | 147 ++++++++++++++++++
 3 files changed, 282 insertions(+)
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
 create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-tls.exp

diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c b/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
new file mode 100644
index 00000000000..3f34d2e570b
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls-lib.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DwIDAg&c=BSDicqBQBDjDI9RkVyTcHQ&r=f-oUQ8ByG1nZ71OI9p76qywCPh7mxzU69hBYnkP9Nis&m=66_Kp84mmQEKNZ7tKE-MfzLaqfgXmgYhLjZwTzzdWoOPrQlE1jHOFQhT8b6nDb4a&s=qdq2vvKujGmQ9cWtAL7q8LKQY1jPVN2ll2n_X9kaJYA&e= >.  */
+
+/* Global-dynamic TLS variables exported from this shared library.
+   The main executable accesses these (R_TLS + R_TLSM relocs), which means
+   the TOC slots will be emitted in the main executable's .loader section.
+   Within this library the compiler may use local-dynamic or initial-exec
+   depending on flags, but the main exe always uses global-dynamic for
+   cross-module symbols.  */
+
+/* gd_var1 and gd_var2 are exported TLS variables that the main executable
+   imports via global-dynamic.  They are also accessed here via local-dynamic
+   so that R_TLS_LD + R_TLSML relocs appear in this library's .loader.  */
+__thread int gd_var1 = 10;
+__thread int gd_var2 = 20;
+
+/* ld_only_var is a local-dynamic variable that is ONLY accessed from within
+   this shared library (never referenced in the main executable).  This
+   exercises the access-dependency limitation: GDB must be able to resolve it
+   even though there is no R_TLS/R_TLSM slot for it in the main exe's loader
+   section.  */
+__thread int ld_only_var = 30;
+
+/* Access gd_var1, gd_var2 and ld_only_var from within the library so that
+   the compiler emits R_TLS_LD / R_TLSML relocs into this .so's .loader
+   section.  Force local-dynamic model explicitly.  */
+int
+lib_set_tls_vars (int a, int b, int c)
+{
+  gd_var1    = a;
+  gd_var2    = b;
+  ld_only_var = c;
+  return gd_var1 + gd_var2 + ld_only_var;
+}
+
+int
+lib_get_gd_var1 (void)
+{
+  return gd_var1;
+}
+
+int
+lib_get_gd_var2 (void)
+{
+  return gd_var2;
+}
+
+int
+lib_get_ld_only (void)
+{
+  return ld_only_var;
+}
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c b/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
new file mode 100644
index 00000000000..1a8a5561e71
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls-main.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DwIDAg&c=BSDicqBQBDjDI9RkVyTcHQ&r=f-oUQ8ByG1nZ71OI9p76qywCPh7mxzU69hBYnkP9Nis&m=66_Kp84mmQEKNZ7tKE-MfzLaqfgXmgYhLjZwTzzdWoOPrQlE1jHOFQhT8b6nDb4a&s=qdq2vvKujGmQ9cWtAL7q8LKQY1jPVN2ll2n_X9kaJYA&e= >.  */
+
+/* This test exercises all four XCOFF TLS models on 64-bit AIX:
+   - local-exec  (variables in the main executable, TP-relative offset)
+   - initial-exec (R_TLS_IE  in which the compiler uses this for extern __thread
+                   variables in the main exe when linked without -brtl)
+   - global-dynamic (R_TLS + R_TLSM in which cross-module access to variables
+                     in a shared library)
+   - local-dynamic  (R_TLS_LD + R_TLSML The within-module access inside the
+                     shared library; also exercises the access-dependency
+                     case for ld_only_var which is never accessed here)  */
+
+/* local-exec TLS variables: defined in the main executable.  */
+__thread int le_var1 = 100;
+__thread int le_var2 = 200;
+
+/* Declaration of TLS variables from the shared library.
+   The compiler uses global-dynamic model for these cross-module accesses,
+   emitting R_TLS + R_TLSM pairs in the .loader section.  */
+extern __thread int gd_var1;
+extern __thread int gd_var2;
+/* ld_only_var is intentionally NOT declared here we only look it up via
+   GDB's symbol lookup to exercise the access-dependency fallback.  This
+   is an edge case.  */
+
+extern int lib_set_tls_vars (int, int, int);
+extern int lib_get_gd_var1 (void);
+extern int lib_get_gd_var2 (void);
+extern int lib_get_ld_only (void);
+
+volatile int sink;
+
+int
+main (void)
+{
+  /* Set local-exec variables to known values.  */
+  le_var1 = 11;
+  le_var2 = 22;
+
+  /* Access cross-module globals -- forces R_TLS + R_TLSM into the main
+     executable's .loader section for gd_var1 and gd_var2.  */
+  gd_var1 = 33;
+  gd_var2 = 44;
+
+  /* Call into the library so the library-side TLS is initialised.  This
+     also exercises the local-dynamic model inside the shared library (the
+     compiler will use R_TLS_LD for within-module accesses to gd_var1,
+     gd_var2, and ld_only_var inside the .so).  */
+  lib_set_tls_vars (33, 44, 55);
+
+  sink = le_var1 + le_var2 + gd_var1 + gd_var2; /* breakpoint here */
+
+  return sink;
+}
diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp b/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp
new file mode 100644
index 00000000000..824884dffc9
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-aix-tls.exp
@@ -0,0 +1,147 @@
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DwIDAg&c=BSDicqBQBDjDI9RkVyTcHQ&r=f-oUQ8ByG1nZ71OI9p76qywCPh7mxzU69hBYnkP9Nis&m=66_Kp84mmQEKNZ7tKE-MfzLaqfgXmgYhLjZwTzzdWoOPrQlE1jHOFQhT8b6nDb4a&s=qdq2vvKujGmQ9cWtAL7q8LKQY1jPVN2ll2n_X9kaJYA&e= >.
+
+# Test GDB TLS variable access on 64-bit AIX (XCOFF) covering all four
+# TLS models:
+#
+#   1. local-exec [le_var1, le_var2 variables defined in the main executable]
+#      GDB reads the XCOFF symbol value directly as a TP-relative offset.
+#
+#   2. initial-exec [gd_var1, gd_var2 accessed from the main executable]
+#      If the compiler chose R_TLS_IE for cross-module accesses
+#      GDB reads the TOC slot and adds it to TP.
+#
+#   3. global-dynamic [gd_var1, gd_var2 via R_TLS + R_TLSM]
+#      GDB reads the module-id from the R_TLSM slot, looks up
+#      thread_vector[mod_id] to find the TLS block base, and adds the per-variable
+#      offset from the R_TLS slot.
+#
+#   4. local-dynamic [ld_only_var which is only accessed from inside the .so of this test case]
+#      GDB reads the module-id from the R_TLSML slot in the .so, looks
+#      up thread_vector[mod_id], and adds the within-module offset from R_TLS_LD.
+#      ld_only_var is never referenced in the main executable, so there
+#      is no per-variable TOC slot for it in the main executbale; So GDB must use
+#      the access-dependency fallback path which is rs6000_aix_compute_tls_address ().
+
+require {istarget "powerpc*-*-aix*"}
+
+standard_testfile powerpc-aix-tls-main.c
+set srcfile_lib powerpc-aix-tls-lib.c
+set binfile_lib [standard_output_file powerpc-aix-tls-lib.so]
+
+# Build shared library
+# On AIX with GCC the standard gdb_compile_shlib helper appends
+# "-Wl,-soname,<name>" which the AIX ld interprets as an input file
+# (COFF mismatch error).  Instead we do the two-step compile+link
+# manually. First compile the .c to a -fPIC .o, then link it to a .so
+# with -shared -Wl,-bexpall -lpthread (needed for __tls_get_addr).
+set lib_obj [standard_output_file powerpc-aix-tls-lib.c.o]
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile_lib}" \
+                 "${lib_obj}" \
+                 object \
+                 {debug additional_flags=-fPIC}] != "" } {
+    unsupported "failed to compile shared library object"
+    return
+}
+if { [gdb_compile "${lib_obj}" \
+                 "${binfile_lib}" \
+                 executable \
+                 {debug additional_flags=-shared \
+                        additional_flags=-Wl,-bexpall \
+                        additional_flags=-lpthread}] != "" } {
+    unsupported "failed to link shared library"
+    return
+}
+
+# Build main executable linked against the shared library
+# Pass the .so directly to gcc; on AIX with GCC the shared lib goes on
+# the link command line as a regular file argument.
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
+                 "${binfile}" \
+                 executable \
+                 [list debug \
+                      additional_flags=${binfile_lib} \
+                      additional_flags=-lpthread]] != "" } {
+    unsupported "failed to compile test executable"
+    return
+}
+
+# Helper: assert that printing VAR_EXPR from the inferior gives EXPECTED.
+proc check_tls_var { var_expr expected test_name } {
+    gdb_test "print $var_expr" "= $expected" $test_name
+}
+
+clean_restart ${testfile}
+gdb_load_shlib ${binfile_lib}
+
+if {![runto_main]} {
+    return
+}
+
+# Set breakpoint at the labelled line in main.
+set bp_line [gdb_get_line_number "breakpoint here" \
+                       "${srcdir}/${subdir}/${srcfile}"]
+gdb_breakpoint $bp_line
+gdb_continue_to_breakpoint "run to breakpoint"
+
+# local-exec testing
+# le_var1 and le_var2 are defined in the main executable.  At this point
+# they have been set to 11 and 22 respectively.
+with_test_prefix "local-exec" {
+    check_tls_var le_var1 11 "le_var1 == 11"
+    check_tls_var le_var2 22 "le_var2 == 22"
+
+    gdb_test "info address le_var1" \
+       "Symbol \"le_var1\" is a thread-local variable.*" \
+       "info address le_var1"
+}
+
+# initial-exec / global-dynamic testing
+# gd_var1 and gd_var2 are defined in the shared library and accessed
+# from the main executable.  Depending on the compiler's TLS dialect
+# the main exe will use either R_TLS_IE = initial-exec or R_TLS+R_TLSM
+# global-dynamic.  Both must produce the correct values 33 and 44.
+with_test_prefix "gd-from-main" {
+    check_tls_var gd_var1 33 "gd_var1 == 33"
+    check_tls_var gd_var2 44 "gd_var2 == 44"
+
+    gdb_test "info address gd_var1" \
+       "Symbol \"gd_var1\" is a thread-local variable.*" \
+       "info address gd_var1"
+}
+
+# local-dynamic testing
+# ld_only_var is accessed solely from within the shared library using
+# local-dynamic model R_TLS_LD + R_TLSML.  lib_set_tls_vars set it to
+# 55.  Because ld_only_var is not referenced in the main executable there
+# is no per-variable TOC slot for it in the main exe's .loader section;
+# The fallback code must be used here which is rs6000_aix_compute_tls_address ()
+with_test_prefix "local-dynamic" {
+    check_tls_var ld_only_var 55 "ld_only_var == 55"
+
+    gdb_test "info address ld_only_var" \
+       "Symbol \"ld_only_var\" is a thread-local variable.*" \
+       "info address ld_only_var"
+}
+
+# Library-side local-dynamic - verify via library accessor
+# Cross-check by calling the library function that reads the same variable.
+with_test_prefix "lib-accessor" {
+    gdb_test "print lib_get_gd_var1()" "= 33" "lib_get_gd_var1"
+    gdb_test "print lib_get_gd_var2()" "= 44" "lib_get_gd_var2"
+    gdb_test "print lib_get_ld_only()" "= 55"  "lib_get_ld_only"
+}
--
2.51.2


[-- Attachment #2: Type: text/html, Size: 23173 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-03  9:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-03  8:54 [PATCH v1 3/3] Add test cases for all TLS support in AIX Aditya Vidyadhar Kamath
2026-09-03  9:07 ` Aditya Kamath

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox