1# tls.exp -- Expect script to test thread-local storage 2# Copyright (C) 1992-2020 Free Software Foundation, Inc. 3 4# This program is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17load_lib gdb-python.exp 18 19standard_testfile tls.c tls2.c 20 21if [istarget "*-*-linux"] then { 22 set target_cflags "-D_MIT_POSIX_THREADS" 23} else { 24 set target_cflags "" 25} 26 27if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile2}" "${binfile}" executable [list c++ debug]] != "" } { 28 return -1 29} 30 31### Compute the value of the a_thread_local variable. 32proc compute_expected_value {value} { 33 set expected_value 0 34 set i 0 35 while { $i <= $value} { 36 incr expected_value $i 37 incr i 38 } 39 return $expected_value 40} 41 42### Get the value of the variable 'me' for the current thread. 43proc get_me_variable {tnum} { 44 global expect_out 45 global gdb_prompt 46 global decimal 47 48 set value_of_me -1 49 send_gdb "print me\n" 50 gdb_expect { 51 -re ".*= ($decimal).*\r\n$gdb_prompt $" { 52 set value_of_me $expect_out(1,string) 53 pass "$tnum thread print me" 54 } 55 -re "$gdb_prompt $" { 56 fail "$tnum thread print me" 57 } 58 timeout { 59 fail "$tnum thread print me (timeout)" 60 } 61 } 62 return ${value_of_me} 63} 64 65### Check the values of the thread local variables in the thread. 66### Also check that info address print the right things. 67proc check_thread_local {number} { 68 set me_variable [get_me_variable $number] 69 set expected_value [compute_expected_value ${me_variable}] 70 71 gdb_test "p a_thread_local" \ 72 "= $expected_value" \ 73 "${number} thread local storage" 74 75 if {![skip_python_tests]} { 76 gdb_test_no_output \ 77 "python sym = gdb.lookup_symbol('a_thread_local')\[0\]" \ 78 "${number} look up a_thread_local symbol" 79 # We intentionally do not pass a frame to "value" here. If a 80 # TLS variable requires a frame, this will fail. However, if 81 # it does not require a frame, then it will succeed. 82 gdb_test "python print(sym.value())" "$expected_value" \ 83 "${number} get symbol value without frame" 84 } 85 86 gdb_test "p K::another_thread_local" \ 87 "= $me_variable" \ 88 "${number} another thread local storage" 89 90 gdb_test "info address a_thread_local" \ 91 ".*a_thread_local.*a thread-local variable at offset.*" \ 92 "${number} info address a_thread_local" 93 94 gdb_test "info address K::another_thread_local" \ 95 ".*another_thread_local.*a thread-local variable at offset.*" \ 96 "${number} info address another_thread_local" 97} 98 99### Select a particular thread. 100proc select_thread {thread} { 101 global gdb_prompt 102 103 send_gdb "thread $thread\n" 104 gdb_expect { 105 -re "\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" { 106 pass "selected thread: $thread" 107 } 108 -re "$gdb_prompt $" { 109 fail "selected thread: $thread" 110 } 111 timeout { 112 fail "selected thread: $thread (timeout)" 113 } 114 } 115} 116 117### Do a backtrace for the current thread, and check that the 'spin' routine 118### is in it. This means we have one of the threads we created, rather 119### than the main thread. Record the thread in the spin_threads 120### array. Also remember the level of the 'spin' routine in the backtrace, for 121### later use. 122proc check_thread_stack {number spin_threads spin_threads_level} { 123 global gdb_prompt 124 global expect_out 125 global decimal 126 global hex 127 upvar $spin_threads tarr 128 upvar $spin_threads_level tarrl 129 130 select_thread $number 131 send_gdb "where\n" 132 gdb_expect { 133 -re ".*(\[0-9\]+)\[ \t\]+$hex in spin \\(vp=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" { 134 if {[info exists tarr($number)]} { 135 fail "backtrace of thread number $number in spin" 136 } else { 137 pass "backtrace of thread number $number in spin" 138 set level $expect_out(1,string) 139 set tarrl($number) $level 140 set tarr($number) 1 141 } 142 } 143 -re ".*$gdb_prompt $" { 144 set tarr($number) 0 145 set tarrl($number) 0 146 pass "backtrace of thread number $number not relevant" 147 } 148 timeout { 149 fail "backtrace of thread number $number (timeout)" 150 } 151 } 152} 153 154clean_restart ${binfile} 155 156gdb_test_multiple "print a_thread_local" "" { 157 -re -wrap "Cannot find thread-local variables on this target" { 158 kfail "gdb/25807" $gdb_test_name 159 } 160 -re -wrap "Cannot read .a_thread_local. without registers" { 161 pass $gdb_test_name 162 } 163} 164 165if ![runto_main] then { 166 fail "can't run to main" 167 return 0 168} 169 170# Set a breakpoint at the "spin" routine to 171# test the thread local's value. 172# 173gdb_test "b [gdb_get_line_number "here we know tls value"]" \ 174 ".*Breakpoint 2.*tls.*" "set breakpoint at all threads" 175 176# Set a bp at a point where we know all threads are alive. 177# 178gdb_test "b [gdb_get_line_number "still alive"]" \ 179 ".*Breakpoint 3.*tls.*" "set breakpoint at synch point" 180 181# Set a bp at the end to see if all threads are finished. 182# 183gdb_test "b [gdb_get_line_number "before exit"]" \ 184 ".*Breakpoint 4.*tls.*" "set breakpoint at exit" 185 186send_gdb "continue\n" 187gdb_expect { 188 -re ".* received signal SIGSEGV.*a_thread_local = 0;.*$gdb_prompt $" { 189 # This is the first symptom if the gcc and binutils versions 190 # in use support TLS, but the system glibc does not. 191 unsupported "continue to first thread: system does not support TLS" 192 return -1 193 } 194 -re ".*$inferior_exited_re normally.*$gdb_prompt $" { 195 fail "continue to first thread: program runaway" 196 } 197 -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" { 198 fail "continue to first thread: program runaway 2" 199 } 200 -re ".*Breakpoint 2.*tls value.*$gdb_prompt $" { 201 pass "continue to first thread: get to thread" 202 } 203 -re ".*$gdb_prompt $" { 204 fail "continue to first thread: no progress?" 205 } 206 timeout { fail "continue to first thread (timeout)" } 207} 208 209gdb_test "info thread" ".*Thread.*spin.*" \ 210 "at least one th in spin while stopped at first th" 211 212check_thread_local "first" 213 214gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to second thread" 215gdb_test "info thread" "Thread.*spin.*" \ 216 "at least one th in spin while stopped at second th" 217 218check_thread_local "second" 219 220gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to third thread" 221gdb_test "info thread" ".*Thread.*spin.*" \ 222 "at least one th in spin while stopped at third th" 223 224check_thread_local "third" 225 226gdb_test "continue" ".*Breakpoint 3.*still alive.*" "continue to synch point" 227 228set no_of_threads 0 229send_gdb "info thread\n" 230gdb_expect { 231 -re "^info thread\[ \t\r\n\]+ *Id .*Frame\[ \t\r\n\]+.*(\[0-9\]+) *Thread\[^\r\n\]+\r\n$gdb_prompt $" { 232 set no_of_threads $expect_out(1,string) 233 pass "get number of threads" 234 } 235 -re "$gdb_prompt $" { 236 fail "get number of threads" 237 } 238 timeout { 239 fail "get number of threads (timeout)" 240 } 241} 242 243array set spin_threads {} 244unset spin_threads 245array set spin_threads_level {} 246unset spin_threads_level 247 248# For each thread check its backtrace to see if it is stopped at the 249# spin routine. 250for {set i 1} {$i <= $no_of_threads} {incr i} { 251 check_thread_stack $i spin_threads spin_threads_level 252} 253 254### Loop through the threads and check the values of the tls variables. 255### keep track of how many threads we find in the spin routine. 256set thrs_in_spin 0 257foreach i [array names spin_threads] { 258 if {$spin_threads($i) == 1} { 259 incr thrs_in_spin 260 select_thread $i 261 set level $spin_threads_level($i) 262 # We expect to be in sem_wait, but if the thread has not yet 263 # been scheduled, we might be in sem_post still. We could be at 264 # any intermediate point in spin, too, but that is much less 265 # likely. 266 gdb_test "up $level" ".*spin.*sem_(wait|post).*" "thread $i up" 267 check_thread_local $i 268 } 269} 270 271if {$thrs_in_spin == 0} { 272 fail "no thread backtrace reported spin (vsyscall kernel problem?)" 273} 274 275gdb_test "continue" ".*Breakpoint 4.*before exit.*" "threads exited" 276 277send_gdb "info thread\n" 278gdb_expect { 279 -re ".* 1 *Thread.*2 *Thread.*$gdb_prompt $" { 280 fail "too many threads left at end" 281 } 282 -re ".*\\\* 1 *Thread.*main.*$gdb_prompt $" { 283 pass "expect only base thread at end" 284 } 285 -re ".*No stack.*$gdb_prompt $" { 286 fail "runaway at end" 287 } 288 -re ".*$gdb_prompt $" { 289 fail "mess at end" 290 } 291 timeout { fail "at end (timeout)" } 292} 293 294# Start over and do some "info address" stuff 295# 296runto spin 297 298gdb_test "info address a_global" \ 299 ".*a_global.*static storage at address.*" 300 301gdb_test "info address me" ".*me.*is a (complex DWARF expression:|variable).*" 302 303 304# Test LOC_UNRESOLVED references resolving for `extern' TLS variables. 305 306gdb_test "p a_thread_local" " = \[0-9\]+" 307# Here it could crash with: Cannot access memory at address 0x0 308gdb_test "p file2_thread_local" " = \[0-9\]+" 309# Depending on the current lookup scope we get LOC_UNRESOLVED or LOC_COMPUTED 310# both printing: 311# Symbol "file2_thread_local" is a thread-local variable at offset 8 in the thread-local storage for `.../gdb.threads/tls'. 312gdb_test "info address file2_thread_local" "Symbol \"file2_thread_local\" is a thread-local variable.*" 313# Here it could also crash with: Cannot access memory at address 0x0 314gdb_test "p a_thread_local" " = \[0-9\]+" "p a_thread_local second time" 315gdb_test "info address a_thread_local" "Symbol \"a_thread_local\" is a thread-local variable.*" 316 317# Done! 318# 319gdb_exit 320 321return 0 322