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