Commit | Line | Data |
---|---|---|
0d79cdc4 AM |
1 | # Copyright 2020 Free Software Foundation, Inc. |
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 | |
33 | if { [string first "with-debuginfod" [exec $GDB --configuration]] == -1 } { | |
34 | untested "gdb not configured with debuginfod" | |
35 | return -1 | |
36 | } | |
37 | ||
38 | set cache [standard_output_file ".client_cache"] | |
39 | set db [standard_output_file ".debuginfod.db"] | |
40 | ||
41 | # Delete any preexisting test files | |
42 | file delete -force $cache | |
43 | file delete -force $db | |
44 | ||
45 | set sourcetmp [standard_output_file tmp-${srcfile}] | |
46 | set outputdir [standard_output_file {}] | |
47 | ||
48 | # Make a copy source file that we can move around | |
49 | if { [catch {file copy -force ${srcdir}/${subdir}/${srcfile} \ | |
50 | [standard_output_file ${sourcetmp}]}] != 0 } { | |
51 | error "create temporary file" | |
52 | return -1 | |
53 | } | |
54 | ||
55 | if { [gdb_compile "$sourcetmp" "$binfile" executable {debug}] != "" } { | |
56 | fail "compile" | |
57 | return -1 | |
58 | } | |
59 | ||
60 | setenv DEBUGINFOD_URLS "" | |
61 | setenv DEBUGINFOD_TIMEOUT 30 | |
62 | setenv DEBUGINFOD_CACHE_PATH $cache | |
63 | ||
64 | # Test that gdb cannot find source without debuginfod | |
65 | clean_restart $binfile | |
66 | gdb_test_no_output "set substitute-path $outputdir /dev/null" | |
67 | gdb_test "list" ".*No such file or directory.*" | |
68 | ||
69 | # Strip symbols into separate file and move it so gdb cannot find it without debuginfod | |
70 | if { [gdb_gnu_strip_debug $binfile ""] != 0 } { | |
71 | fail "strip debuginfo" | |
72 | return -1 | |
73 | } | |
74 | ||
75 | set debugdir [standard_output_file "debug"] | |
76 | set debuginfo [standard_output_file "fetch_src_and_symbols.debug"] | |
77 | ||
78 | file mkdir $debugdir | |
79 | file rename -force $debuginfo $debugdir | |
80 | ||
81 | # Test that gdb cannot find symbols without debuginfod | |
82 | clean_restart $binfile | |
83 | gdb_test "file" ".*No symbol file.*" | |
84 | ||
85 | # Write some assembly that just has a .gnu_debugaltlink section. | |
86 | # Copied from testsuite/gdb.dwarf2/dwzbuildid.exp. | |
87 | proc write_just_debugaltlink {filename dwzname buildid} { | |
88 | set asm_file [standard_output_file $filename] | |
89 | ||
90 | Dwarf::assemble $asm_file { | |
91 | upvar dwzname dwzname | |
92 | upvar buildid buildid | |
93 | ||
94 | gnu_debugaltlink $dwzname $buildid | |
95 | ||
96 | # Only the DWARF reader checks .gnu_debugaltlink, so make sure | |
97 | # there is a bit of DWARF in here. | |
98 | cu {} { | |
99 | compile_unit {{language @DW_LANG_C}} { | |
100 | } | |
101 | } | |
102 | } | |
103 | } | |
104 | ||
105 | # Write some DWARF that also sets the buildid. | |
106 | # Copied from testsuite/gdb.dwarf2/dwzbuildid.exp. | |
107 | proc write_dwarf_file {filename buildid {value 99}} { | |
108 | set asm_file [standard_output_file $filename] | |
109 | ||
110 | Dwarf::assemble $asm_file { | |
111 | declare_labels int_label int_label2 | |
112 | ||
113 | upvar buildid buildid | |
114 | upvar value value | |
115 | ||
116 | build_id $buildid | |
117 | ||
118 | cu {} { | |
119 | compile_unit {{language @DW_LANG_C}} { | |
120 | int_label2: base_type { | |
121 | {name int} | |
122 | {byte_size 4 sdata} | |
123 | {encoding @DW_ATE_signed} | |
124 | } | |
125 | ||
126 | constant { | |
127 | {name the_int} | |
128 | {type :$int_label2} | |
129 | {const_value $value data1} | |
130 | } | |
131 | } | |
132 | } | |
133 | } | |
134 | } | |
135 | ||
136 | set buildid "01234567890abcdef0123456" | |
137 | ||
138 | write_just_debugaltlink ${binfile}_has_altlink.S ${binfile}_dwz.o $buildid | |
139 | write_dwarf_file ${binfile}_dwz.S $buildid | |
140 | ||
141 | if {[gdb_compile ${binfile}_has_altlink.S ${binfile}_alt.o object nodebug] != ""} { | |
142 | fail "compile main with altlink" | |
143 | return -1 | |
144 | } | |
145 | ||
146 | if {[gdb_compile ${binfile}_dwz.S ${binfile}_dwz.o object nodebug] != ""} { | |
147 | fail "compile altlink" | |
148 | return -1 | |
149 | } | |
150 | ||
151 | file rename -force ${binfile}_dwz.o $debugdir | |
152 | ||
153 | # Test that gdb cannot find dwz without debuginfod. | |
154 | clean_restart | |
155 | gdb_test "file ${binfile}_alt.o" ".*could not find '.gnu_debugaltlink'.*" | |
156 | ||
157 | # Find an unused port | |
158 | set port 7999 | |
159 | set found 0 | |
160 | while { ! $found } { | |
161 | incr port | |
162 | if { $port == 65536 } { | |
163 | fail "no available ports" | |
164 | return -1 | |
165 | } | |
166 | ||
167 | spawn debuginfod -vvvv -d $db -p $port -F $debugdir | |
168 | expect { | |
169 | "started http server on IPv4 IPv6 port=$port" { set found 1 } | |
170 | "failed to bind to port" { kill_wait_spawned_process $spawn_id } | |
171 | timeout { | |
172 | fail "find port timeout" | |
173 | return -1 | |
174 | } | |
175 | } | |
176 | } | |
177 | ||
178 | set metrics [list "ready 1" \ | |
179 | "thread_work_total{role=\"traverse\"} 1" \ | |
180 | "thread_work_pending{role=\"scan\"} 0" \ | |
181 | "thread_busy{role=\"scan\"} 0"] | |
182 | ||
183 | # Check server metrics to confirm init has completed. | |
184 | foreach m $metrics { | |
185 | set timelim 20 | |
186 | while { $timelim != 0 } { | |
187 | sleep 0.5 | |
188 | catch {exec curl -s http://127.0.0.1:$port/metrics} got | |
189 | ||
190 | if { [regexp $m $got] } { | |
191 | break | |
192 | } | |
193 | ||
194 | incr timelim -1 | |
195 | } | |
196 | ||
197 | if { $timelim == 0 } { | |
198 | fail "server init timeout" | |
199 | return -1 | |
200 | } | |
201 | } | |
202 | ||
203 | # Point the client to the server | |
204 | setenv DEBUGINFOD_URLS http://127.0.0.1:$port | |
205 | ||
206 | # gdb should now find the symbol and source files | |
207 | clean_restart $binfile | |
208 | gdb_test_no_output "set substitute-path $outputdir /dev/null" | |
209 | gdb_test "br main" "Breakpoint 1 at.*file.*" | |
210 | gdb_test "l" ".*This program is distributed in the hope.*" | |
211 | ||
212 | # gdb should now find the debugaltlink file | |
213 | clean_restart | |
214 | gdb_test "file ${binfile}_alt.o" ".*Reading symbols from ${binfile}_alt.o\.\.\.*" |