New test - gdb.base/tls-dlobj.exp

This test exercises musl_link_map_to_tls_module_id() and
glibc_link_map_to_tls_module_id(), both of which are in solib-svr4.c.

Prior to writing this test, I had only written what is now named
'musl_link_map_to_tls_module_id' and it worked for both GLIBC and
MUSL.  Once I wrote this new test, tls-dlobj.exp, there were a number
of tests which didn't work with GLIBC.  This led me to write a
GLIBC-specific link map to module id function, i.e,
'glibc_link_map_to_tls_module_id'.

It only has one compilation scenario, in which the pthread(s) library
is used - as noted in a comment, it became too much of a hassle to try
to KFAIL things, though it certainly could have been done in much the
same was as was done in gdb.base/multiobj.exp.  It didn't seem that
important to do so, however, since I believe that the other tests
have adequate coverage for different compilation scenarios.

Tested-By: Luis Machado <luis.machado@arm.com>
Approved-By: Luis Machado <luis.machado@arm.com>
This commit is contained in:
Kevin Buettner
2025-04-23 21:39:29 -07:00
parent b0789fb6c2
commit e4a5126ec0
3 changed files with 776 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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
}
}