]>
Commit | Line | Data |
---|---|---|
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 | ||
18 | standard_testfile main.c | |
19 | ||
20 | load_lib dwarf.exp | |
21 | ||
22 | if { [which debuginfod] == 0 } { | |
23 | untested "cannot find debuginfod" | |
24 | return -1 | |
25 | } | |
26 | ||
27 | if { [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 | 38 | if { [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 | ||
44 | set cache [standard_output_file ".client_cache"] | |
45 | set db [standard_output_file ".debuginfod.db"] | |
46 | ||
47 | # Delete any preexisting test files | |
48 | file delete -force $cache | |
49 | file delete -force $db | |
50 | ||
51 | set sourcetmp [standard_output_file tmp-${srcfile}] | |
52 | set outputdir [standard_output_file {}] | |
53 | ||
54 | # Make a copy source file that we can move around | |
55 | if { [catch {file copy -force ${srcdir}/${subdir}/${srcfile} \ | |
56 | [standard_output_file ${sourcetmp}]}] != 0 } { | |
57 | error "create temporary file" | |
58 | return -1 | |
59 | } | |
60 | ||
61 | if { [gdb_compile "$sourcetmp" "$binfile" executable {debug}] != "" } { | |
7264ba83 | 62 | untested "failed to compile" |
0d79cdc4 AM |
63 | return -1 |
64 | } | |
65 | ||
b91f93a0 AM |
66 | if { [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. | |
73 | proc 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. | |
93 | proc 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 |
122 | set corefile [standard_output_file "corefile"] |
123 | ||
bd460ecb TV |
124 | proc 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 | ||
194 | proc 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 |
211 | proc 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" { | |
9cf71b13 | 313 | -re -wrap "This GDB supports auto-downloading.*" { |
52449404 AM |
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 |
346 | set envlist \ |
347 | [list \ | |
348 | env(DEBUGINFOD_URLS) \ | |
349 | env(DEBUGINFOD_TIMEOUT) \ | |
350 | env(DEBUGINFOD_CACHE_PATH)] | |
0d79cdc4 | 351 | |
bd460ecb TV |
352 | save_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 | } |