]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.debuginfod/fetch_src_and_symbols.exp
gdb/debuginfod: Prevent out_of_range exception
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.debuginfod / fetch_src_and_symbols.exp
CommitLineData
4a94e368 1# Copyright 2020-2022 Free Software Foundation, Inc.
0d79cdc4
AM
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16# Test debuginfod functionality
17
18standard_testfile main.c
19
20load_lib dwarf.exp
21
22if { [which debuginfod] == 0 } {
23 untested "cannot find debuginfod"
24 return -1
25}
26
27if { [which curl] == 0 } {
28 untested "cannot find curl"
29 return -1
30}
31
32# Skip testing if gdb was not configured with debuginfod
f0bbba78
SM
33#
34# If GDB is built with ASan, it warns that some signal handlers (installed by
35# ASan) exist on startup. That makes TCL's exec throw an error. Disable that
36# by passing --quiet.
37
43327b20 38if { [string first "with-debuginfod" \
f0bbba78 39 [eval exec $GDB --quiet $INTERNAL_GDBFLAGS --configuration]] == -1 } {
0d79cdc4
AM
40 untested "gdb not configured with debuginfod"
41 return -1
42}
43
44set cache [standard_output_file ".client_cache"]
45set db [standard_output_file ".debuginfod.db"]
46
47# Delete any preexisting test files
48file delete -force $cache
49file delete -force $db
50
51set sourcetmp [standard_output_file tmp-${srcfile}]
52set outputdir [standard_output_file {}]
53
54# Make a copy source file that we can move around
55if { [catch {file copy -force ${srcdir}/${subdir}/${srcfile} \
56 [standard_output_file ${sourcetmp}]}] != 0 } {
57 error "create temporary file"
58 return -1
59}
60
61if { [gdb_compile "$sourcetmp" "$binfile" executable {debug}] != "" } {
7264ba83 62 untested "failed to compile"
0d79cdc4
AM
63 return -1
64}
65
b91f93a0
AM
66if { [gdb_compile "$sourcetmp" "${binfile}2" executable {debug}] != "" } {
67 fail "compile"
68 return -1
69}
70
0d79cdc4
AM
71# Write some assembly that just has a .gnu_debugaltlink section.
72# Copied from testsuite/gdb.dwarf2/dwzbuildid.exp.
73proc write_just_debugaltlink {filename dwzname buildid} {
74 set asm_file [standard_output_file $filename]
75
76 Dwarf::assemble $asm_file {
77 upvar dwzname dwzname
78 upvar buildid buildid
79
80 gnu_debugaltlink $dwzname $buildid
81
82 # Only the DWARF reader checks .gnu_debugaltlink, so make sure
83 # there is a bit of DWARF in here.
84 cu {} {
85 compile_unit {{language @DW_LANG_C}} {
86 }
87 }
88 }
89}
90
91# Write some DWARF that also sets the buildid.
92# Copied from testsuite/gdb.dwarf2/dwzbuildid.exp.
93proc write_dwarf_file {filename buildid {value 99}} {
94 set asm_file [standard_output_file $filename]
95
96 Dwarf::assemble $asm_file {
97 declare_labels int_label int_label2
98
99 upvar buildid buildid
100 upvar value value
101
102 build_id $buildid
103
104 cu {} {
105 compile_unit {{language @DW_LANG_C}} {
bd460ecb 106 int_label2: base_type {
0d79cdc4
AM
107 {name int}
108 {byte_size 4 sdata}
109 {encoding @DW_ATE_signed}
110 }
111
112 constant {
113 {name the_int}
114 {type :$int_label2}
115 {const_value $value data1}
116 }
117 }
118 }
119 }
120}
121
b91f93a0
AM
122set corefile [standard_output_file "corefile"]
123
bd460ecb
TV
124proc no_url { } {
125 global binfile outputdir debugdir
0d79cdc4 126
bd460ecb 127 setenv DEBUGINFOD_URLS ""
0d79cdc4 128
bd460ecb
TV
129 # Test that gdb cannot find source without debuginfod
130 clean_restart $binfile
131 gdb_test_no_output "set substitute-path $outputdir /dev/null" \
132 "set substitute-path"
133 gdb_test "list" ".*No such file or directory.*"
0d79cdc4 134
bd460ecb
TV
135 # Strip symbols into separate file and move it so gdb cannot find it \
136 without debuginfod
137 if { [gdb_gnu_strip_debug $binfile ""] != 0 } {
138 fail "strip debuginfo"
139 return -1
140 }
0d79cdc4 141
bd460ecb
TV
142 set debugdir [standard_output_file "debug"]
143 set debuginfo [standard_output_file "fetch_src_and_symbols.debug"]
0d79cdc4 144
bd460ecb
TV
145 file mkdir $debugdir
146 file rename -force $debuginfo $debugdir
0d79cdc4 147
bd460ecb
TV
148 # Test that gdb cannot find symbols without debuginfod
149 clean_restart $binfile
150 gdb_test "file" ".*No symbol file.*"
151
152 set buildid "01234567890abcdef0123456"
153
154 write_just_debugaltlink ${binfile}_has_altlink.S ${binfile}_dwz.o \
155 $buildid
156 write_dwarf_file ${binfile}_dwz.S $buildid
157
158 if {[gdb_compile ${binfile}_has_altlink.S ${binfile}_alt.o object \
159 nodebug] != ""} {
160 fail "compile main with altlink"
161 return -1
0d79cdc4 162 }
0d79cdc4 163
bd460ecb
TV
164 if {[gdb_compile ${binfile}_dwz.S ${binfile}_dwz.o object \
165 nodebug] != ""} {
166 fail "compile altlink"
167 return -1
168 }
169
170 file rename -force ${binfile}_dwz.o $debugdir
0d79cdc4 171
bd460ecb
TV
172 # Test that gdb cannot find dwz without debuginfod.
173 clean_restart
174 gdb_test "file ${binfile}_alt.o" \
175 ".*could not find '.gnu_debugaltlink'.*" \
176 "file [file tail ${binfile}_alt.o]"
b91f93a0
AM
177
178 # Generate a core file and test that gdb cannot find the executable
179 clean_restart ${binfile}2
180 gdb_test "start" "Temporary breakpoint.*"
181 gdb_test "generate-core-file $::corefile" "Saved corefile $::corefile" \
182 "file [file tail $::corefile] gen"
183 file rename -force ${binfile}2 $debugdir
184
185 clean_restart
186 gdb_test "core $::corefile" ".*in ?? ().*" "file [file tail $::corefile]"
bd460ecb
TV
187}
188
52449404
AM
189# Test that GDB prints the debuginfod URLs when loading files. URLS
190# is the string set in the DEBUGINFOD_URLS environment variable.
191# PATTERN_RE is the URLs pattern we expect to see out of GDB. TEST is
192# the test name.
193
194proc test_urls {urls pattern_re test} {
195 setenv DEBUGINFOD_URLS $urls
196 clean_restart
197
198 if {$pattern_re != ""} {
199 set urls_re " +${pattern_re}\r\n"
200 } else {
201 set urls_re ""
202 }
203
204 # Use "with confirm off" to avoid having to deal with the
205 # "Enable debuginfod for this session? (y or [n])" question.
206 gdb_test "with confirm off -- file $::binfile" \
207 "following URLs:\r\n${urls_re}Debuginfod .*" \
208 $test
209}
210
bd460ecb
TV
211proc local_url { } {
212 global binfile outputdir db debugdir
213
214 # Find an unused port
215 set port 7999
216 set found 0
217 while { ! $found } {
218 incr port
219 if { $port == 65536 } {
220 fail "no available ports"
221 return -1
222 }
0d79cdc4 223
bd460ecb
TV
224 spawn debuginfod -vvvv -d $db -p $port -F $debugdir
225 expect {
226 "started http server on IPv4 IPv6 port=$port" { set found 1 }
35da8c61
TV
227 "started http server on IPv4 port=$port" { set found 1 }
228 "started http server on IPv6 port=$port" {}
229 "failed to bind to port" {}
bd460ecb
TV
230 timeout {
231 fail "find port timeout"
232 return -1
233 }
234 }
35da8c61
TV
235 if { ! $found } {
236 kill_wait_spawned_process $spawn_id
237 }
0d79cdc4
AM
238 }
239
bd460ecb
TV
240 set metrics [list "ready 1" \
241 "thread_work_total{role=\"traverse\"} 1" \
242 "thread_work_pending{role=\"scan\"} 0" \
243 "thread_busy{role=\"scan\"} 0"]
0d79cdc4 244
bd460ecb
TV
245 # Check server metrics to confirm init has completed.
246 foreach m $metrics {
247 set timelim 20
248 while { $timelim != 0 } {
249 sleep 0.5
250 catch {exec curl -s http://127.0.0.1:$port/metrics} got
251
252 if { [regexp $m $got] } {
253 break
254 }
255
256 incr timelim -1
257 }
258
259 if { $timelim == 0 } {
260 fail "server init timeout"
261 return -1
262 }
263 }
264
265 # Point the client to the server
266 setenv DEBUGINFOD_URLS http://127.0.0.1:$port
267
268 # gdb should now find the symbol and source files
7811fa59
AM
269 clean_restart
270 gdb_test "file $binfile" "" "file [file tail $binfile]" "Enable debuginfod?.*" "y"
bd460ecb
TV
271 gdb_test_no_output "set substitute-path $outputdir /dev/null" \
272 "set substitute-path"
273 gdb_test "br main" "Breakpoint 1 at.*file.*"
274 gdb_test "l" ".*This program is distributed in the hope.*"
275
b91f93a0
AM
276 # gdb should now find the executable file
277 clean_restart
278 gdb_test "core $::corefile" ".*return 0.*" "file [file tail $::corefile]" \
279 "Enable debuginfod?.*" "y"
280
bd460ecb
TV
281 # gdb should now find the debugaltlink file
282 clean_restart
283 gdb_test "file ${binfile}_alt.o" \
7811fa59
AM
284 ".*Downloading.*separate debug info.*" \
285 "file [file tail ${binfile}_alt.o]" \
286 ".*Enable debuginfod?.*" "y"
287
288 # Configure debuginfod with commands
289 unsetenv DEBUGINFOD_URLS
290 clean_restart
291 gdb_test "file $binfile" ".*No debugging symbols.*" \
292 "file [file tail $binfile] cmd"
333f35b6 293 gdb_test_no_output "set debuginfod enabled off"
7811fa59
AM
294 gdb_test_no_output "set debuginfod urls http://127.0.0.1:$port"
295
296 # gdb shouldn't find the debuginfo since debuginfod has been disabled
297 gdb_test "file $binfile" ".*No debugging symbols.*" \
298 "file [file tail $binfile] cmd off"
299
300 # Enable debuginfod and fetch the debuginfo
333f35b6 301 gdb_test_no_output "set debuginfod enabled on"
7811fa59
AM
302 gdb_test "file $binfile" ".*Reading symbols from.*debuginfo.*" \
303 "file [file tail $binfile] cmd on"
52449404
AM
304
305 # Test that URLs are printed correctly for the first-use notice.
306
307 # Empty URLS disables Debuginfod.
308 setenv DEBUGINFOD_URLS ""
309 clean_restart
310 # Disable confirmation to avoid having to deal with a query. See
311 # test_urls.
312 gdb_test_multiple "with confirm off -- file $binfile" "notice empty URL" {
313 -re ".*Enable debuginfod.*" {
314 fail $gdb_test_name
315 }
316 -re -wrap "" {
317 pass $gdb_test_name
318 }
319 }
320
321 test_urls " " \
322 "" \
323 "notice whitespace URL"
324
325 set url "http://127.0.0.1:$port"
326
327 test_urls $url \
328 "<$url>" \
329 "notice 1 URL"
330
331 test_urls " $url " \
332 "<$url>" \
333 "notice 1 URL with whitespace"
334
335 set url2 "127.0.0.1:$port"
336
337 test_urls "$url $url2" \
338 "<$url>\r\n +<$url2>" \
339 "notice 2 URLs"
340
341 test_urls " $url $url2 " \
342 "<$url>\r\n +<$url2>" \
343 "notice 2 URLs with whitespace"
0d79cdc4
AM
344}
345
bd460ecb
TV
346set envlist \
347 [list \
348 env(DEBUGINFOD_URLS) \
349 env(DEBUGINFOD_TIMEOUT) \
350 env(DEBUGINFOD_CACHE_PATH)]
0d79cdc4 351
bd460ecb
TV
352save_vars $envlist {
353 setenv DEBUGINFOD_TIMEOUT 30
354 setenv DEBUGINFOD_CACHE_PATH $cache
0d79cdc4 355
bd460ecb
TV
356 with_test_prefix no_url no_url
357
358 with_test_prefix local_url local_url
359}