1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
}
}
}
|