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