aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/gdb.base')
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.c2
-rw-r--r--gdb/testsuite/gdb.base/bg-execution-repeat.exp11
-rw-r--r--gdb/testsuite/gdb.base/break1.c8
-rw-r--r--gdb/testsuite/gdb.base/default.exp2
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c6
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids.exp133
-rw-r--r--gdb/testsuite/gdb.base/tls-common.exp.tcl50
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj-lib.c87
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.c311
-rw-r--r--gdb/testsuite/gdb.base/tls-dlobj.exp378
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.c89
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj.exp230
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj1.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj2.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-multiobj3.c26
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.c57
-rw-r--r--gdb/testsuite/gdb.base/tls-nothreads.exp248
17 files changed, 1688 insertions, 2 deletions
diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.c b/gdb/testsuite/gdb.base/bg-execution-repeat.c
index 8e9bae4..3c0cc76 100644
--- a/gdb/testsuite/gdb.base/bg-execution-repeat.c
+++ b/gdb/testsuite/gdb.base/bg-execution-repeat.c
@@ -37,9 +37,9 @@ main (void)
{
alarm (60);
+ do_wait = 1;
foo ();
- do_wait = 1;
wait ();
/* do_wait set to 0 externally. */
diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.exp b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
index b1496ee..d5580fb 100644
--- a/gdb/testsuite/gdb.base/bg-execution-repeat.exp
+++ b/gdb/testsuite/gdb.base/bg-execution-repeat.exp
@@ -67,6 +67,17 @@ proc test {continue_cmd} {
# enable the "set var" command with an interrupt / continue& pair.
gdb_test -no-prompt-anchor "interrupt"
+ set test "interrupt received"
+ set re [string_to_regexp "Program received signal SIGINT, Interrupt."]
+ gdb_expect {
+ -re $re {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
# Allow the breakpoint to trigger.
gdb_test -no-prompt-anchor "set var do_wait=0"
diff --git a/gdb/testsuite/gdb.base/break1.c b/gdb/testsuite/gdb.base/break1.c
index 110341c..26c4663 100644
--- a/gdb/testsuite/gdb.base/break1.c
+++ b/gdb/testsuite/gdb.base/break1.c
@@ -23,7 +23,13 @@ struct some_struct
{
int a_field;
int b_field;
- union { int z_field; };
+ union
+ {
+ struct
+ {
+ int z_field;
+ };
+ };
};
struct some_struct values[50];
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index d4d6b20..3abd049 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -699,6 +699,8 @@ set show_conv_list \
{$_gdb_minor = 1} \
{$_shell_exitsignal = void} \
{$_shell_exitcode = 0} \
+ {$_active_linker_namespaces = 1} \
+ {$_current_linker_namespace = <error: No registers.>}\
}
if [allow_python_tests] {
append show_conv_list \
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
index 3bcd819..c7c038a 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids-main.c
@@ -41,6 +41,12 @@ main (void)
handle[2] = dlmopen (LM_ID_NEWLM, DSO_NAME, RTLD_LAZY | RTLD_LOCAL);
assert (handle[2] != NULL);
+ for (dl = 2; dl >= 0; dl--)
+ {
+ fun = dlsym (handle[dl], "inc");
+ fun (dl);
+ }
+
dlclose (handle[0]); /* TAG: first dlclose */
dlclose (handle[1]); /* TAG: second dlclose */
dlclose (handle[2]); /* TAG: third dlclose */
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index 3ddc07e..8f52199 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -105,4 +105,137 @@ proc test_info_shared {} {
"after unloading everything"
}
+# Run all tests related to the linkage namespaces convenience
+# variables, _active_namespaces and _current_namespaces.
+proc_with_prefix test_conv_vars {} {
+ clean_restart $::binfile
+
+ gdb_test "print \$_active_linker_namespaces" "1" \
+ "1 namespace before starting inferior"
+ gdb_test "print \$_current_linker_namespace" "No registers." \
+ "No current namespace before starting inferior"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_test "print \$_active_linker_namespaces" "1" \
+ "Before activating namespaces"
+ gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[0\\\]\\\]\"" \
+ "Still in the default namespace"
+
+ gdb_breakpoint "inc" allow-pending
+ gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"]
+
+ foreach_with_prefix dl {3 2 1} {
+ gdb_continue_to_breakpoint "inc"
+
+ gdb_test "print \$_current_linker_namespace" ".*\"\\\[\\\[$dl\\\]\\\]\"" \
+ "Verify we're in namespace $dl"
+ }
+
+ gdb_continue_to_breakpoint "first dlclose"
+ gdb_test "print \$_active_linker_namespaces" "4" "all SOs loaded"
+
+ gdb_test "next" ".*second dlclose.*" "close one SO"
+ gdb_test "print \$_active_linker_namespaces" "3" "one SOs unloaded"
+ gdb_test "next" ".*third dlclose.*" "close another SO"
+ gdb_test "print \$_active_linker_namespaces" "2" "two SOs unloaded"
+
+ # Restarting GDB so that we can test setting a breakpoint
+ # using the convenience variable, while a proper bp syntax
+ # isn't implemented for namespaces
+ clean_restart $::binfile
+ if {![runto_main]} {
+ return
+ }
+
+ # We need to load one SO because you can't have confitional
+ # breakpoints and pending breakpoints at the same time with
+ # gdb_breakpoint.
+ gdb_test "next" ".*assert.*" "load the first SO"
+ gdb_breakpoint "inc if \$_streq(\$_current_linker_namespace, \"\[\[2\]\]\")"
+ gdb_continue_to_breakpoint "inc"
+ gdb_continue_to_end "" continue 1
+}
+
+# Run several tests relating to the command "info namespaces".
+proc test_info_linker_namespaces {} {
+ clean_restart $::binfile
+
+ if { ![runto_main] } {
+ return
+ }
+
+ with_test_prefix "info linker-namespaces" {
+ gdb_breakpoint [gdb_get_line_number "TAG: first dlclose"]
+ gdb_continue_to_breakpoint "TAG: first dlclose"
+ }
+
+ # First, test printing a single namespace, and ensure all of
+ # them are correct, using both syntaxes.
+ set found_all_libs false
+ gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" -lbl {
+ -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[0\\\]\\\]" {
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, and up to 2 more libraries.
+ set libs $expect_out(1,string)
+ set found_all_libs [expr $libs - 1 <= 2]
+ exp_continue
+ }
+ -re "^\r\n$::gdb_prompt $" {
+ gdb_assert $found_all_libs "the correct number of libraries was reported"
+ }
+ -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
+ exp_continue
+ }
+ }
+ foreach_with_prefix ns {1 2 3} {
+ set found_test_so false
+ set found_all_libs false
+ gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" -lbl {
+ -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[$ns\\\]\\\]" {
+ set libs $expect_out(1,string)
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, the test SO, and maybe up to 2
+ # more libraries.
+ set found_all_libs [expr $libs - 2 <= 2]
+ exp_continue
+ }
+ -re "^\r\n\[^\r\n\]+${::binfile_lib}\[^\r\n\]*(?=\r\n)" {
+ set found_test_so true
+ exp_continue
+ }
+ -re "^\r\n$::gdb_prompt $" {
+ gdb_assert $found_test_so "this testfle's SO was reported"
+ gdb_assert $found_all_libs "the correct number of libraries was reported"
+ }
+ -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
+ exp_continue
+ }
+ }
+ }
+
+ # These patterns are simpler, and purposefully glob multiple lines.
+ # The point is to ensure that we find and display all the namespaces,
+ # without worrying about the libraries printed, since that was tested
+ # above.
+ gdb_test "info linker-namespaces" \
+ [multi_line "There are 4 linker namespaces loaded" \
+ "There are $::decimal libraries loaded in linker namespace ..0.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..1.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..2.." \
+ ".*" \
+ "There are $::decimal libraries loaded in linker namespace ..3.." \
+ ".*" ] "print namespaces with no argument"
+}
+
test_info_shared
+test_conv_vars
+test_info_linker_namespaces
diff --git a/gdb/testsuite/gdb.base/tls-common.exp.tcl b/gdb/testsuite/gdb.base/tls-common.exp.tcl
new file mode 100644
index 0000000..7aa7f46
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-common.exp.tcl
@@ -0,0 +1,50 @@
+# Copyright 2024 Free Software Foundation, Inc.
+# 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.
+
+# Require statement, variables and procs used by tls-nothreads.exp,
+# tls-multiobj.exp, and tls-dlobj.exp.
+
+# The tests listed above are known to work for the targets listed on
+# the 'require' line, below.
+#
+# At the moment, only the Linux target is listed, but, ideally, these
+# tests should be run on other targets too. E.g, testing on FreeBSD
+# shows many failures which should be addressed in some fashion before
+# enabling it for that target.
+
+require {is_any_target "*-*-linux*"}
+
+# These are the targets which have support for internal TLS lookup:
+
+set internal_tls_linux_targets {"x86_64-*-linux*" "aarch64-*-linux*"
+ "riscv*-*-linux*" "powerpc64*-*-linux*"
+ "s390x*-*-linux*"}
+
+# The "maint set force-internal-tls-address-lookup" command is only
+# available for certain Linux architectures. Don't attempt to force
+# use of internal TLS support for architectures which don't support
+# it.
+
+if [is_any_target {*}$internal_tls_linux_targets] {
+ set internal_tls_iters { false true }
+} else {
+ set internal_tls_iters { false }
+}
+
+# Set up a kfail with message KFAIL_MSG when KFAIL_COND holds, then
+# issue gdb_test with command CMD and regular expression RE.
+
+proc gdb_test_with_kfail {cmd re kfail_cond kfail_msg} {
+ if [uplevel 1 [list expr $kfail_cond]] {
+ setup_kfail $kfail_msg *-*-*
+ }
+ gdb_test $cmd $re
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj-lib.c b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
new file mode 100644
index 0000000..c69bab7
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj-lib.c
@@ -0,0 +1,87 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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 program needs to be compiled with preprocessor symbol set to
+ a small integer, e.g. "gcc -DN=1 ..." With N defined, the CONCAT2
+ and CONCAT3 macros will construct suitable names for the global
+ variables and functions. */
+
+#define CONCAT2(a,b) CONCAT2_(a,b)
+#define CONCAT2_(a,b) a ## b
+
+#define CONCAT3(a,b,c) CONCAT3_(a,b,c)
+#define CONCAT3_(a,b,c) a ## b ## c
+
+/* For N=1, this ends up being...
+ __thread int tls_lib1_tbss_1;
+ __thread int tls_lib1_tbss_2;
+ __thread int tls_lib1_tdata_1 = 196;
+ __thread int tls_lib1_tdata_2 = 197; */
+
+__thread int CONCAT3(tls_lib, N, _tbss_1);
+__thread int CONCAT3(tls_lib, N, _tbss_2);
+__thread int CONCAT3(tls_lib, N, _tdata_1) = CONCAT2(N, 96);
+__thread int CONCAT3(tls_lib, N, _tdata_2) = CONCAT2(N, 97);
+
+/* Substituting for N, define function:
+
+ int get_tls_libN_var (int which) . */
+
+int
+CONCAT3(get_tls_lib, N, _var) (int which)
+{
+ switch (which)
+ {
+ case 0:
+ return -1;
+ case 1:
+ return CONCAT3(tls_lib, N, _tbss_1);
+ case 2:
+ return CONCAT3(tls_lib, N, _tbss_2);
+ case 3:
+ return CONCAT3(tls_lib, N, _tdata_1);
+ case 4:
+ return CONCAT3(tls_lib, N, _tdata_2);
+ }
+ return -1;
+}
+
+/* Substituting for N, define function:
+
+ void set_tls_libN_var (int which, int val) . */
+
+void
+CONCAT3(set_tls_lib, N, _var) (int which, int val)
+{
+ switch (which)
+ {
+ case 0:
+ break;
+ case 1:
+ CONCAT3(tls_lib, N, _tbss_1) = val;
+ break;
+ case 2:
+ CONCAT3(tls_lib, N, _tbss_2) = val;
+ break;
+ case 3:
+ CONCAT3(tls_lib, N, _tdata_1) = val;
+ break;
+ case 4:
+ CONCAT3(tls_lib, N, _tdata_2) = val;
+ break;
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.c b/gdb/testsuite/gdb.base/tls-dlobj.c
new file mode 100644
index 0000000..322bdda
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj.c
@@ -0,0 +1,311 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef void (*setter_ftype) (int which, int val);
+
+__thread int tls_main_tbss_1;
+__thread int tls_main_tbss_2;
+__thread int tls_main_tdata_1 = 96;
+__thread int tls_main_tdata_2 = 97;
+
+extern void set_tls_lib10_var (int which, int val);
+extern void set_tls_lib11_var (int which, int val);
+
+volatile int data;
+
+static void
+set_tls_main_var (int which, int val)
+{
+ switch (which)
+ {
+ case 1:
+ tls_main_tbss_1 = val;
+ break;
+ case 2:
+ tls_main_tbss_2 = val;
+ break;
+ case 3:
+ tls_main_tdata_1 = val;
+ break;
+ case 4:
+ tls_main_tdata_2 = val;
+ break;
+ }
+}
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+static void *
+load_dso (char *dso_name, int n, setter_ftype *setterp)
+{
+ char buf[80];
+ void *sym;
+ void *handle = dlopen (dso_name, RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL)
+ {
+ fprintf (stderr, "dlopen of DSO '%s' failed: %s\n", dso_name, dlerror ());
+ exit (1);
+ }
+ sprintf (buf, "set_tls_lib%d_var", n);
+ sym = dlsym (handle, buf);
+ assert (sym != NULL);
+ *setterp = sym;
+
+ /* Some libc implementations (for some architectures) refuse to
+ initialize TLS data structures (specifically, the DTV) without
+ first calling dlsym on one of the TLS symbols. */
+ sprintf (buf, "tls_lib%d_tdata_1", n);
+ assert (dlsym (handle, buf) != NULL);
+
+ return handle;
+}
+
+int
+main (int argc, char **argv)
+{
+ int i, status;
+ setter_ftype s0, s1, s2, s3, s4, s10, s11;
+ void *h1 = load_dso (OBJ1, 1, &s1);
+ void *h2 = load_dso (OBJ2, 2, &s2);
+ void *h3 = load_dso (OBJ3, 3, &s3);
+ void *h4 = load_dso (OBJ4, 4, &s4);
+ s0 = set_tls_main_var;
+ s10 = set_tls_lib10_var;
+ s11 = set_tls_lib11_var;
+
+ use_it (0); /* main-breakpoint-1 */
+
+ /* Set TLS variables in main program and all libraries. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 10 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 110 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 210 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 310 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 410 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1010 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1110 + i);
+
+ use_it (0); /* main-breakpoint-2 */
+
+ /* Unload lib2 and lib3. */
+ status = dlclose (h2);
+ assert (status == 0);
+ status = dlclose (h3);
+ assert (status == 0);
+
+ /* Set TLS variables in main program and in libraries which are still
+ loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 20 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 120 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 420 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1020 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1120 + i);
+
+ use_it (0); /* main-breakpoint-3 */
+
+ /* Load lib3. */
+ h3 = load_dso (OBJ3, 3, &s3);
+
+ /* Set TLS vars again; currently, only lib2 is not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 30 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 130 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 330 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 430 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1030 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1130 + i);
+
+ use_it (0); /* main-breakpoint-4 */
+
+ /* Unload lib1 and lib4; load lib2. */
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+ h2 = load_dso (OBJ2, 2, &s2);
+
+ /* Set TLS vars; currently, lib2 and lib3 are loaded,
+ lib1 and lib4 are not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 40 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 240 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 340 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1040 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1140 + i);
+
+ use_it (0); /* main-breakpoint-5 */
+
+ /* Load lib4 and lib1. Unload lib2. */
+ h4 = load_dso (OBJ4, 4, &s4);
+ h1 = load_dso (OBJ1, 1, &s1);
+ status = dlclose (h2);
+ assert (status == 0);
+
+ /* Set TLS vars; currently, lib1, lib3, and lib4 are loaded;
+ lib2 is not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 50 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 150 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 350 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 450 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1050 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1150 + i);
+
+ use_it (0); /* main-breakpoint-6 */
+
+ /* Load lib2, unload lib1, lib3, and lib4; then load lib3 again. */
+ h2 = load_dso (OBJ2, 2, &s2);
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+ h3 = load_dso (OBJ3, 3, &s3);
+
+ /* Set TLS vars; currently, lib2 and lib3 are loaded;
+ lib1 and lib4 are not loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 60 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 260 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 360 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1060 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1160 + i);
+
+ use_it (0); /* main-breakpoint-7 */
+
+ /* Unload lib3 and lib2, then (re)load lib4, lib3, lib2, and lib1,
+ in that order. */
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h2);
+ assert (status == 0);
+ h4 = load_dso (OBJ4, 4, &s4);
+ h3 = load_dso (OBJ3, 3, &s3);
+ h2 = load_dso (OBJ2, 2, &s2);
+ h1 = load_dso (OBJ1, 1, &s1);
+
+ /* Set TLS vars; currently, lib1, lib2, lib3, and lib4 are all
+ loaded. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 70 + i);
+ for (i = 1; i <= 4; i++)
+ s1 (i, 170 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 270 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 370 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 470 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1070 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1170 + i);
+
+ use_it (0); /* main-breakpoint-8 */
+
+ /* Unload lib3, lib1, and lib4. */
+ status = dlclose (h3);
+ assert (status == 0);
+ status = dlclose (h1);
+ assert (status == 0);
+ status = dlclose (h4);
+ assert (status == 0);
+
+ /* Set TLS vars; currently, lib2 is loaded; lib1, lib3, and lib4 are
+ not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 80 + i);
+ for (i = 1; i <= 4; i++)
+ s2 (i, 280 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1080 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1180 + i);
+
+ use_it (0); /* main-breakpoint-9 */
+
+ /* Load lib3, unload lib2, load lib4. */
+ h3 = load_dso (OBJ3, 3, &s3);
+ status = dlclose (h2);
+ assert (status == 0);
+ h4 = load_dso (OBJ4, 4, &s4);
+
+ /* Set TLS vars; currently, lib3 and lib4 are loaded; lib1 and lib2
+ are not. */
+ for (i = 1; i <= 4; i++)
+ s0 (i, 90 + i);
+ for (i = 1; i <= 4; i++)
+ s3 (i, 390 + i);
+ for (i = 1; i <= 4; i++)
+ s4 (i, 490 + i);
+ for (i = 1; i <= 4; i++)
+ s10 (i, 1090 + i);
+ for (i = 1; i <= 4; i++)
+ s11 (i, 1190 + i);
+
+ use_it (0); /* main-breakpoint-10 */
+
+ /* Attempt to keep variables in the main program from being optimized
+ away. */
+ use_it (tls_main_tbss_1);
+ use_it (tls_main_tbss_2);
+ use_it (tls_main_tdata_1);
+ use_it (tls_main_tdata_2);
+
+ use_it (100); /* main-breakpoint-last */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-dlobj.exp b/gdb/testsuite/gdb.base/tls-dlobj.exp
new file mode 100644
index 0000000..02f2ff8
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-dlobj.exp
@@ -0,0 +1,378 @@
+# Copyright 2024 Free Software Foundation, Inc.
+# 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.
+
+# Test that the GDB-internal TLS link map to module id mapping code
+# works correctly when debugging a program which is linked against
+# shared objects and which also loads and unloads other shared objects
+# in different orders. For targets which have GDB-internal TLS
+# support, it'll check both GDB-internal TLS support as well as that
+# provided by a helper library such as libthread_db.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+require allow_shlib_tests
+
+standard_testfile
+
+set libsrc "${srcdir}/${subdir}/${testfile}-lib.c"
+
+# These will be dlopen'd:
+set lib1obj [standard_output_file "${testfile}1-lib.so"]
+set lib2obj [standard_output_file "${testfile}2-lib.so"]
+set lib3obj [standard_output_file "${testfile}3-lib.so"]
+set lib4obj [standard_output_file "${testfile}4-lib.so"]
+
+# These will be dynamically linked with the main program:
+set lib10obj [standard_output_file "${testfile}10-lib.so"]
+set lib11obj [standard_output_file "${testfile}11-lib.so"]
+
+# Due to problems with some versions of glibc, we expect some tests to
+# fail due to TLS storage not being allocated/initialized. Test
+# command CMD using regular expression RE, and use XFAIL instead of
+# FAIL when the relevant RE is matched and COND is true when evaluated
+# in the upper level.
+
+proc gdb_test_with_xfail { cmd re cond} {
+ gdb_test_multiple $cmd $cmd {
+ -re -wrap $re {
+ pass $gdb_test_name
+ }
+ -re -wrap "The inferior has not yet allocated storage for thread-local variables.*" {
+ if [ uplevel 1 [list expr $cond]] {
+ xfail $gdb_test_name
+ } else {
+ fail $gdb_test_name
+ }
+ }
+ }
+}
+
+proc do_tests {force_internal_tls} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ with_test_prefix "before assignments" {
+ gdb_test "print tls_main_tbss_1" ".* = 0"
+ gdb_test "print tls_main_tbss_2" ".* = 0"
+ gdb_test "print tls_main_tdata_1" ".* = 96"
+ gdb_test "print tls_main_tdata_2" ".* = 97"
+
+ # For these tests, where we're attempting to access TLS vars
+ # in a dlopen'd library, but before assignment to any of the
+ # vars, so it could happen that storage hasn't been allocated
+ # yet. But it might also work. (When testing against MUSL,
+ # things just work; GLIBC ends to produce the TLS error.) So
+ # accept either the right answer or a TLS error message.
+
+ set tlserr "The inferior has not yet allocated storage for thread-local variables.*"
+ foreach n {1 2 3 4} {
+ gdb_test "print tls_lib${n}_tbss_1" \
+ "0|${tlserr}"
+ gdb_test "print tls_lib${n}_tbss_2" \
+ "0|${tlserr}"
+ gdb_test "print tls_lib${n}_tdata_1" \
+ "96|${tlserr}"
+ gdb_test "print tls_lib${n}_tdata_2" \
+ "97|${tlserr}"
+ }
+ foreach n {10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = 0"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = 0"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}96"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}97"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "at main-breakpoint-2" {
+ gdb_test "print tls_main_tbss_1" ".* = 11"
+ gdb_test "print tls_main_tbss_2" ".* = 12"
+ gdb_test "print tls_main_tdata_1" ".* = 13"
+ gdb_test "print tls_main_tdata_2" ".* = 14"
+
+ foreach n {1 2 3 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}11"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}12"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}13"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}14"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-3"]
+ gdb_continue_to_breakpoint "main-breakpoint-3"
+
+ # At this point lib2 and lib3 have been unloaded. Also, TLS vars
+ # in remaining libraries have been changed.
+
+ with_test_prefix "at main-breakpoint-3" {
+ gdb_test "print tls_main_tbss_1" ".* = 21"
+ gdb_test "print tls_main_tbss_2" ".* = 22"
+ gdb_test "print tls_main_tdata_1" ".* = 23"
+ gdb_test "print tls_main_tdata_2" ".* = 24"
+
+ foreach n {1 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}21"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}22"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}23"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}24"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-4"]
+ gdb_continue_to_breakpoint "main-breakpoint-4"
+
+ # lib3 has been loaded again; lib2 is the only one not loaded.
+
+ with_test_prefix "at main-breakpoint-4" {
+ gdb_test "print tls_main_tbss_1" ".* = 31"
+ gdb_test "print tls_main_tbss_2" ".* = 32"
+ gdb_test "print tls_main_tdata_1" ".* = 33"
+ gdb_test "print tls_main_tdata_2" ".* = 34"
+
+ set cond { $n == 3 }
+ foreach n {1 3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}31" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}32" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}33" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}34" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-5"]
+ gdb_continue_to_breakpoint "main-breakpoint-5"
+
+ # lib2 and lib3 are loaded; lib1 and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-5" {
+ gdb_test "print tls_main_tbss_1" ".* = 41"
+ gdb_test "print tls_main_tbss_2" ".* = 42"
+ gdb_test "print tls_main_tdata_1" ".* = 43"
+ gdb_test "print tls_main_tdata_2" ".* = 44"
+
+ set cond { $n == 2 || $n == 3 }
+ foreach n {2 3 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}41" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}42" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}43" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}44" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-6"]
+ gdb_continue_to_breakpoint "main-breakpoint-6"
+
+ # lib1, lib3 and lib4 are loaded; lib2 is not loaded.
+
+ with_test_prefix "at main-breakpoint-6" {
+ gdb_test "print tls_main_tbss_1" ".* = 51"
+ gdb_test "print tls_main_tbss_2" ".* = 52"
+ gdb_test "print tls_main_tdata_1" ".* = 53"
+ gdb_test "print tls_main_tdata_2" ".* = 54"
+
+ set cond { $n == 1 || $n == 3 || $n == 4}
+ foreach n {1 3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}51" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}52" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}53" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}54" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-7"]
+ gdb_continue_to_breakpoint "main-breakpoint-7"
+
+ # lib2 and lib3 are loaded; lib1 and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-7" {
+ gdb_test "print tls_main_tbss_1" ".* = 61"
+ gdb_test "print tls_main_tbss_2" ".* = 62"
+ gdb_test "print tls_main_tdata_1" ".* = 63"
+ gdb_test "print tls_main_tdata_2" ".* = 64"
+
+ set cond { $n == 2 || $n == 3 }
+ foreach n {2 3 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}61" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}62" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}63" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}64" $cond
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-8"]
+ gdb_continue_to_breakpoint "main-breakpoint-8"
+
+ # lib1, lib2, lib3, and lib4 are all loaded.
+
+ with_test_prefix "at main-breakpoint-8" {
+ gdb_test "print tls_main_tbss_1" ".* = 71"
+ gdb_test "print tls_main_tbss_2" ".* = 72"
+ gdb_test "print tls_main_tdata_1" ".* = 73"
+ gdb_test "print tls_main_tdata_2" ".* = 74"
+
+ foreach n {1 2 3 4 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}71"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}72"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}73"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}74"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-9"]
+ gdb_continue_to_breakpoint "main-breakpoint-9"
+
+ # lib2 is loaded; lib1, lib3, and lib4 are not.
+
+ with_test_prefix "at main-breakpoint-9" {
+ gdb_test "print tls_main_tbss_1" ".* = 81"
+ gdb_test "print tls_main_tbss_2" ".* = 82"
+ gdb_test "print tls_main_tdata_1" ".* = 83"
+ gdb_test "print tls_main_tdata_2" ".* = 84"
+
+ foreach n {2 10 11} {
+ gdb_test "print tls_lib${n}_tbss_1" ".* = ${n}81"
+ gdb_test "print tls_lib${n}_tbss_2" ".* = ${n}82"
+ gdb_test "print tls_lib${n}_tdata_1" ".* = ${n}83"
+ gdb_test "print tls_lib${n}_tdata_2" ".* = ${n}84"
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-10"]
+ gdb_continue_to_breakpoint "main-breakpoint-10"
+
+ # lib3 and lib4 are loaded; lib1 and lib2 are not.
+
+ with_test_prefix "at main-breakpoint-10" {
+ gdb_test "print tls_main_tbss_1" ".* = 91"
+ gdb_test "print tls_main_tbss_2" ".* = 92"
+ gdb_test "print tls_main_tdata_1" ".* = 93"
+ gdb_test "print tls_main_tdata_2" ".* = 94"
+
+ set cond { $n == 3 || $n == 4 }
+ foreach n {3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond
+ }
+ }
+
+ # gdb_interact
+
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test "print tls_main_tbss_1" ".* = 91"
+ gdb_test "print tls_main_tbss_2" ".* = 92"
+ gdb_test "print tls_main_tdata_1" ".* = 93"
+ gdb_test "print tls_main_tdata_2" ".* = 94"
+
+ set cond { $n == 3 || $n == 4 }
+ foreach n {3 4 10 11} {
+ gdb_test_with_xfail "print tls_lib${n}_tbss_1" ".* = ${n}91" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tbss_2" ".* = ${n}92" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_1" ".* = ${n}93" $cond
+ gdb_test_with_xfail "print tls_lib${n}_tdata_2" ".* = ${n}94" $cond
+ }
+ }
+}
+
+# Build shared objects for dlopen:
+if { [gdb_compile_shlib $libsrc $lib1obj [list debug additional_flags=-DN=1]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib2obj [list debug additional_flags=-DN=2]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib3obj [list debug additional_flags=-DN=3]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib4obj [list debug additional_flags=-DN=4]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Build shared objects to link against main program:
+if { [gdb_compile_shlib $libsrc $lib10obj [list debug additional_flags=-DN=10]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $libsrc $lib11obj [list debug additional_flags=-DN=11]] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Use gdb_compile_pthreads to build and link the main program for
+# testing. It's also possible to run the tests using plain old
+# gdb_compile, but this adds complexity with setting up additional
+# KFAILs. (When run using GLIBC versions earlier than 2.34, a program
+# that's not dynamically linked against libpthread will lack a working
+# libthread_db, and, therefore, won't be able to access thread local
+# storage without GDB-internal TLS support. Additional complications
+# arise from when testing on x86_64 with -m32, which tends to work
+# okay on GLIBC 2.34 and newer, but not older versions. It gets messy
+# to properly sort out all of these cases.)
+#
+# This test was originally written to do it both ways, i.e. with both
+# both gdb_compile and gdb_compile_pthreads, but the point of this
+# test is to check that the link map address to TLS module id mapping
+# code works correctly in programs which use lots of dlopen and
+# dlclose calls in various orders - and that can be done using just
+# gdb_compile_pthreads.
+
+if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib_load \
+ shlib=${lib10obj} \
+ shlib=${lib11obj} \
+ additional_flags=-DOBJ1=\"${lib1obj}\" \
+ additional_flags=-DOBJ2=\"${lib2obj}\" \
+ additional_flags=-DOBJ3=\"${lib3obj}\" \
+ additional_flags=-DOBJ4=\"${lib4obj}\" \
+ ]] != "" } {
+ untested "failed to compile"
+} else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.c b/gdb/testsuite/gdb.base/tls-multiobj.c
new file mode 100644
index 0000000..10e67da
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj.c
@@ -0,0 +1,89 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+__thread int tls_main_tbss_1;
+__thread int tls_main_tbss_2;
+__thread int tls_main_tdata_1 = 96;
+__thread int tls_main_tdata_2 = 97;
+
+extern __thread int tls_lib1_tbss_1;
+extern __thread int tls_lib1_tbss_2;
+extern __thread int tls_lib1_tdata_1;
+extern __thread int tls_lib1_tdata_2;
+
+extern __thread int tls_lib2_tbss_1;
+extern __thread int tls_lib2_tbss_2;
+extern __thread int tls_lib2_tdata_1;
+extern __thread int tls_lib2_tdata_2;
+
+extern __thread int tls_lib3_tbss_1;
+extern __thread int tls_lib3_tbss_2;
+extern __thread int tls_lib3_tdata_1;
+extern __thread int tls_lib3_tdata_2;
+
+extern void lib1_func ();
+extern void lib2_func ();
+extern void lib3_func ();
+
+volatile int data;
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+int
+main (int argc, char **argv)
+{
+ use_it (-1);
+
+ tls_main_tbss_1 = 51; /* main-breakpoint-1 */
+ tls_main_tbss_2 = 52;
+ tls_main_tdata_1 = 53;
+ tls_main_tdata_2 = 54;
+
+ tls_lib1_tbss_1 = 151;
+ tls_lib1_tbss_2 = 152;
+ tls_lib1_tdata_1 = 153;
+ tls_lib1_tdata_2 = 154;
+
+ tls_lib2_tbss_1 = 251;
+ tls_lib2_tbss_2 = 252;
+ tls_lib2_tdata_1 = 253;
+ tls_lib2_tdata_2 = 254;
+
+ tls_lib3_tbss_1 = 351;
+ tls_lib3_tbss_2 = 352;
+ tls_lib3_tdata_1 = 353;
+ tls_lib3_tdata_2 = 354;
+
+ lib1_func ();
+ lib2_func ();
+ lib3_func ();
+
+ /* Attempt to keep variables in the main program from being optimized
+ away. */
+ use_it (tls_main_tbss_1);
+ use_it (tls_main_tbss_2);
+ use_it (tls_main_tdata_1);
+ use_it (tls_main_tdata_2);
+
+ use_it (100); /* main-breakpoint-2 */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj.exp b/gdb/testsuite/gdb.base/tls-multiobj.exp
new file mode 100644
index 0000000..97acb33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj.exp
@@ -0,0 +1,230 @@
+# Copyright 2024 Free Software Foundation, Inc.
+# 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.
+
+# Using different compilation/linking scenarios, attempt to access
+# thread-local variables in a non-threaded program using multiple
+# shared objects.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+standard_testfile
+
+set lib1src "${srcdir}/${subdir}/${testfile}1.c"
+set lib2src "${srcdir}/${subdir}/${testfile}2.c"
+set lib3src "${srcdir}/${subdir}/${testfile}3.c"
+
+set lib1obj [standard_output_file "${testfile}1-lib.so"]
+set lib2obj [standard_output_file "${testfile}2-lib.so"]
+set lib3obj [standard_output_file "${testfile}3-lib.so"]
+
+proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ if { $do_kfail_tls_access && [istarget "*-*-linux*"] } {
+ # Turn off do_kfail_tls_access when libthread_db is loaded.
+ # This can happen for the default case when testing x86_64
+ # w/ -m32 using glibc versions 2.34 or newer.
+ gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" {
+ -re -wrap "libthread_db integrity checks passed." {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "No libthread_db loaded" {
+ pass $gdb_test_name
+ }
+ }
+ # Also turn off do_kfail_tls_access when connected to a
+ # gdbserver and we observe that accessing a TLS variable
+ # works.
+ if [target_is_gdbserver] {
+ gdb_test_multiple "print tls_main_tbss_1" \
+ "Check TLS accessibility when connected to a gdbserver" {
+ -re -wrap "= 0" {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "Remote target failed to process qGetTLSAddr request" {
+ pass $gdb_test_name
+ }
+ }
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ set t $do_kfail_tls_access
+ set m "tls not available"
+ with_test_prefix "before assignments" {
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 96" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 97" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 196" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 197" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 296" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 297" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 396" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 397" $t $m
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "after assignments" {
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m
+ }
+
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test_with_kfail "print tls_main_tbss_1" ".* = 51" $t $m
+ gdb_test_with_kfail "print tls_main_tbss_2" ".* = 52" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_1" ".* = 53" $t $m
+ gdb_test_with_kfail "print tls_main_tdata_2" ".* = 54" $t $m
+
+ gdb_test_with_kfail "print tls_lib1_tbss_1" ".* = 151" $t $m
+ gdb_test_with_kfail "print tls_lib1_tbss_2" ".* = 152" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_1" ".* = 153" $t $m
+ gdb_test_with_kfail "print tls_lib1_tdata_2" ".* = 154" $t $m
+
+ gdb_test_with_kfail "print tls_lib2_tbss_1" ".* = 251" $t $m
+ gdb_test_with_kfail "print tls_lib2_tbss_2" ".* = 252" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_1" ".* = 253" $t $m
+ gdb_test_with_kfail "print tls_lib2_tdata_2" ".* = 254" $t $m
+
+ gdb_test_with_kfail "print tls_lib3_tbss_1" ".* = 351" $t $m
+ gdb_test_with_kfail "print tls_lib3_tbss_2" ".* = 352" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_1" ".* = 353" $t $m
+ gdb_test_with_kfail "print tls_lib3_tdata_2" ".* = 354" $t $m
+ }
+}
+
+if { [gdb_compile_shlib $lib1src $lib1obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $lib2src $lib2obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+if { [gdb_compile_shlib $lib3src $lib3obj {debug}] != "" } {
+ untested "failed to compile shared object"
+ return -1
+}
+
+# Certain linux target architectures implement support for internal
+# TLS lookup which is used when thread stratum support (via
+# libthread_db) is missing or when the linux-only GDB maintenance
+# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some
+# of the testing scenarios, such as statically linked executables,
+# this internal support will be used. Set 'do_kfail_tls_access' to 1
+# for those architectures which don't implement internal tls support.
+if {[istarget *-*-linux*]
+ && ![is_any_target {*}$internal_tls_linux_targets]} {
+ set do_kfail_tls_access 1
+} elseif {[istarget *-*-linux*] && [is_x86_like_target]} {
+ # This covers the case of x86_64 with -m32:
+ set do_kfail_tls_access 1
+} else {
+ set do_kfail_tls_access 0
+}
+
+set binprefix $binfile
+
+with_test_prefix "default" {
+ set binfile $binprefix-default
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib=${lib1obj} \
+ shlib=${lib2obj} \
+ shlib=${lib3obj}]] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ # Depending on glibc version, it might not be appropriate
+ # for do_kfail_tls_access to be set here. That will be
+ # handled in 'do_tests', disabling it if necessary.
+ #
+ # Specifically, glibc versions 2.34 and later have the
+ # thread library (and libthread_db availability) in
+ # programs not linked against libpthread.so
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "pthreads" {
+ set binfile $binprefix-pthreads
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+ [list debug shlib=${lib1obj} \
+ shlib=${lib2obj} \
+ shlib=${lib3obj}]] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+ }
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj1.c b/gdb/testsuite/gdb.base/tls-multiobj1.c
new file mode 100644
index 0000000..86e7222
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj1.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+__thread int tls_lib1_tbss_1;
+__thread int tls_lib1_tbss_2;
+__thread int tls_lib1_tdata_1 = 196;
+__thread int tls_lib1_tdata_2 = 197;
+
+void
+lib1_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj2.c b/gdb/testsuite/gdb.base/tls-multiobj2.c
new file mode 100644
index 0000000..cea0709
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj2.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+__thread int tls_lib2_tbss_1;
+__thread int tls_lib2_tbss_2;
+__thread int tls_lib2_tdata_1 = 296;
+__thread int tls_lib2_tdata_2 = 297;
+
+void
+lib2_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-multiobj3.c b/gdb/testsuite/gdb.base/tls-multiobj3.c
new file mode 100644
index 0000000..bb0f239
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-multiobj3.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+__thread int tls_lib3_tbss_1;
+__thread int tls_lib3_tbss_2;
+__thread int tls_lib3_tdata_1 = 396;
+__thread int tls_lib3_tdata_2 = 397;
+
+void
+lib3_func ()
+{
+}
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.c b/gdb/testsuite/gdb.base/tls-nothreads.c
new file mode 100644
index 0000000..b3aaa33
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-nothreads.c
@@ -0,0 +1,57 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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/>. */
+
+__thread int tls_tbss_1;
+__thread int tls_tbss_2;
+__thread int tls_tbss_3;
+
+__thread int tls_tdata_1 = 21;
+__thread int tls_tdata_2 = 22;
+__thread int tls_tdata_3 = 23;
+
+volatile int data;
+
+void
+use_it (int a)
+{
+ data = a;
+}
+
+int
+main (int argc, char **argv)
+{
+ use_it (-1);
+
+ tls_tbss_1 = 24; /* main-breakpoint-1 */
+ tls_tbss_2 = 25;
+ tls_tbss_3 = 26;
+
+ tls_tdata_1 = 42;
+ tls_tdata_2 = 43;
+ tls_tdata_3 = 44;
+
+ use_it (tls_tbss_1);
+ use_it (tls_tbss_2);
+ use_it (tls_tbss_3);
+ use_it (tls_tdata_1);
+ use_it (tls_tdata_2);
+ use_it (tls_tdata_3);
+
+ use_it (100); /* main-breakpoint-2 */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/tls-nothreads.exp b/gdb/testsuite/gdb.base/tls-nothreads.exp
new file mode 100644
index 0000000..92a5cd9
--- /dev/null
+++ b/gdb/testsuite/gdb.base/tls-nothreads.exp
@@ -0,0 +1,248 @@
+# Copyright 2024 Free Software Foundation, Inc.
+# 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.
+
+# Using different compilation/linking scenarios, attempt to access
+# thread-local variables in a non-threaded program. Also test that
+# GDB internal TLS lookup works correctly.
+
+source $srcdir/$subdir/tls-common.exp.tcl
+
+standard_testfile
+
+proc do_tests {force_internal_tls {do_kfail_tls_access 0}} {
+ clean_restart $::binfile
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ if { $do_kfail_tls_access && [istarget "*-*-linux*"] } {
+ # Turn off do_kfail_tls_access when libthread_db is loaded.
+ # This can happen for the default case when testing x86_64
+ # w/ -m32 using glibc versions 2.34 or newer.
+ gdb_test_multiple "maint check libthread-db" "Check for loaded libthread_db" {
+ -re -wrap "libthread_db integrity checks passed." {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "No libthread_db loaded" {
+ pass $gdb_test_name
+ }
+ }
+ # Also turn off do_kfail_tls_access when connected to a
+ # gdbserver and we observe that accessing a TLS variable
+ # works.
+ if [target_is_gdbserver] {
+ gdb_test_multiple "print tls_tbss_1" "Check TLS accessibility when connected to a gdbserver" {
+ -re -wrap "= 0" {
+ set do_kfail_tls_access 0
+ pass $gdb_test_name
+ }
+ -re -wrap "Remote target failed to process qGetTLSAddr request" {
+ pass $gdb_test_name
+ }
+ }
+ }
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-1"]
+ gdb_continue_to_breakpoint "main-breakpoint-1"
+
+ set t $do_kfail_tls_access
+ set m "tls not available"
+ with_test_prefix "before assignments" {
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 0" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 0" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 21" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 22" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 23" $t $m
+ }
+
+ gdb_breakpoint [gdb_get_line_number "main-breakpoint-2"]
+ gdb_continue_to_breakpoint "main-breakpoint-2"
+
+ with_test_prefix "after assignments" {
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m
+ }
+
+ # Make a core file now, but save testing using it until the end
+ # in case core files are not supported.
+ set corefile ${::binfile}.core
+ set core_supported 0
+ if { ![is_remote host] } {
+ set core_supported [gdb_gcore_cmd $corefile "save corefile"]
+ }
+
+ # Now continue to end and see what happens when attempting to
+ # access a TLS variable when the program is no longer running.
+ gdb_continue_to_end
+ with_test_prefix "after exit" {
+ gdb_test "print tls_tbss_1" \
+ "Cannot (?:read|find address of TLS symbol) `tls_tbss_1' without registers"
+ }
+
+ with_test_prefix "stripped" {
+ set binfile_stripped "${::binfile}.stripped"
+ set objcopy [gdb_find_objcopy]
+ set cmd "$objcopy --strip-debug ${::binfile} $binfile_stripped"
+ if ![catch "exec $cmd" cmd_output] {
+ clean_restart $binfile_stripped
+ if ![runto_main] {
+ return
+ }
+
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ # While there are no debug (e.g. DWARF) symbols, there
+ # are minimal symbols, so we should be able to place a
+ # breakpoint in use_it and continue to it. Continuing
+ # twice should put us past the assignments, at which point
+ # we can see if the TLS variables are still accessible.
+ gdb_test "break use_it" "Breakpoint 2 at $::hex"
+ gdb_test "continue" "Breakpoint 2, $::hex in use_it.*"
+ gdb_test "continue" "Breakpoint 2, $::hex in use_it.*" "continue 2"
+
+ # Note that a cast has been added in order to avoid the
+ # "...has unknown type; cast it to its declared type"
+ # problem.
+ gdb_test_with_kfail "print (int) tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print (int) tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print (int) tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print (int) tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print (int) tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print (int) tls_tdata_3" ".* = 44" $t $m
+
+ # Get rid of the "use_it" breakpoint
+ gdb_test_no_output "del 2"
+
+ # Continue to program exit
+ gdb_continue_to_end
+
+ # TLS variables should not be accessible after program exit
+ # (This case initially caused GDB to crash during development
+ # of GDB-internal TLS lookup support.)
+ with_test_prefix "after exit" {
+ gdb_test "print (int) tls_tbss_1" \
+ "Cannot find address of TLS symbol `tls_tbss_1' without registers"
+ }
+ }
+ }
+
+ # Finish test early if no core file was made.
+ if !$core_supported {
+ return
+ }
+
+ clean_restart $::binfile
+
+ set core_loaded [gdb_core_cmd $corefile "load corefile"]
+ if { $core_loaded == -1 } {
+ return
+ }
+
+ with_test_prefix "core file" {
+ if $force_internal_tls {
+ gdb_test_no_output "maint set force-internal-tls-address-lookup on"
+ }
+
+ gdb_test_with_kfail "print tls_tbss_1" ".* = 24" $t $m
+ gdb_test_with_kfail "print tls_tbss_2" ".* = 25" $t $m
+ gdb_test_with_kfail "print tls_tbss_3" ".* = 26" $t $m
+
+ gdb_test_with_kfail "print tls_tdata_1" ".* = 42" $t $m
+ gdb_test_with_kfail "print tls_tdata_2" ".* = 43" $t $m
+ gdb_test_with_kfail "print tls_tdata_3" ".* = 44" $t $m
+ }
+}
+
+# Certain linux target architectures implement support for internal
+# TLS lookup which is used when thread stratum support (via
+# libthread_db) is missing or when the linux-only GDB maintenance
+# setting 'force-internal-tls-address-lookup' is 'on'. Thus for some
+# of the testing scenarios, such as statically linked executables,
+# this internal support will be used. Set 'do_kfail_tls_access' to 1
+# for those architectures which don't implement internal TLS support.
+if {[istarget *-*-linux*]
+ && ![is_any_target {*}$internal_tls_linux_targets]} {
+ set do_kfail_tls_access 1
+} elseif {[istarget *-*-linux*] && [is_x86_like_target]} {
+ # This covers the case of x86_64 with -m32:
+ set do_kfail_tls_access 1
+} else {
+ set do_kfail_tls_access 0
+}
+
+set binprefix $binfile
+
+with_test_prefix "default" {
+ set binfile $binprefix-default
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ # Depending on glibc version, it might not be appropriate
+ # for do_kfail_tls_access to be set here. That will be
+ # handled in 'do_tests', disabling it if necessary.
+ #
+ # Specifically, glibc versions 2.34 and later have the
+ # thread library (and libthread_db availability) in
+ # programs not linked against libpthread.so
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "static" {
+ set binfile $binprefix-static
+ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}
+
+with_test_prefix "pthreads" {
+ set binfile $binprefix-pthreads
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls
+ }
+ }
+}
+
+with_test_prefix "pthreads-static" {
+ set binfile $binprefix-pthreads-static
+ if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-static"}] != "" } {
+ untested "failed to compile"
+ } else {
+ foreach_with_prefix force_internal_tls $internal_tls_iters {
+ do_tests $force_internal_tls $do_kfail_tls_access
+ }
+ }
+}