blob: d1557cf6d3f1fb7b5a1f167c15f5bc4d93f7b4d1 [file] [log] [blame]
Greg Claytoneae5e262011-05-20 02:00:47 +00001#!/usr/bin/perl
2
3use strict;
4
5#----------------------------------------------------------------------
6# Globals
7#----------------------------------------------------------------------
Greg Clayton125628c2011-06-02 22:21:38 +00008our $unimplemented_str = "UNIMPLEMENTED";
Greg Claytoneae5e262011-05-20 02:00:47 +00009our $success_str = "OK";
10our $swap = 1;
11our $addr_size = 4;
12our $thread_suffix_supported = 0;
13our $max_bytes_per_line = 32;
14our $addr_format = sprintf("0x%%%u.%ux", $addr_size*2, $addr_size*2);
15our $pid_format = "%04.4x";
16our $tid_format = "%04.4x";
17our $reg8_href = { extract => \&get8, format => "0x%2.2x" };
18our $reg16_href = { extract => \&get16, format => "0x%4.4x" };
19our $reg32_href = { extract => \&get32, format => "0x%8.8x" };
20our $reg64_href = { extract => \&get64, format => "0x%s" };
21our $reg80_href = { extract => \&get80, format => "0x%s" };
22our $reg128_href = { extract => \&get128, format => "0x%s" };
23our $float32_href = { extract => \&get32, format => "0x%8.8x" };
24our $float64_href = { extract => \&get64, format => "0x%s" };
25our $float96_href = { extract => \&get96, format => "0x%s" };
26our $curr_cmd = undef;
27our $reg_cmd_reg;
28our %reg_map = (
29 'i386-gdb' => [
30 { name => 'eax', info => $reg32_href },
31 { name => 'ecx', info => $reg32_href },
32 { name => 'edx', info => $reg32_href },
33 { name => 'ebx', info => $reg32_href },
34 { name => 'esp', info => $reg32_href },
35 { name => 'ebp', info => $reg32_href },
36 { name => 'esi', info => $reg32_href },
37 { name => 'edi', info => $reg32_href },
38 { name => 'eip', info => $reg32_href },
39 { name => 'eflags', info => $reg32_href },
40 { name => 'cs', info => $reg32_href },
41 { name => 'ss', info => $reg32_href },
42 { name => 'ds', info => $reg32_href },
43 { name => 'es', info => $reg32_href },
44 { name => 'fs', info => $reg32_href },
45 { name => 'gs', info => $reg32_href },
46 { name => 'st0', info => $reg80_href },
47 { name => 'st1', info => $reg80_href },
48 { name => 'st2', info => $reg80_href },
49 { name => 'st3', info => $reg80_href },
50 { name => 'st4', info => $reg80_href },
51 { name => 'st5', info => $reg80_href },
52 { name => 'st6', info => $reg80_href },
53 { name => 'st7', info => $reg80_href },
54 { name => 'fctrl', info => $reg32_href },
55 { name => 'fstat', info => $reg32_href },
56 { name => 'ftag', info => $reg32_href },
57 { name => 'fiseg', info => $reg32_href },
58 { name => 'fioff', info => $reg32_href },
59 { name => 'foseg', info => $reg32_href },
60 { name => 'fooff', info => $reg32_href },
61 { name => 'fop', info => $reg32_href },
62 { name => 'xmm0', info => $reg128_href },
63 { name => 'xmm1', info => $reg128_href },
64 { name => 'xmm2', info => $reg128_href },
65 { name => 'xmm3', info => $reg128_href },
66 { name => 'xmm4', info => $reg128_href },
67 { name => 'xmm5', info => $reg128_href },
68 { name => 'xmm6', info => $reg128_href },
69 { name => 'xmm7', info => $reg128_href },
70 { name => 'mxcsr', info => $reg32_href },
71 { name => 'mm0', info => $reg64_href },
72 { name => 'mm1', info => $reg64_href },
73 { name => 'mm2', info => $reg64_href },
74 { name => 'mm3', info => $reg64_href },
75 { name => 'mm4', info => $reg64_href },
76 { name => 'mm5', info => $reg64_href },
77 { name => 'mm6', info => $reg64_href },
78 { name => 'mm7', info => $reg64_href },
79 ],
80
81 'i386-lldb' => [
82 { name => 'eax', info => $reg32_href },
83 { name => 'ebx', info => $reg32_href },
84 { name => 'ecx', info => $reg32_href },
85 { name => 'edx', info => $reg32_href },
86 { name => 'edi', info => $reg32_href },
87 { name => 'esi', info => $reg32_href },
88 { name => 'ebp', info => $reg32_href },
89 { name => 'esp', info => $reg32_href },
90 { name => 'ss', info => $reg32_href },
91 { name => 'eflags', info => $reg32_href },
92 { name => 'eip', info => $reg32_href },
93 { name => 'cs', info => $reg32_href },
94 { name => 'ds', info => $reg32_href },
95 { name => 'es', info => $reg32_href },
96 { name => 'fs', info => $reg32_href },
97 { name => 'gs', info => $reg32_href },
98 { name => 'fctrl', info => $reg16_href },
99 { name => 'fstat', info => $reg16_href },
100 { name => 'ftag', info => $reg8_href },
101 { name => 'fop', info => $reg16_href },
102 { name => 'fioff', info => $reg32_href },
103 { name => 'fiseg', info => $reg16_href },
104 { name => 'fooff', info => $reg32_href },
105 { name => 'foseg', info => $reg16_href },
106 { name => 'mxcsr', info => $reg32_href },
107 { name => 'mxcsrmask', info => $reg32_href },
108 { name => 'stmm0', info => $reg80_href },
109 { name => 'stmm1', info => $reg80_href },
110 { name => 'stmm2', info => $reg80_href },
111 { name => 'stmm3', info => $reg80_href },
112 { name => 'stmm4', info => $reg80_href },
113 { name => 'stmm5', info => $reg80_href },
114 { name => 'stmm6', info => $reg80_href },
115 { name => 'stmm7', info => $reg80_href },
116 { name => 'xmm0', info => $reg128_href },
117 { name => 'xmm1', info => $reg128_href },
118 { name => 'xmm2', info => $reg128_href },
119 { name => 'xmm3', info => $reg128_href },
120 { name => 'xmm4', info => $reg128_href },
121 { name => 'xmm5', info => $reg128_href },
122 { name => 'xmm6', info => $reg128_href },
123 { name => 'xmm7', info => $reg128_href },
124 { name => 'trapno', info => $reg32_href },
125 { name => 'err', info => $reg32_href },
126 { name => 'faultvaddr', info => $reg32_href },
127 ],
128
129 'arm-gdb' => [
130 { name => 'r0' , info => $reg32_href },
131 { name => 'r1' , info => $reg32_href },
132 { name => 'r2' , info => $reg32_href },
133 { name => 'r3' , info => $reg32_href },
134 { name => 'r4' , info => $reg32_href },
135 { name => 'r5' , info => $reg32_href },
136 { name => 'r6' , info => $reg32_href },
137 { name => 'r7' , info => $reg32_href },
138 { name => 'r8' , info => $reg32_href },
139 { name => 'r9' , info => $reg32_href },
140 { name => 'r10' , info => $reg32_href },
141 { name => 'r11' , info => $reg32_href },
142 { name => 'r12' , info => $reg32_href },
143 { name => 'sp' , info => $reg32_href },
144 { name => 'lr' , info => $reg32_href },
145 { name => 'pc' , info => $reg32_href },
146 { name => 'f0' , info => $float96_href },
147 { name => 'f1' , info => $float96_href },
148 { name => 'f2' , info => $float96_href },
149 { name => 'f3' , info => $float96_href },
150 { name => 'f4' , info => $float96_href },
151 { name => 'f5' , info => $float96_href },
152 { name => 'f6' , info => $float96_href },
153 { name => 'f7' , info => $float96_href },
154 { name => 'fps' , info => $reg32_href },
155 { name => 'cpsr' , info => $reg32_href },
156 { name => 's0' , info => $float32_href },
157 { name => 's1' , info => $float32_href },
158 { name => 's2' , info => $float32_href },
159 { name => 's3' , info => $float32_href },
160 { name => 's4' , info => $float32_href },
161 { name => 's5' , info => $float32_href },
162 { name => 's6' , info => $float32_href },
163 { name => 's7' , info => $float32_href },
164 { name => 's8' , info => $float32_href },
165 { name => 's9' , info => $float32_href },
166 { name => 's10' , info => $float32_href },
167 { name => 's11' , info => $float32_href },
168 { name => 's12' , info => $float32_href },
169 { name => 's13' , info => $float32_href },
170 { name => 's14' , info => $float32_href },
171 { name => 's15' , info => $float32_href },
172 { name => 's16' , info => $float32_href },
173 { name => 's17' , info => $float32_href },
174 { name => 's18' , info => $float32_href },
175 { name => 's19' , info => $float32_href },
176 { name => 's20' , info => $float32_href },
177 { name => 's21' , info => $float32_href },
178 { name => 's22' , info => $float32_href },
179 { name => 's23' , info => $float32_href },
180 { name => 's24' , info => $float32_href },
181 { name => 's25' , info => $float32_href },
182 { name => 's26' , info => $float32_href },
183 { name => 's27' , info => $float32_href },
184 { name => 's28' , info => $float32_href },
185 { name => 's29' , info => $float32_href },
186 { name => 's30' , info => $float32_href },
187 { name => 's31' , info => $float32_href },
188 { name => 'fpscr' , info => $reg32_href },
189 { name => 'd16' , info => $float64_href },
190 { name => 'd17' , info => $float64_href },
191 { name => 'd18' , info => $float64_href },
192 { name => 'd19' , info => $float64_href },
193 { name => 'd20' , info => $float64_href },
194 { name => 'd21' , info => $float64_href },
195 { name => 'd22' , info => $float64_href },
196 { name => 'd23' , info => $float64_href },
197 { name => 'd24' , info => $float64_href },
198 { name => 'd25' , info => $float64_href },
199 { name => 'd26' , info => $float64_href },
200 { name => 'd27' , info => $float64_href },
201 { name => 'd28' , info => $float64_href },
202 { name => 'd29' , info => $float64_href },
203 { name => 'd30' , info => $float64_href },
204 { name => 'd31' , info => $float64_href },
205 ],
206
Greg Clayton139da722011-05-20 03:15:54 +0000207
208 'arm-lldb' => [
209 { name => 'r0' , info => $reg32_href },
210 { name => 'r1' , info => $reg32_href },
211 { name => 'r2' , info => $reg32_href },
212 { name => 'r3' , info => $reg32_href },
213 { name => 'r4' , info => $reg32_href },
214 { name => 'r5' , info => $reg32_href },
215 { name => 'r6' , info => $reg32_href },
216 { name => 'r7' , info => $reg32_href },
217 { name => 'r8' , info => $reg32_href },
218 { name => 'r9' , info => $reg32_href },
219 { name => 'r10' , info => $reg32_href },
220 { name => 'r11' , info => $reg32_href },
221 { name => 'r12' , info => $reg32_href },
222 { name => 'sp' , info => $reg32_href },
223 { name => 'lr' , info => $reg32_href },
224 { name => 'pc' , info => $reg32_href },
225 { name => 'cpsr' , info => $reg32_href },
226 { name => 's0' , info => $float32_href },
227 { name => 's1' , info => $float32_href },
228 { name => 's2' , info => $float32_href },
229 { name => 's3' , info => $float32_href },
230 { name => 's4' , info => $float32_href },
231 { name => 's5' , info => $float32_href },
232 { name => 's6' , info => $float32_href },
233 { name => 's7' , info => $float32_href },
234 { name => 's8' , info => $float32_href },
235 { name => 's9' , info => $float32_href },
236 { name => 's10' , info => $float32_href },
237 { name => 's11' , info => $float32_href },
238 { name => 's12' , info => $float32_href },
239 { name => 's13' , info => $float32_href },
240 { name => 's14' , info => $float32_href },
241 { name => 's15' , info => $float32_href },
242 { name => 's16' , info => $float32_href },
243 { name => 's17' , info => $float32_href },
244 { name => 's18' , info => $float32_href },
245 { name => 's19' , info => $float32_href },
246 { name => 's20' , info => $float32_href },
247 { name => 's21' , info => $float32_href },
248 { name => 's22' , info => $float32_href },
249 { name => 's23' , info => $float32_href },
250 { name => 's24' , info => $float32_href },
251 { name => 's25' , info => $float32_href },
252 { name => 's26' , info => $float32_href },
253 { name => 's27' , info => $float32_href },
254 { name => 's28' , info => $float32_href },
255 { name => 's29' , info => $float32_href },
256 { name => 's30' , info => $float32_href },
257 { name => 's31' , info => $float32_href },
258 { name => 'd0' , info => $float64_href },
259 { name => 'd1' , info => $float64_href },
260 { name => 'd2' , info => $float64_href },
261 { name => 'd3' , info => $float64_href },
262 { name => 'd4' , info => $float64_href },
263 { name => 'd5' , info => $float64_href },
264 { name => 'd6' , info => $float64_href },
265 { name => 'd7' , info => $float64_href },
266 { name => 'd8' , info => $float64_href },
267 { name => 'd9' , info => $float64_href },
268 { name => 'd10' , info => $float64_href },
269 { name => 'd11' , info => $float64_href },
270 { name => 'd12' , info => $float64_href },
271 { name => 'd13' , info => $float64_href },
272 { name => 'd14' , info => $float64_href },
273 { name => 'd15' , info => $float64_href },
274 { name => 'd16' , info => $float64_href },
275 { name => 'd17' , info => $float64_href },
276 { name => 'd18' , info => $float64_href },
277 { name => 'd19' , info => $float64_href },
278 { name => 'd20' , info => $float64_href },
279 { name => 'd21' , info => $float64_href },
280 { name => 'd22' , info => $float64_href },
281 { name => 'd23' , info => $float64_href },
282 { name => 'd24' , info => $float64_href },
283 { name => 'd25' , info => $float64_href },
284 { name => 'd26' , info => $float64_href },
285 { name => 'd27' , info => $float64_href },
286 { name => 'd28' , info => $float64_href },
287 { name => 'd29' , info => $float64_href },
288 { name => 'd30' , info => $float64_href },
289 { name => 'd31' , info => $float64_href },
290 { name => 'fpscr' , info => $reg32_href },
291 { name => 'exc' , info => $reg32_href },
292 { name => 'fsr' , info => $reg32_href },
293 { name => 'far' , info => $reg32_href },
294 ],
295
Greg Claytoneae5e262011-05-20 02:00:47 +0000296 'x86_64-gdb' => [
297 { name => 'rax' , info => $reg64_href },
298 { name => 'rbx' , info => $reg64_href },
299 { name => 'rcx' , info => $reg64_href },
300 { name => 'rdx' , info => $reg64_href },
301 { name => 'rsi' , info => $reg64_href },
302 { name => 'rdi' , info => $reg64_href },
303 { name => 'rbp' , info => $reg64_href },
304 { name => 'rsp' , info => $reg64_href },
305 { name => 'r8' , info => $reg64_href },
306 { name => 'r9' , info => $reg64_href },
307 { name => 'r10' , info => $reg64_href },
308 { name => 'r11' , info => $reg64_href },
309 { name => 'r12' , info => $reg64_href },
310 { name => 'r13' , info => $reg64_href },
311 { name => 'r14' , info => $reg64_href },
312 { name => 'r15' , info => $reg64_href },
313 { name => 'rip' , info => $reg64_href },
314 { name => 'eflags' , info => $reg32_href },
315 { name => 'cs' , info => $reg32_href },
316 { name => 'ss' , info => $reg32_href },
317 { name => 'ds' , info => $reg32_href },
318 { name => 'es' , info => $reg32_href },
319 { name => 'fs' , info => $reg32_href },
320 { name => 'gs' , info => $reg32_href },
321 { name => 'stmm0' , info => $reg80_href },
322 { name => 'stmm1' , info => $reg80_href },
323 { name => 'stmm2' , info => $reg80_href },
324 { name => 'stmm3' , info => $reg80_href },
325 { name => 'stmm4' , info => $reg80_href },
326 { name => 'stmm5' , info => $reg80_href },
327 { name => 'stmm6' , info => $reg80_href },
328 { name => 'stmm7' , info => $reg80_href },
329 { name => 'fctrl' , info => $reg32_href },
330 { name => 'fstat' , info => $reg32_href },
331 { name => 'ftag' , info => $reg32_href },
332 { name => 'fiseg' , info => $reg32_href },
333 { name => 'fioff' , info => $reg32_href },
334 { name => 'foseg' , info => $reg32_href },
335 { name => 'fooff' , info => $reg32_href },
336 { name => 'fop' , info => $reg32_href },
337 { name => 'xmm0' , info => $reg128_href },
338 { name => 'xmm1' , info => $reg128_href },
339 { name => 'xmm2' , info => $reg128_href },
340 { name => 'xmm3' , info => $reg128_href },
341 { name => 'xmm4' , info => $reg128_href },
342 { name => 'xmm5' , info => $reg128_href },
343 { name => 'xmm6' , info => $reg128_href },
344 { name => 'xmm7' , info => $reg128_href },
345 { name => 'xmm8' , info => $reg128_href },
346 { name => 'xmm9' , info => $reg128_href },
347 { name => 'xmm10' , info => $reg128_href },
348 { name => 'xmm11' , info => $reg128_href },
349 { name => 'xmm12' , info => $reg128_href },
350 { name => 'xmm13' , info => $reg128_href },
351 { name => 'xmm14' , info => $reg128_href },
352 { name => 'xmm15' , info => $reg128_href },
353 { name => 'mxcsr' , info => $reg32_href },
354 ],
355
356 'x86_64-lldb' => [
357 { name => 'rax' , info => $reg64_href },
358 { name => 'rbx' , info => $reg64_href },
359 { name => 'rcx' , info => $reg64_href },
360 { name => 'rdx' , info => $reg64_href },
361 { name => 'rdi' , info => $reg64_href },
362 { name => 'rsi' , info => $reg64_href },
363 { name => 'rbp' , info => $reg64_href },
364 { name => 'rsp' , info => $reg64_href },
365 { name => 'r8 ' , info => $reg64_href },
366 { name => 'r9 ' , info => $reg64_href },
367 { name => 'r10' , info => $reg64_href },
368 { name => 'r11' , info => $reg64_href },
369 { name => 'r12' , info => $reg64_href },
370 { name => 'r13' , info => $reg64_href },
371 { name => 'r14' , info => $reg64_href },
372 { name => 'r15' , info => $reg64_href },
373 { name => 'rip' , info => $reg64_href },
374 { name => 'rflags' , info => $reg64_href },
375 { name => 'cs' , info => $reg64_href },
376 { name => 'fs' , info => $reg64_href },
377 { name => 'gs' , info => $reg64_href },
378 { name => 'fctrl' , info => $reg16_href },
379 { name => 'fstat' , info => $reg16_href },
380 { name => 'ftag' , info => $reg8_href },
381 { name => 'fop' , info => $reg16_href },
382 { name => 'fioff' , info => $reg32_href },
383 { name => 'fiseg' , info => $reg16_href },
384 { name => 'fooff' , info => $reg32_href },
385 { name => 'foseg' , info => $reg16_href },
386 { name => 'mxcsr' , info => $reg32_href },
387 { name => 'mxcsrmask' , info => $reg32_href },
388 { name => 'stmm0' , info => $reg80_href },
389 { name => 'stmm1' , info => $reg80_href },
390 { name => 'stmm2' , info => $reg80_href },
391 { name => 'stmm3' , info => $reg80_href },
392 { name => 'stmm4' , info => $reg80_href },
393 { name => 'stmm5' , info => $reg80_href },
394 { name => 'stmm6' , info => $reg80_href },
395 { name => 'stmm7' , info => $reg80_href },
396 { name => 'xmm0' , info => $reg128_href },
397 { name => 'xmm1' , info => $reg128_href },
398 { name => 'xmm2' , info => $reg128_href },
399 { name => 'xmm3' , info => $reg128_href },
400 { name => 'xmm4' , info => $reg128_href },
401 { name => 'xmm5' , info => $reg128_href },
402 { name => 'xmm6' , info => $reg128_href },
403 { name => 'xmm7' , info => $reg128_href },
404 { name => 'xmm8' , info => $reg128_href },
405 { name => 'xmm9' , info => $reg128_href },
406 { name => 'xmm10' , info => $reg128_href },
407 { name => 'xmm11' , info => $reg128_href },
408 { name => 'xmm12' , info => $reg128_href },
409 { name => 'xmm13' , info => $reg128_href },
410 { name => 'xmm14' , info => $reg128_href },
411 { name => 'xmm15' , info => $reg128_href },
412 { name => 'trapno' , info => $reg32_href },
413 { name => 'err' , info => $reg32_href },
414 { name => 'faultvaddr' , info => $reg64_href },
415 ]
416);
417
418our $max_register_name_len = 0;
419calculate_max_register_name_length();
420our @point_types = ( "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" );
421our $opt_v = 0; # verbose
422our $opt_g = 0; # debug
423our $opt_q = 0; # quiet
424our $opt_r = undef;
425use Getopt::Std;
426getopts('gvqr:');
427
428our $registers_aref = undef;
429
430if (length($opt_r))
431{
Greg Clayton125628c2011-06-02 22:21:38 +0000432 if (exists $reg_map{$opt_r})
433 {
434 $registers_aref = $reg_map{$opt_r};
435 }
436 else
437 {
438 die "Can't get registers group for '$opt_r'\n";
439 }
Greg Claytoneae5e262011-05-20 02:00:47 +0000440}
441
442sub extract_key_value_pairs
443{
444 my $kv_href = {};
445 my $arrayref = shift;
446 my $str = join('',@$arrayref);
447 my @kv_strs = split(/;/, $str);
448 foreach my $kv_str (@kv_strs)
449 {
450 my ($key, $value) = split(/:/, $kv_str);
451 $kv_href->{$key} = $value;
452 }
453 return $kv_href;
454}
455
456sub get_thread_from_thread_suffix
457{
458 if ($thread_suffix_supported)
459 {
460 my $arrayref = shift;
461 # Skip leading semi-colon if needed
462 $$arrayref[0] == ';' and shift @$arrayref;
463 my $thread_href = extract_key_value_pairs ($arrayref);
464 if (exists $thread_href->{thread})
465 {
466 return $thread_href->{thread};
467 }
468 }
469 return undef;
470}
471
472sub calculate_max_register_name_length
473{
474 $max_register_name_len = 7;
475 foreach my $reg_href (@$registers_aref)
476 {
477 my $name_len = length($reg_href->{name});
478 if ($max_register_name_len < $name_len)
479 {
480 $max_register_name_len = $name_len;
481 }
482 }
483}
484#----------------------------------------------------------------------
485# Hash that maps command characters to the appropriate functions using
486# the command character as the key and the value being a reference to
487# the dump function for dumping the command itself.
488#----------------------------------------------------------------------
489our %cmd_callbacks =
490(
491 '?' => \&dump_last_signal_cmd,
492 'H' => \&dump_set_thread_cmd,
493 'T' => \&dump_thread_is_alive_cmd,
494 'q' => \&dump_general_query_cmd,
495 'Q' => \&dump_general_set_cmd,
496 'g' => \&dump_read_regs_cmd,
497 'G' => \&dump_write_regs_cmd,
498 'p' => \&dump_read_single_register_cmd,
499 'P' => \&dump_write_single_register_cmd,
500 'm' => \&dump_read_mem_cmd,
501 'M' => \&dump_write_mem_cmd,
502 'X' => \&dump_write_mem_binary_cmd,
503 'Z' => \&dump_bp_wp_command,
504 'z' => \&dump_bp_wp_command,
505 'k' => \&dump_kill_cmd,
506 'A' => \&dump_A_command,
507 'c' => \&dump_continue_cmd,
508 'C' => \&dump_continue_with_signal_cmd,
509 '_M' => \&dump_allocate_memory_cmd,
510 '_m' => \&dump_deallocate_memory_cmd,
511 # extended commands
512 'v' => \&dump_extended_cmd
513);
514
515#----------------------------------------------------------------------
516# Hash that maps command characters to the appropriate functions using
517# the command character as the key and the value being a reference to
518# the dump function for the response to the command.
519#----------------------------------------------------------------------
520our %rsp_callbacks =
521(
522 'c' => \&dump_stop_reply_packet,
523 'C' => \&dump_stop_reply_packet,
524 '?' => \&dump_stop_reply_packet,
525 'T' => \&dump_thread_is_alive_rsp,
526 'H' => \&dump_set_thread_rsp,
527 'q' => \&dump_general_query_rsp,
528 'g' => \&dump_read_regs_rsp,
529 'p' => \&dump_read_single_register_rsp,
530 'm' => \&dump_read_mem_rsp,
531 '_M' => \&dump_allocate_memory_rsp,
532
533 # extended commands
534 'v' => \&dump_extended_rsp,
535);
536
537
538sub dump_register_value
539{
540 my $indent = shift;
541 my $arrayref = shift;
542 my $reg_num = shift;
543
544 if ($reg_num >= @$registers_aref)
545 {
546 printf("\tinvalid register index %d\n", $reg_num);
547 }
548
549 my $reg_href = $$registers_aref[$reg_num];
550 my $reg_name = $reg_href->{name};
551 if ($$arrayref[0] eq '#')
552 {
553 printf("\t%*s: error: EOS reached when trying to read register %d\n", $max_register_name_len, $reg_name, $reg_num);
554 }
555
556 my $reg_info = $reg_href->{info};
557 my $reg_extract = $reg_info->{extract};
558 my $reg_format = $reg_info->{format};
559 my $reg_val = &$reg_extract($arrayref);
560 if ($indent) {
561 printf("\t%*s = $reg_format", $max_register_name_len, $reg_name, $reg_val);
562 } else {
563 printf("%s = $reg_format", $reg_name, $reg_val);
564 }
565}
566
567#----------------------------------------------------------------------
568# Extract the command into an array of ASCII char strings for easy
569# processing
570#----------------------------------------------------------------------
571sub extract_command
572{
573 my $cmd_str = shift;
574 my @cmd_chars = split(/ */, $cmd_str);
575 if ($cmd_chars[0] ne '$')
576 {
577 # only set the current command if it isn't a reply
578 $curr_cmd = $cmd_chars[0];
579 }
580 return @cmd_chars;
581}
582
583#----------------------------------------------------------------------
584# Strip the 3 checksum array entries after we don't need them anymore
585#----------------------------------------------------------------------
586sub strip_checksum
587{
588 my $arrayref = shift;
589 splice(@$arrayref, -3);
590}
591
592#----------------------------------------------------------------------
593# Dump all strings in array by joining them together with no space
594# between them
595#----------------------------------------------------------------------
596sub dump_chars
597{
598 print join('',@_);
599}
600
601#----------------------------------------------------------------------
602# Check if the response is an error 'EXX'
603#----------------------------------------------------------------------
604sub is_error_response
605{
606 if ($_[0] eq 'E')
607 {
608 shift;
609 print "ERROR = " . join('',@_) . "\n";
610 return 1;
611 }
612 return 0;
613}
614
615#----------------------------------------------------------------------
616# 'H' command
617#----------------------------------------------------------------------
618sub dump_set_thread_cmd
619{
620 my $cmd = shift;
621 my $mod = shift;
622 print "set_thread ( $mod, " . join('',@_) . " )\n";
623}
624
625#----------------------------------------------------------------------
626# 'T' command
627#----------------------------------------------------------------------
628our $T_cmd_tid = -1;
629sub dump_thread_is_alive_cmd
630{
631 my $cmd = shift;
632 $T_cmd_tid = get_hex(\@_);
633 printf("thread_is_alive ( $tid_format )\n", $T_cmd_tid);
634}
635
636sub dump_thread_is_alive_rsp
637{
638 my $rsp = join('',@_);
639
640 printf("thread_is_alive ( $tid_format ) =>", $T_cmd_tid);
641 if ($rsp eq 'OK')
642 {
643 print " alive.\n";
644 }
645 else
646 {
647 print " dead.\n";
648 }
649}
650
651#----------------------------------------------------------------------
652# 'H' response
653#----------------------------------------------------------------------
654sub dump_set_thread_rsp
655{
656 if (!is_error_response(@_))
657 {
658 print join('',@_) . "\n";
659 }
660}
661
662#----------------------------------------------------------------------
663# 'q' command
664#----------------------------------------------------------------------
665our $gen_query_cmd;
Greg Clayton125628c2011-06-02 22:21:38 +0000666our $qRegisterInfo_reg_num = -1;
Greg Claytoneae5e262011-05-20 02:00:47 +0000667sub dump_general_query_cmd
668{
669 $gen_query_cmd = join('',@_);
670 if ($gen_query_cmd eq 'qC')
671 {
672 print 'get_current_pid ()';
673 }
674 elsif ($gen_query_cmd eq 'qfThreadInfo')
675 {
676 print 'get_first_active_threads ()';
677 }
678 elsif ($gen_query_cmd eq 'qsThreadInfo')
679 {
680 print 'get_subsequent_active_threads ()';
681 }
682 elsif (index($gen_query_cmd, 'qThreadExtraInfo') == 0)
683 {
684 # qThreadExtraInfo,id
685 print 'get_thread_extra_info ()';
686 }
687 elsif (index($gen_query_cmd, 'qThreadStopInfo') == 0)
688 {
689 # qThreadStopInfoXXXX
690 @_ = splice(@_, length('qThreadStopInfo'));
691 my $tid = get_addr(\@_);
692 printf('get_thread_stop_info ( thread = 0x%4.4x )', $tid);
693 }
694 elsif (index($gen_query_cmd, 'qSymbol:') == 0)
695 {
696 # qCRC:addr,length
697 print 'gdb_ready_to_serve_symbol_lookups ()';
698 }
699 elsif (index($gen_query_cmd, 'qCRC:') == 0)
700 {
701 # qCRC:addr,length
702 @_ = splice(@_, length('qCRC:'));
703 my $address = get_addr(\@_);
704 shift @_;
705 my $length = join('', @_);
706 printf("compute_crc (addr = $addr_format, length = $length)", $address);
707 }
708 elsif (index($gen_query_cmd, 'qGetTLSAddr:') == 0)
709 {
710 # qGetTLSAddr:thread-id,offset,lm
711 @_ = splice(@_, length('qGetTLSAddr:'));
712 my ($tid, $offset, $lm) = split (/,/, join('', @_));
713 print "get_thread_local_storage_addr (thread-id = $tid, offset = $offset, lm = $lm)";
714 }
715 elsif ($gen_query_cmd eq 'qOffsets')
716 {
717 print 'get_section_offsets ()';
718 }
719 elsif (index($gen_query_cmd, 'qRegisterInfo') == 0)
720 {
721 @_ = splice(@_, length('qRegisterInfo'));
Greg Clayton125628c2011-06-02 22:21:38 +0000722 $qRegisterInfo_reg_num = get_hex(\@_);
723
724 printf "get_dynamic_register_info ($qRegisterInfo_reg_num)";
Greg Claytoneae5e262011-05-20 02:00:47 +0000725 }
726 else
727 {
728 print $gen_query_cmd;
729 }
730 print "\n";
731}
732
733#----------------------------------------------------------------------
734# 'q' response
735#----------------------------------------------------------------------
736sub dump_general_query_rsp
737{
738 my $gen_query_rsp = join('',@_);
Greg Clayton125628c2011-06-02 22:21:38 +0000739 my $gen_query_rsp_len = length ($gen_query_rsp);
Greg Claytoneae5e262011-05-20 02:00:47 +0000740 if ($gen_query_cmd eq 'qC' and index($gen_query_rsp, 'QC') == 0)
741 {
742 shift @_; shift @_;
743 my $pid = get_hex(\@_);
Greg Clayton125628c2011-06-02 22:21:38 +0000744 printf("pid = $pid_format\n", $pid);
Greg Claytoneae5e262011-05-20 02:00:47 +0000745 return;
746 }
747 elsif (index($gen_query_cmd, 'qRegisterInfo') == 0)
748 {
Greg Clayton125628c2011-06-02 22:21:38 +0000749 if ($gen_query_rsp_len == 0)
Greg Claytoneae5e262011-05-20 02:00:47 +0000750 {
Greg Clayton125628c2011-06-02 22:21:38 +0000751 print "$unimplemented_str\n";
Greg Claytoneae5e262011-05-20 02:00:47 +0000752 }
753 else
754 {
Greg Clayton125628c2011-06-02 22:21:38 +0000755 if (index($gen_query_rsp, 'name') == 0)
756 {
757 $qRegisterInfo_reg_num == 0 and $registers_aref = [];
758
759 my @name_and_values = split (/;/, $gen_query_rsp);
760
761 my $reg_name = undef;
762 my $byte_size = 0;
763 foreach (@name_and_values)
764 {
765 my ($name, $value) = split /:/;
766 if ($name eq "name") { $reg_name = $value; }
767 elsif ($name eq "bitsize") { $byte_size = $value / 8; last; }
768 }
769 if (defined $reg_name and $byte_size > 0)
770 {
771 if ($byte_size == 4) {push @$registers_aref, { name => $reg_name, info => $reg32_href };}
772 elsif ($byte_size == 8) {push @$registers_aref, { name => $reg_name, info => $reg64_href };}
773 elsif ($byte_size == 10) {push @$registers_aref, { name => $reg_name, info => $reg80_href };}
774 elsif ($byte_size == 12) {push @$registers_aref, { name => $reg_name, info => $float96_href };}
775 elsif ($byte_size == 16) {push @$registers_aref, { name => $reg_name, info => $reg128_href };}
776 }
777 }
778 elsif ($gen_query_rsp_len == 3 and index($gen_query_rsp, 'E') == 0)
779 {
780 calculate_max_register_name_length();
781 }
Greg Claytoneae5e262011-05-20 02:00:47 +0000782 }
783 }
784 elsif ($gen_query_cmd =~ 'qThreadStopInfo')
785 {
786 dump_stop_reply_packet (@_);
787 }
788 if (dump_standard_response(\@_))
789 {
790 # Do nothing...
791 }
792 else
793 {
794 print join('',@_) . "\n";
795 }
796}
797
798#----------------------------------------------------------------------
799# 'Q' command
800#----------------------------------------------------------------------
801our $gen_set_cmd;
802sub dump_general_set_cmd
803{
804 $gen_query_cmd = join('',@_);
805 if ($gen_query_cmd eq 'QStartNoAckMode')
806 {
807 print "StartNoAckMode ()"
808 }
809 elsif ($gen_query_cmd eq 'QThreadSuffixSupported')
810 {
811 $thread_suffix_supported = 1;
812 print "ThreadSuffixSupported ()"
813 }
814 elsif (index($gen_query_cmd, 'QSetMaxPayloadSize:') == 0)
815 {
816 @_ = splice(@_, length('QSetMaxPayloadSize:'));
817 my $max_payload_size = get_hex(\@_);
818 # QSetMaxPayloadSize:XXXX where XXXX is a hex length of the max
819 # packet payload size supported by gdb
820 printf("SetMaxPayloadSize ( 0x%x (%u))", $max_payload_size, $max_payload_size);
821 }
Greg Clayton125628c2011-06-02 22:21:38 +0000822 elsif (index ($gen_query_cmd, 'QSetSTDIN:') == 0)
823 {
824 @_ = splice(@_, length('QSetSTDIN:'));
825 printf ("SetSTDIN (path ='%s')\n", get_hex_string (\@_));
826 }
827 elsif (index ($gen_query_cmd, 'QSetSTDOUT:') == 0)
828 {
829 @_ = splice(@_, length('QSetSTDOUT:'));
830 printf ("SetSTDOUT (path ='%s')\n", get_hex_string (\@_));
831 }
832 elsif (index ($gen_query_cmd, 'QSetSTDERR:') == 0)
833 {
834 @_ = splice(@_, length('QSetSTDERR:'));
835 printf ("SetSTDERR (path ='%s')\n", get_hex_string (\@_));
836 }
Greg Claytoneae5e262011-05-20 02:00:47 +0000837 else
838 {
839 print $gen_query_cmd;
840 }
841 print "\n";
842}
843
844#----------------------------------------------------------------------
845# 'k' command
846#----------------------------------------------------------------------
847sub dump_kill_cmd
848{
849 my $cmd = shift;
850 print "kill (" . join('',@_) . ")\n";
851}
852
853#----------------------------------------------------------------------
854# 'g' command
855#----------------------------------------------------------------------
856sub dump_read_regs_cmd
857{
858 my $cmd = shift;
859 print "read_registers ()\n";
860}
861
862#----------------------------------------------------------------------
863# 'G' command
864#----------------------------------------------------------------------
865sub dump_write_regs_cmd
866{
867 print "write_registers:\n";
868 my $cmd = shift;
869 foreach my $reg_href (@$registers_aref)
870 {
871 last if ($_[0] eq '#');
872 my $reg_info_href = $reg_href->{info};
873 my $reg_name = $reg_href->{name};
874 my $reg_extract = $reg_info_href->{extract};
875 my $reg_format = $reg_info_href->{format};
876 my $reg_val = &$reg_extract(\@_);
877 printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val);
878 }
879}
880
881sub dump_read_regs_rsp
882{
883 print "read_registers () =>\n";
884 if (!is_error_response(@_))
885 {
886 # print join('',@_) . "\n";
887 foreach my $reg_href (@$registers_aref)
888 {
889 last if ($_[0] eq '#');
890 my $reg_info_href = $reg_href->{info};
891 my $reg_name = $reg_href->{name};
892 my $reg_extract = $reg_info_href->{extract};
893 my $reg_format = $reg_info_href->{format};
894 my $reg_val = &$reg_extract(\@_);
895 printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val);
896 }
897 }
898}
899
900sub dump_read_single_register_rsp
901{
902 dump_register_value(0, \@_, $reg_cmd_reg);
903 print "\n";
904}
905
906#----------------------------------------------------------------------
907# '_M' - allocate memory command (LLDB extension)
908#
909# Command: '_M'
910# Arg1: Hex byte size as big endian hex string
911# Separator: ','
912# Arg2: permissions as string that must be a string that contains any
913# combination of 'r' (readable) 'w' (writable) or 'x' (executable)
914#
915# Returns: The address that was allocated as a big endian hex string
916# on success, else an error "EXX" where XX are hex bytes
917# that indicate an error code.
918#
919# Examples:
920# _M10,rw # allocate 16 bytes with read + write permissions
921# _M100,rx # allocate 256 bytes with read + execute permissions
922#----------------------------------------------------------------------
923sub dump_allocate_memory_cmd
924{
925 shift; shift; # shift off the '_' and the 'M'
926 my $byte_size = get_addr(\@_);
927 shift; # Skip ','
928 printf("allocate_memory ( byte_size = %u (0x%x), permissions = %s)\n", $byte_size, $byte_size, join('',@_));
929}
930
931sub dump_allocate_memory_rsp
932{
933 if (@_ == 3 and $_[0] == 'E')
934 {
935 printf("allocated memory addr = ERROR (%s))\n", join('',@_));
936 }
937 else
938 {
939 printf("allocated memory addr = 0x%s\n", join('',@_));
940 }
941}
942
Greg Claytoneae5e262011-05-20 02:00:47 +0000943#----------------------------------------------------------------------
944# '_m' - deallocate memory command (LLDB extension)
945#
946# Command: '_m'
947# Arg1: Hex address as big endian hex string
948#
949# Returns: "OK" on success "EXX" on error
950#
951# Examples:
952# _m201000 # Free previously allocated memory at address 0x201000
953#----------------------------------------------------------------------
954sub dump_deallocate_memory_cmd
955{
956 shift; shift; # shift off the '_' and the 'm'
957 printf("deallocate_memory ( addr = 0x%s)\n", join('',@_));
958}
959
960
961#----------------------------------------------------------------------
962# 'p' command
963#----------------------------------------------------------------------
964sub dump_read_single_register_cmd
965{
966 my $cmd = shift;
Greg Clayton125628c2011-06-02 22:21:38 +0000967 my $reg_num = get_hex(\@_);
Greg Claytoneae5e262011-05-20 02:00:47 +0000968 my $thread = get_thread_from_thread_suffix (\@_);
Greg Clayton125628c2011-06-02 22:21:38 +0000969 my $reg_href = $$registers_aref[$reg_num];
970
Greg Claytoneae5e262011-05-20 02:00:47 +0000971 if (defined $thread)
972 {
Greg Clayton125628c2011-06-02 22:21:38 +0000973 print "read_register ( reg = \"$reg_href->{name}\", thread = $thread )\n";
Greg Claytoneae5e262011-05-20 02:00:47 +0000974 }
975 else
976 {
Greg Clayton125628c2011-06-02 22:21:38 +0000977 print "read_register ( reg = \"$reg_href->{name}\" )\n";
Greg Claytoneae5e262011-05-20 02:00:47 +0000978 }
979}
980
981
982#----------------------------------------------------------------------
983# 'P' command
984#----------------------------------------------------------------------
985sub dump_write_single_register_cmd
986{
987 my $cmd = shift;
988 my $reg_num = get_hex(\@_);
989 shift (@_); # Discard the '='
990
991 print "write_register ( ";
992 dump_register_value(0, \@_, $reg_num);
993 my $thread = get_thread_from_thread_suffix (\@_);
994 if (defined $thread)
995 {
996 print ", thread = $thread";
997 }
998 print " )\n";
999}
1000
1001#----------------------------------------------------------------------
1002# 'm' command
1003#----------------------------------------------------------------------
1004our $read_mem_address = 0;
1005sub dump_read_mem_cmd
1006{
1007 my $cmd = shift;
1008 $read_mem_address = get_addr(\@_);
1009 shift; # Skip ','
1010 printf("read_mem ( $addr_format, %s )\n", $read_mem_address, join('',@_));
1011}
1012
1013#----------------------------------------------------------------------
1014# 'm' response
1015#----------------------------------------------------------------------
1016sub dump_read_mem_rsp
1017{
1018 # If the memory read was 2 or 4 bytes, print it out in native format
1019 # instead of just as bytes.
1020 my $num_nibbles = @_;
1021 if ($num_nibbles == 2)
1022 {
1023 printf(" 0x%2.2x", get8(\@_));
1024 }
1025 elsif ($num_nibbles == 4)
1026 {
1027 printf(" 0x%4.4x", get16(\@_));
1028 }
1029 elsif ($num_nibbles == 8)
1030 {
1031 printf(" 0x%8.8x", get32(\@_));
1032 }
1033 elsif ($num_nibbles == 16)
1034 {
1035 printf(" 0x%s", get64(\@_));
1036 }
1037 else
1038 {
1039 my $curr_address = $read_mem_address;
1040 my $nibble;
1041 my $nibble_offset = 0;
1042 my $max_nibbles_per_line = 2 * $max_bytes_per_line;
1043 foreach $nibble (@_)
1044 {
1045 if (($nibble_offset % $max_nibbles_per_line) == 0)
1046 {
1047 ($nibble_offset > 0) and print "\n ";
1048 printf("$addr_format: ", $curr_address + $nibble_offset/2);
1049 }
1050 (($nibble_offset % 2) == 0) and print ' ';
1051 print $nibble;
1052 $nibble_offset++;
1053 }
1054 }
1055 print "\n";
1056}
1057
1058#----------------------------------------------------------------------
1059# 'c' command
1060#----------------------------------------------------------------------
1061sub dump_continue_cmd
1062{
1063 my $cmd = shift;
1064 my $address = -1;
1065 if (@_)
1066 {
1067 my $address = get_addr(\@_);
1068 printf("continue ($addr_format)\n", $address);
1069 }
1070 else
1071 {
1072 printf("continue ()\n");
1073 }
1074}
1075
1076#----------------------------------------------------------------------
1077# 'Css' continue (C) with signal (ss where 'ss' is two hex digits)
1078#----------------------------------------------------------------------
1079sub dump_continue_with_signal_cmd
1080{
1081 my $cmd = shift;
1082 my $address = -1;
1083 my $signal = get_hex(\@_);
1084 if (@_)
1085 {
1086 my $address = 0;
1087 if (@_ && $_[0] == ';')
1088 {
1089 shift;
1090 $address = get_addr(\@_);
1091 }
1092 }
1093
1094 if ($address != -1)
1095 {
1096 printf("continue_with_signal (signal = 0x%2.2x, address = $addr_format)\n", $signal, $address);
1097 }
1098 else
1099 {
1100 printf("continue_with_signal (signal = 0x%2.2x)\n", $signal);
1101 }
1102}
1103
1104#----------------------------------------------------------------------
1105# 'A' command
1106#----------------------------------------------------------------------
1107sub dump_A_command
1108{
1109 my $cmd = get_exptected_char(\@_, 'A') or print "error: incorrect command letter for argument packet, exptected 'A'\n";
1110 printf("set_program_arguments (\n");
1111 do
1112 {
1113 my $arg_len = get_uint(\@_);
1114 get_exptected_char(\@_, ',') or die "error: missing comma after argument length...?\n";
1115 my $arg_idx = get_uint(\@_);
1116 get_exptected_char(\@_, ',') or die "error: missing comma after argument number...?\n";
1117
1118 my $arg = '';
1119 my $num_hex8_bytes = $arg_len/2;
1120 for (1 .. $num_hex8_bytes)
1121 {
1122 $arg .= sprintf("%c", get8(\@_))
1123 }
1124 printf(" <%3u> argv[%u] = '%s'\n", $arg_len, $arg_idx, $arg);
1125 if (@_ > 0)
1126 {
1127 get_exptected_char(\@_, ',') or die "error: missing comma after argument argument ASCII hex bytes...?\n";
1128 }
1129 } while (@_ > 0);
1130 printf(" )\n");
1131}
1132
1133
1134#----------------------------------------------------------------------
1135# 'z' and 'Z' command
1136#----------------------------------------------------------------------
1137sub dump_bp_wp_command
1138{
1139 my $cmd = shift;
1140 my $type = shift;
1141 shift; # Skip ','
1142 my $address = get_addr(\@_);
1143 shift; # Skip ','
1144 my $length = join('',@_);
1145 if ($cmd eq 'z')
1146 {
1147 printf("remove $point_types[$type]($addr_format, %d)\n", $address, $length);
1148 }
1149 else
1150 {
1151 printf("insert $point_types[$type]($addr_format, %d)\n", $address, $length);
1152 }
1153}
1154
1155
1156#----------------------------------------------------------------------
1157# 'X' command
1158#----------------------------------------------------------------------
1159sub dump_write_mem_binary_cmd
1160{
1161 my $cmd = shift;
1162 my $address = get_addr(\@_);
1163 shift; # Skip ','
1164
1165 my ($length, $binary) = split(/:/, join('',@_));
1166 printf("write_mem_binary ( $addr_format, %d, %s)\n", $address, $length, $binary);
1167
1168}
1169
1170#----------------------------------------------------------------------
1171# 'M' command
1172#----------------------------------------------------------------------
1173sub dump_write_mem_cmd
1174{
1175 my $cmd = shift;
1176 my $address = get_addr(\@_);
1177 shift; # Skip ','
1178 my ($length, $hex_bytes) = split(/:/, join('',@_));
1179# printf("write_mem ( $addr_format, %d, %s)\n", $address, $length, $hex_bytes);
1180 printf("write_mem ( addr = $addr_format, len = %d (0x%x), bytes = ", $address, $length, $length);
1181 splice(@_, 0, length($length)+1);
1182
1183 my $curr_address = $address;
1184 my $nibble;
1185 my $nibble_count = 0;
1186 my $max_nibbles_per_line = 2 * $max_bytes_per_line;
1187 foreach $nibble (@_)
1188 {
1189 (($nibble_count % 2) == 0) and print ' ';
1190 print $nibble;
1191 $nibble_count++;
1192 }
1193
1194 # If the memory to write is 2 or 4 bytes, print it out in native format
1195 # instead of just as bytes.
1196 if (@_ == 4)
1197 {
1198 printf(" ( 0x%4.4x )", get16(\@_));
1199 }
1200 elsif (@_ == 8)
1201 {
1202 printf(" ( 0x%8.8x )", get32(\@_));
1203 }
1204 print " )\n";
1205
1206}
1207
1208#----------------------------------------------------------------------
1209# 'v' command
1210#----------------------------------------------------------------------
1211our $extended_rsp_callback = 0;
1212sub dump_extended_cmd
1213{
1214 $extended_rsp_callback = 0;
1215 if (join('', @_[0..4]) eq "vCont")
1216 {
1217 dump_extended_continue_cmd(splice(@_,5));
1218 }
1219 elsif (join('', @_[0..11]) eq 'vAttachWait;')
1220 {
1221 dump_attach_wait_command (splice(@_,12));
1222 }
1223}
1224
1225#----------------------------------------------------------------------
1226# 'v' response
1227#----------------------------------------------------------------------
1228sub dump_extended_rsp
1229{
1230 if ($extended_rsp_callback)
1231 {
1232 &$extended_rsp_callback(@_);
1233 }
1234 $extended_rsp_callback = 0;
1235}
1236
1237#----------------------------------------------------------------------
1238# 'vAttachWait' command
1239#----------------------------------------------------------------------
1240sub dump_attach_wait_command
1241{
Greg Claytoneae5e262011-05-20 02:00:47 +00001242 print "attach_wait ( ";
1243 while (@_)
1244 {
1245 printf("%c", get8(\@_))
1246 }
1247 printf " )\n";
1248
1249}
1250
1251#----------------------------------------------------------------------
1252# 'vCont' command
1253#----------------------------------------------------------------------
1254sub dump_extended_continue_cmd
1255{
Greg Claytoneae5e262011-05-20 02:00:47 +00001256 print "extended_continue ( ";
1257 my $cmd = shift;
1258 if ($cmd eq '?')
1259 {
1260 print "list supported modes )\n";
1261 $extended_rsp_callback = \&dump_extended_continue_rsp;
1262 }
1263 elsif ($cmd eq ';')
1264 {
1265 $extended_rsp_callback = \&dump_stop_reply_packet;
1266 my $i = 0;
1267 while ($#_ >= 0)
1268 {
1269 if ($i > 0)
1270 {
1271 print ", ";
1272 }
1273 my $continue_cmd = shift;
1274 my $tmp;
1275 if ($continue_cmd eq 'c')
1276 {
1277 print "continue";
1278 }
1279 elsif ($continue_cmd eq 'C')
1280 {
1281 print "continue with signal ";
1282 print shift;
1283 print shift;
1284 }
1285 elsif ($continue_cmd eq 's')
1286 {
1287 print "step";
1288 }
1289 elsif ($continue_cmd eq 'S')
1290 {
1291 print "step with signal ";
1292 print shift;
1293 print shift;
1294 }
1295
1296 if ($_[0] eq ':')
1297 {
1298 shift; # Skip ':'
1299 print " for thread ";
1300 while ($#_ >= 0)
1301 {
1302 $tmp = shift;
1303 if (length($tmp) > 0 && $tmp ne ';') {
1304 print $tmp;
1305 } else {
1306 last;
1307 }
1308 }
1309 }
1310 $i++;
1311 }
1312
1313 printf " )\n";
1314 }
1315}
1316
1317#----------------------------------------------------------------------
1318# 'vCont' response
1319#----------------------------------------------------------------------
1320sub dump_extended_continue_rsp
1321{
Greg Clayton125628c2011-06-02 22:21:38 +00001322 if (scalar(@_) == 0)
1323 {
1324 print "$unimplemented_str\n";
1325 }
1326 else
1327 {
1328 print "extended_continue supports " . join('',@_) . "\n";
1329 }
Greg Claytoneae5e262011-05-20 02:00:47 +00001330}
1331
1332#----------------------------------------------------------------------
1333# Dump the command ascii for any unknown commands
1334#----------------------------------------------------------------------
1335sub dump_other_cmd
1336{
1337 print "other = " . join('',@_) . "\n";
1338}
1339
1340#----------------------------------------------------------------------
1341# Check to see if the response was unsupported with appropriate checksum
1342#----------------------------------------------------------------------
1343sub rsp_is_unsupported
1344{
1345 return join('',@_) eq "#00";
1346}
1347
1348#----------------------------------------------------------------------
1349# Check to see if the response was "OK" with appropriate checksum
1350#----------------------------------------------------------------------
1351sub rsp_is_OK
1352{
1353 return join('',@_) eq "OK#9a";
1354}
1355
1356#----------------------------------------------------------------------
1357# Dump a response for an unknown command
1358#----------------------------------------------------------------------
1359sub dump_other_rsp
1360{
1361 print "other = " . join('',@_) . "\n";
1362}
1363
1364#----------------------------------------------------------------------
1365# Get a byte from the ascii string assuming that the 2 nibble ascii
1366# characters are in hex.
1367#
1368# The argument for this function needs to be a reference to an array
1369# that contains single character strings and the array will get
1370# updated by shifting characters off the front of it (no leading # "0x")
1371#----------------------------------------------------------------------
1372sub get8
1373{
1374 my $arrayref = shift;
1375 my $val = hex(shift(@$arrayref) . shift(@$arrayref));
1376 return $val;
1377}
1378
1379#----------------------------------------------------------------------
1380# Get a 16 bit integer and swap if $swap global is set to a non-zero
1381# value.
1382#
1383# The argument for this function needs to be a reference to an array
1384# that contains single character strings and the array will get
1385# updated by shifting characters off the front of it (no leading # "0x")
1386#----------------------------------------------------------------------
1387sub get16
1388{
1389 my $arrayref = shift;
1390 my $val = 0;
1391 if ($swap)
1392 {
1393 $val = get8($arrayref) |
1394 get8($arrayref) << 8;
1395 }
1396 else
1397 {
1398 $val = get8($arrayref) << 8 |
1399 get8($arrayref) ;
1400 }
1401 return $val;
1402}
1403
1404#----------------------------------------------------------------------
1405# Get a 32 bit integer and swap if $swap global is set to a non-zero
1406# value.
1407#
1408# The argument for this function needs to be a reference to an array
1409# that contains single character strings and the array will get
1410# updated by shifting characters off the front of it (no leading # "0x")
1411#----------------------------------------------------------------------
1412sub get32
1413{
1414 my $arrayref = shift;
1415 my $val = 0;
1416 if ($swap)
1417 {
1418 $val = get8($arrayref) |
1419 get8($arrayref) << 8 |
1420 get8($arrayref) << 16 |
1421 get8($arrayref) << 24 ;
1422 }
1423 else
1424 {
1425 $val = get8($arrayref) << 24 |
1426 get8($arrayref) << 16 |
1427 get8($arrayref) << 8 |
1428 get8($arrayref) ;
1429 }
1430 return $val;
1431}
1432
1433#----------------------------------------------------------------------
1434# Get a 64 bit hex value as a string
1435#
1436# The argument for this function needs to be a reference to an array
1437# that contains single character strings and the array will get
1438# updated by shifting characters off the front of it (no leading # "0x")
1439#----------------------------------------------------------------------
1440sub get64
1441{
1442 my $arrayref = shift;
1443 my $val = '';
1444 my @nibbles;
1445 if ($swap)
1446 {
1447 push @nibbles, splice(@$arrayref, 14, 2);
1448 push @nibbles, splice(@$arrayref, 12, 2);
1449 push @nibbles, splice(@$arrayref, 10, 2);
1450 push @nibbles, splice(@$arrayref, 8, 2);
1451 push @nibbles, splice(@$arrayref, 6, 2);
1452 push @nibbles, splice(@$arrayref, 4, 2);
1453 push @nibbles, splice(@$arrayref, 2, 2);
1454 push @nibbles, splice(@$arrayref, 0, 2);
1455 }
1456 else
1457 {
1458 (@nibbles) = splice(@$arrayref, 0, 24);
1459 }
1460 $val = join('', @nibbles);
1461 return $val;
1462}
1463
1464#----------------------------------------------------------------------
1465# Get a 80 bit hex value as a string
1466#
1467# The argument for this function needs to be a reference to an array
1468# that contains single character strings and the array will get
1469# updated by shifting characters off the front of it (no leading # "0x")
1470#----------------------------------------------------------------------
1471sub get80
1472{
1473 my $arrayref = shift;
1474 my $val = '';
1475 my @nibbles;
1476 if ($swap)
1477 {
1478 push @nibbles, splice(@$arrayref, 18, 2);
1479 push @nibbles, splice(@$arrayref, 16, 2);
1480 push @nibbles, splice(@$arrayref, 14, 2);
1481 push @nibbles, splice(@$arrayref, 12, 2);
1482 push @nibbles, splice(@$arrayref, 10, 2);
1483 push @nibbles, splice(@$arrayref, 8, 2);
1484 push @nibbles, splice(@$arrayref, 6, 2);
1485 push @nibbles, splice(@$arrayref, 4, 2);
1486 push @nibbles, splice(@$arrayref, 2, 2);
1487 push @nibbles, splice(@$arrayref, 0, 2);
1488 }
1489 else
1490 {
1491 (@nibbles) = splice(@$arrayref, 0, 24);
1492 }
1493 $val = join('', @nibbles);
1494 return $val;
1495}
1496
1497#----------------------------------------------------------------------
1498# Get a 96 bit hex value as a string
1499#
1500# The argument for this function needs to be a reference to an array
1501# that contains single character strings and the array will get
1502# updated by shifting characters off the front of it (no leading # "0x")
1503#----------------------------------------------------------------------
1504sub get96
1505{
1506 my $arrayref = shift;
1507 my $val = '';
1508 my @nibbles;
1509 if ($swap)
1510 {
1511 push @nibbles, splice(@$arrayref, 22, 2);
1512 push @nibbles, splice(@$arrayref, 20, 2);
1513 push @nibbles, splice(@$arrayref, 18, 2);
1514 push @nibbles, splice(@$arrayref, 16, 2);
1515 push @nibbles, splice(@$arrayref, 14, 2);
1516 push @nibbles, splice(@$arrayref, 12, 2);
1517 push @nibbles, splice(@$arrayref, 10, 2);
1518 push @nibbles, splice(@$arrayref, 8, 2);
1519 push @nibbles, splice(@$arrayref, 6, 2);
1520 push @nibbles, splice(@$arrayref, 4, 2);
1521 push @nibbles, splice(@$arrayref, 2, 2);
1522 push @nibbles, splice(@$arrayref, 0, 2);
1523 }
1524 else
1525 {
1526 (@nibbles) = splice(@$arrayref, 0, 24);
1527 }
1528 $val = join('', @nibbles);
1529 return $val;
1530}
1531
1532#----------------------------------------------------------------------
1533# Get a 128 bit hex value as a string
1534#
1535# The argument for this function needs to be a reference to an array
1536# that contains single character strings and the array will get
1537# updated by shifting characters off the front of it (no leading # "0x")
1538#----------------------------------------------------------------------
1539sub get128
1540{
1541 my $arrayref = shift;
1542 my $val = '';
1543 my @nibbles;
1544 if ($swap)
1545 {
1546 push @nibbles, splice(@$arrayref, 30, 2);
1547 push @nibbles, splice(@$arrayref, 28, 2);
1548 push @nibbles, splice(@$arrayref, 26, 2);
1549 push @nibbles, splice(@$arrayref, 24, 2);
1550 push @nibbles, splice(@$arrayref, 22, 2);
1551 push @nibbles, splice(@$arrayref, 20, 2);
1552 push @nibbles, splice(@$arrayref, 18, 2);
1553 push @nibbles, splice(@$arrayref, 16, 2);
1554 push @nibbles, splice(@$arrayref, 14, 2);
1555 push @nibbles, splice(@$arrayref, 12, 2);
1556 push @nibbles, splice(@$arrayref, 10, 2);
1557 push @nibbles, splice(@$arrayref, 8, 2);
1558 push @nibbles, splice(@$arrayref, 6, 2);
1559 push @nibbles, splice(@$arrayref, 4, 2);
1560 push @nibbles, splice(@$arrayref, 2, 2);
1561 push @nibbles, splice(@$arrayref, 0, 2);
1562 }
1563 else
1564 {
1565 (@nibbles) = splice(@$arrayref, 0, 24);
1566 }
1567 $val = join('', @nibbles);
1568 return $val;
1569}
1570
1571#----------------------------------------------------------------------
1572# Get a an unsigned integer value by grabbing items off the front of
1573# the array stopping when a non-digit char string is encountered.
1574#
1575# The argument for this function needs to be a reference to an array
1576# that contains single character strings and the array will get
1577# updated by shifting characters off the front of it
1578#----------------------------------------------------------------------
1579sub get_uint
1580{
1581 my $arrayref = shift;
1582 @$arrayref == 0 and return 0;
1583 my $val = 0;
1584 while ($$arrayref[0] =~ /[0-9]/)
1585 {
1586 $val = $val * 10 + int(shift(@$arrayref));
1587 }
1588 return $val;
1589}
1590
1591#----------------------------------------------------------------------
1592# Check the first character in the array and if it matches the expected
1593# character, return that character, else return undef;
1594#
1595# The argument for this function needs to be a reference to an array
1596# that contains single character strings and the array will get
1597# updated by shifting characters off the front of it. If the expected
1598# character doesn't match, it won't touch the array. If the first
1599# character does match, it will shift it off and return it.
1600#----------------------------------------------------------------------
1601sub get_exptected_char
1602{
1603 my $arrayref = shift;
1604 my $expected_char = shift;
1605 if ($expected_char eq $$arrayref[0])
1606 {
1607 return shift(@$arrayref);
1608 }
1609 return undef;
1610}
1611#----------------------------------------------------------------------
1612# Get a hex value by grabbing items off the front of the array and
1613# stopping when a non-hex char string is encountered.
1614#
1615# The argument for this function needs to be a reference to an array
1616# that contains single character strings and the array will get
1617# updated by shifting characters off the front of it (no leading # "0x")
1618#----------------------------------------------------------------------
1619sub get_hex
1620{
1621 my $arrayref = shift;
1622 my $my_swap = @_ ? shift : 0;
1623 my $shift = 0;
1624 my $val = 0;
1625 while ($$arrayref[0] =~ /[0-9a-fA-F]/)
1626 {
1627 if ($my_swap)
1628 {
1629 my $byte = hex(shift(@$arrayref)) << 4 | hex(shift(@$arrayref));
1630 $val |= $byte << $shift;
1631 $shift += 8;
1632 }
1633 else
1634 {
1635 $val <<= 4;
1636 $val |= hex(shift(@$arrayref));
1637 }
1638 }
1639 return $val;
1640}
1641
1642#----------------------------------------------------------------------
1643# Get an address value by grabbing items off the front of the array.
1644#
1645# The argument for this function needs to be a reference to an array
1646# that contains single character strings and the array will get
1647# updated by shifting characters off the front of it (no leading # "0x")
1648#----------------------------------------------------------------------
1649sub get_addr
1650{
1651 get_hex(shift);
1652}
1653
Greg Clayton125628c2011-06-02 22:21:38 +00001654sub get_hex_string
1655{
1656 my $arrayref = shift;
1657 my $str = '';
1658 while ($$arrayref[0] =~ /[0-9a-fA-F]/ and $$arrayref[1] =~ /[0-9a-fA-F]/)
1659 {
1660 my $hi_nibble = hex(shift(@$arrayref));
1661 my $lo_nibble = hex(shift(@$arrayref));
1662 my $byte = ($hi_nibble << 4) | $lo_nibble;
1663 $str .= chr($byte);
1664 }
1665 return $str;
1666}
1667
Greg Claytoneae5e262011-05-20 02:00:47 +00001668sub dump_stop_reply_data
1669{
1670 while ($#_ >= 0)
1671 {
1672 last unless ($_[0] ne '#');
1673
1674
1675 my $key = '';
1676 my $value = '';
1677 if ($_[0] =~ /[0-9a-fA-F]/ && $_[1] =~ /[0-9a-fA-F]/)
1678 {
1679 my $reg_num = get8(\@_);
1680 shift(@_); # Skip ':'
1681 if (defined ($registers_aref) && $reg_num < @$registers_aref)
1682 {
1683 dump_register_value(1, \@_, $reg_num);
1684 print "\n";
1685 shift(@_); # Skip ';'
1686 next;
1687 }
1688 $key = sprintf("reg %u", $reg_num);
1689 }
1690 my $char;
1691
1692 if (length($key) == 0)
1693 {
1694 while (1)
1695 {
1696 $char = shift(@_);
1697 if (length($char) == 0 or $char eq ':' or $char eq '#') { last; }
1698 $key .= $char;
1699 }
1700 }
1701
1702 while (1)
1703 {
1704 $char = shift(@_);
1705 if (length($char) == 0 or $char eq ';' or $char eq '#') { last; }
1706 $value .= $char;
1707 }
1708 printf("\t%*s = %s\n", $max_register_name_len, $key, $value);
1709 }
1710}
1711
1712#----------------------------------------------------------------------
1713# Dumps a Stop Reply Packet which happens in response to a step,
1714# continue, last signal, and probably a few other commands.
1715#----------------------------------------------------------------------
1716sub dump_stop_reply_packet
1717{
1718 my $what = shift(@_);
1719 if ($what eq 'S')
1720 {
1721 print 'signal ( 0x' . shift(@_) . shift(@_) . " )\n";
1722 }
1723 elsif ($what eq 'T')
1724 {
1725 print 'signal ( 0x' . shift(@_) . shift(@_) . " )\n";
1726 dump_stop_reply_data (@_);
1727 }
1728 elsif ($what eq 'W')
1729 {
1730 print 'process_exited( ' . shift(@_) . shift(@_) . " )\n";
1731 }
1732 elsif ($what eq 'X')
1733 {
1734 print 'process_terminated( ' . shift(@_) . shift(@_) . " )\n";
1735 }
1736 elsif ($what eq 'O')
1737 {
1738 my $console_output = '';
1739 my $num_hex8_bytes = @_/2;
1740 for (1 .. $num_hex8_bytes)
1741 {
1742 $console_output .= sprintf("%c", get8(\@_))
1743 }
1744
1745 print "program_console_output('$console_output')\n";
1746 }
1747}
1748
1749#----------------------------------------------------------------------
1750# '?' command
1751#----------------------------------------------------------------------
1752sub dump_last_signal_cmd
1753{
1754 my $cmd = shift;
1755 print 'last_signal (' . join('',@_) . ")\n";
1756}
1757
1758sub dump_raw_command
1759{
1760 my $cmd_aref = shift;
1761 my $callback_ref;
1762 $curr_cmd = $$cmd_aref[0];
1763 $curr_cmd eq '_' and $curr_cmd .= $$cmd_aref[1];
1764
1765 $callback_ref = $cmd_callbacks{$curr_cmd};
1766 if ($callback_ref)
1767 {
1768 &$callback_ref(@$cmd_aref);
1769 }
1770 else
1771 {
1772 # Strip the command byte for responses since we injected that above
1773 dump_other_cmd(@$cmd_aref);
1774 }
1775}
1776
1777sub dump_standard_response
1778{
1779 my $cmd_aref = shift;
1780
Greg Clayton125628c2011-06-02 22:21:38 +00001781 my $cmd_len = scalar(@$cmd_aref);
1782 if ($cmd_len == 0)
Greg Claytoneae5e262011-05-20 02:00:47 +00001783 {
Greg Clayton125628c2011-06-02 22:21:38 +00001784 print "$unimplemented_str\n";
Greg Claytoneae5e262011-05-20 02:00:47 +00001785 return 1;
1786 }
1787
1788 my $response = join('', @$cmd_aref);
1789 if ($response eq 'OK')
1790 {
1791 print "$success_str\n";
1792 return 1;
1793 }
1794
Greg Clayton125628c2011-06-02 22:21:38 +00001795 if ($cmd_len == 3 and index($response, 'E') == 0)
Greg Claytoneae5e262011-05-20 02:00:47 +00001796 {
1797 print "ERROR: " . substr($response, 1) . "\n";
1798 return 1;
1799 }
1800
1801 return 0;
1802}
1803sub dump_raw_response
1804{
1805 my $cmd_aref = shift;
1806 my $callback_ref;
1807
1808 $callback_ref = $rsp_callbacks{$curr_cmd};
1809
1810 if ($callback_ref)
1811 {
1812 &$callback_ref(@$cmd_aref);
1813 }
1814 else
1815 {
1816 dump_standard_response($cmd_aref) or dump_other_rsp(@$cmd_aref);
1817 }
1818
1819}
1820#----------------------------------------------------------------------
1821# Dumps any command and handles simple error checking on the responses
1822# for commands that are unsupported or OK.
1823#----------------------------------------------------------------------
1824sub dump_command
1825{
1826 my $cmd_str = shift;
1827
1828 # Dump the original command string if verbose is on
1829 if ($opt_v)
1830 {
1831 print "dump_command($cmd_str)\n ";
1832 }
1833
1834 my @cmd_chars = extract_command($cmd_str);
1835 my $is_cmd = 1;
1836
1837 my $cmd = $cmd_chars[0];
1838 if ($cmd eq '$')
1839 {
1840 $is_cmd = 0; # Note that this is a reply
1841 $cmd = $curr_cmd; # set the command byte appropriately
1842 shift @cmd_chars; # remove the '$' from the cmd bytes
1843 }
1844
1845 # Check for common responses across all commands and handle them
1846 # if we can
1847 if ( $is_cmd == 0 )
1848 {
1849 if (rsp_is_unsupported(@cmd_chars))
1850 {
Greg Clayton125628c2011-06-02 22:21:38 +00001851 print "$unimplemented_str\n";
Greg Claytoneae5e262011-05-20 02:00:47 +00001852 return;
1853 }
1854 elsif (rsp_is_OK(@cmd_chars))
1855 {
1856 print "$success_str\n";
1857 return;
1858 }
1859 # Strip the checksum information for responses
1860 strip_checksum(\@cmd_chars);
1861 }
1862
1863 my $callback_ref;
1864 if ($is_cmd) {
1865 $callback_ref = $cmd_callbacks{$cmd};
1866 } else {
1867 $callback_ref = $rsp_callbacks{$cmd};
1868 }
1869
1870 if ($callback_ref)
1871 {
1872 &$callback_ref(@cmd_chars);
1873 }
1874 else
1875 {
1876 # Strip the command byte for responses since we injected that above
1877 if ($is_cmd) {
1878 dump_other_cmd(@cmd_chars);
1879 } else {
1880 dump_other_rsp(@cmd_chars);
1881 }
1882
1883 }
1884}
1885
1886
1887#----------------------------------------------------------------------
1888# Process a gdbserver log line by looking for getpkt and putkpt and
1889# tossing any other lines.
1890#----------------------------------------------------------------------
1891sub process_log_line
1892{
1893 my $line = shift;
1894 #($opt_v and $opt_g) and print "# $line";
1895 my $extract_cmd = 0;
1896 if ($line =~ /getpkt /)
1897 {
1898 $extract_cmd = 1;
1899 print "\n--> ";
1900 }
1901 elsif ($line =~ /putpkt /)
1902 {
1903 $extract_cmd = 1;
1904 print "<-- ";
1905 }
1906 elsif ($line =~ /.*Sent: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/)
1907 {
1908 $opt_g and print "maintenance dump-packets command: $1\n";
1909 my @raw_cmd_bytes = split(/ */, $1);
1910 print "\n--> ";
1911 dump_raw_command(\@raw_cmd_bytes);
1912 process_log_line($2);
1913 }
1914 elsif ($line =~ /.*Recvd: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/)
1915 {
1916 $opt_g and print "maintenance dump-packets reply: $1\n";
1917 my @raw_rsp_bytes = split(/ */, $1);
1918 print "<-- ";
1919 dump_raw_response(\@raw_rsp_bytes);
1920 print "\n";
1921 }
1922 elsif ($line =~ /getpkt: (.*)/)
1923 {
1924 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/)
1925 {
1926 $opt_g and print "command: $1\n";
1927 my @raw_cmd_bytes = split(/ */, $1);
1928 print "--> ";
1929 dump_raw_command(\@raw_cmd_bytes);
1930 }
1931 elsif ($1 =~ /\+/)
1932 {
1933 #print "--> ACK\n";
1934 }
1935 elsif ($1 =~ /-/)
1936 {
1937 #print "--> NACK\n";
1938 }
1939 }
1940 elsif ($line =~ /putpkt: (.*)/)
1941 {
1942 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/)
1943 {
1944 $opt_g and print "response: $1\n";
1945 my @raw_rsp_bytes = split(/ */, $1);
1946 print "<-- ";
1947 dump_raw_response(\@raw_rsp_bytes);
1948 print "\n";
1949 }
1950 elsif ($1 =~ /\+/)
1951 {
1952 #print "<-- ACK\n";
1953 }
1954 elsif ($1 =~ /-/)
1955 {
1956 #print "<-- NACK\n";
1957 }
1958 }
1959 elsif ($line =~ /send packet: (.*)/)
1960 {
1961 if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/)
1962 {
1963 $opt_g and print "command: $1\n";
1964 my @raw_cmd_bytes = split(/ */, $1);
1965 print "--> ";
1966 dump_raw_command(\@raw_cmd_bytes);
1967 }
1968 elsif ($1 =~ /\+/)
1969 {
1970 #print "--> ACK\n";
1971 }
1972 elsif ($1 =~ /-/)
1973 {
1974 #print "--> NACK\n";
1975 }
1976 }
1977 elsif ($line =~ /read packet: (.*)/)
1978 {
Greg Clayton125628c2011-06-02 22:21:38 +00001979 if ($1 =~ /\$([^#]*)#[0-9a-fA-F]{2}/)
Greg Claytoneae5e262011-05-20 02:00:47 +00001980 {
1981 $opt_g and print "response: $1\n";
1982 my @raw_rsp_bytes = split(/ */, $1);
1983 print "<-- ";
1984 dump_raw_response(\@raw_rsp_bytes);
1985 print "\n";
1986 }
1987 elsif ($1 =~ /\+/)
1988 {
1989 #print "<-- ACK\n";
1990 }
1991 elsif ($1 =~ /-/)
1992 {
1993 #print "<-- NACK\n";
1994 }
1995 }
1996 elsif ($line =~ /Sending packet: \$([^#]+)#[0-9a-fA-F]{2}\.\.\.(.*)/)
1997 {
1998 $opt_g and print "command: $1\n";
1999 my @raw_cmd_bytes = split(/ */, $1);
2000 print "\n--> ";
2001 dump_raw_command(\@raw_cmd_bytes);
2002 process_log_line($2);
2003 }
2004 elsif ($line =~ /Packet received: (.*)/)
2005 {
2006 $opt_g and print "response: $1\n";
2007 my @raw_rsp_bytes = split(/ */, $1);
2008 print "<-- ";
2009 dump_raw_response(\@raw_rsp_bytes);
2010 print "\n";
2011 }
2012
2013 if ($extract_cmd)
2014 {
2015 my $beg = index($line, '("') + 2;
2016 my $end = rindex($line, '");');
2017 dump_command(substr($line, $beg, $end - $beg));
2018 }
2019}
2020
2021
2022our $line_num = 0;
2023while(<>)
2024{
2025 $line_num++;
2026 $opt_q or printf("# %5d: $_", $line_num);
2027 process_log_line($_);
2028}
2029
2030
2031
2032
2033
2034