Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / core / gdbstub.c
1 /*
2  * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /**
23  * @file
24  *
25  * GDB stub for remote debugging
26  *
27  */
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <byteswap.h>
34 #include <ipxe/gdbstub.h>
35 #include "gdbmach.h"
36
37 enum {
38         POSIX_EINVAL = 0x1c,  /* used to report bad arguments to GDB */
39         SIZEOF_PAYLOAD = 256, /* buffer size of GDB payload data */
40 };
41
42 struct gdbstub {
43         struct gdb_transport *trans;
44         int exit_handler; /* leave interrupt handler */
45
46         int signo;
47         gdbreg_t *regs;
48
49         void ( * parse ) ( struct gdbstub *stub, char ch );
50         uint8_t cksum1;
51
52         /* Buffer for payload data when parsing a packet.  Once the
53          * packet has been received, this buffer is used to hold
54          * the reply payload. */
55         char buf [ SIZEOF_PAYLOAD + 4 ]; /* $...PAYLOAD...#XX */
56         char *payload;                   /* start of payload */
57         int len;                         /* length of payload */
58 };
59
60 /* Packet parser states */
61 static void gdbstub_state_new ( struct gdbstub *stub, char ch );
62 static void gdbstub_state_data ( struct gdbstub *stub, char ch );
63 static void gdbstub_state_cksum1 ( struct gdbstub *stub, char ch );
64 static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch );
65 static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch );
66
67 static uint8_t gdbstub_from_hex_digit ( char ch ) {
68         return ( isdigit ( ch ) ? ch - '0' : tolower ( ch ) - 'a' + 0xa ) & 0xf;
69 }
70
71 static uint8_t gdbstub_to_hex_digit ( uint8_t b ) {
72         b &= 0xf;
73         return ( b < 0xa ? '0' : 'a' - 0xa ) + b;
74 }
75
76 /*
77  * To make reading/writing device memory atomic, we check for
78  * 2- or 4-byte aligned operations and handle them specially.
79  */
80
81 static void gdbstub_from_hex_buf ( char *dst, char *src, int lenbytes ) {
82         if ( lenbytes == 2 && ( ( unsigned long ) dst & 0x1 ) == 0 ) {
83                 uint16_t i = gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
84                         gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
85                         gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
86                         gdbstub_from_hex_digit ( src [ 1 ] );
87                 * ( uint16_t * ) dst = cpu_to_le16 ( i );
88         } else if ( lenbytes == 4 && ( ( unsigned long ) dst & 0x3 ) == 0 ) {
89                 uint32_t i = gdbstub_from_hex_digit ( src [ 6 ] ) << 28 |
90                         gdbstub_from_hex_digit ( src [ 7 ] ) << 24 |
91                         gdbstub_from_hex_digit ( src [ 4 ] ) << 20 |
92                         gdbstub_from_hex_digit ( src [ 5 ] ) << 16 |
93                         gdbstub_from_hex_digit ( src [ 2 ] ) << 12 |
94                         gdbstub_from_hex_digit ( src [ 3 ] ) << 8 |
95                         gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
96                         gdbstub_from_hex_digit ( src [ 1 ] );
97                 * ( uint32_t * ) dst = cpu_to_le32 ( i );
98         } else {
99                 while ( lenbytes-- > 0 ) {
100                         *dst++ = gdbstub_from_hex_digit ( src [ 0 ] ) << 4 |
101                                 gdbstub_from_hex_digit ( src [ 1 ] );
102                         src += 2;
103                 }
104         }
105 }
106
107 static void gdbstub_to_hex_buf ( char *dst, char *src, int lenbytes ) {
108         if ( lenbytes == 2 && ( ( unsigned long ) src & 0x1 ) == 0 ) {
109                 uint16_t i = cpu_to_le16 ( * ( uint16_t * ) src );
110                 dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
111                 dst [ 1 ] = gdbstub_to_hex_digit ( i );
112                 dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
113                 dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
114         } else if ( lenbytes == 4 && ( ( unsigned long ) src & 0x3 ) == 0 ) {
115                 uint32_t i = cpu_to_le32 ( * ( uint32_t * ) src );
116                 dst [ 0 ] = gdbstub_to_hex_digit ( i >> 4 );
117                 dst [ 1 ] = gdbstub_to_hex_digit ( i );
118                 dst [ 2 ] = gdbstub_to_hex_digit ( i >> 12 );
119                 dst [ 3 ] = gdbstub_to_hex_digit ( i >> 8 );
120                 dst [ 4 ] = gdbstub_to_hex_digit ( i >> 20 );
121                 dst [ 5 ] = gdbstub_to_hex_digit ( i >> 16);
122                 dst [ 6 ] = gdbstub_to_hex_digit ( i >> 28 );
123                 dst [ 7 ] = gdbstub_to_hex_digit ( i >> 24 );
124         } else {
125                 while ( lenbytes-- > 0 ) {
126                         *dst++ = gdbstub_to_hex_digit ( *src >> 4 );
127                         *dst++ = gdbstub_to_hex_digit ( *src );
128                         src++;
129                 }
130         }
131 }
132
133 static uint8_t gdbstub_cksum ( char *data, int len ) {
134         uint8_t cksum = 0;
135         while ( len-- > 0 ) {
136                 cksum += ( uint8_t ) *data++;
137         }
138         return cksum;
139 }
140
141 static void gdbstub_tx_packet ( struct gdbstub *stub ) {
142         uint8_t cksum = gdbstub_cksum ( stub->payload, stub->len );
143         stub->buf [ 0 ] = '$';
144         stub->buf [ stub->len + 1 ] = '#';
145         stub->buf [ stub->len + 2 ] = gdbstub_to_hex_digit ( cksum >> 4 );
146         stub->buf [ stub->len + 3 ] = gdbstub_to_hex_digit ( cksum );
147         stub->trans->send ( stub->buf, stub->len + 4 );
148         stub->parse = gdbstub_state_wait_ack;
149 }
150
151 /* GDB commands */
152 static void gdbstub_send_ok ( struct gdbstub *stub ) {
153         stub->payload [ 0 ] = 'O';
154         stub->payload [ 1 ] = 'K';
155         stub->len = 2;
156         gdbstub_tx_packet ( stub );
157 }
158
159 static void gdbstub_send_num_packet ( struct gdbstub *stub, char reply, int num ) {
160         stub->payload [ 0 ] = reply;
161         stub->payload [ 1 ] = gdbstub_to_hex_digit ( ( char ) num >> 4 );
162         stub->payload [ 2 ] = gdbstub_to_hex_digit ( ( char ) num );
163         stub->len = 3;
164         gdbstub_tx_packet ( stub );
165 }
166
167 /* Format is arg1,arg2,...,argn:data where argn are hex integers and data is not an argument */
168 static int gdbstub_get_packet_args ( struct gdbstub *stub, unsigned long *args, int nargs, int *stop_idx ) {
169         int i;
170         char ch = 0;
171         int argc = 0;
172         unsigned long val = 0;
173         for ( i = 1; i < stub->len && argc < nargs; i++ ) {
174                 ch = stub->payload [ i ];
175                 if ( ch == ':' ) {
176                         break;
177                 } else if ( ch == ',' ) {
178                         args [ argc++ ] = val;
179                         val = 0;
180                 } else {
181                         val = ( val << 4 ) | gdbstub_from_hex_digit ( ch );
182                 }
183         }
184         if ( stop_idx ) {
185                 *stop_idx = i;
186         }
187         if ( argc < nargs ) {
188                 args [ argc++ ] = val;
189         }
190         return ( ( i == stub->len || ch == ':' ) && argc == nargs );
191 }
192
193 static void gdbstub_send_errno ( struct gdbstub *stub, int errno ) {
194         gdbstub_send_num_packet ( stub, 'E', errno );
195 }
196
197 static void gdbstub_report_signal ( struct gdbstub *stub ) {
198         gdbstub_send_num_packet ( stub, 'S', stub->signo );
199 }
200
201 static void gdbstub_read_regs ( struct gdbstub *stub ) {
202         gdbstub_to_hex_buf ( stub->payload, ( char * ) stub->regs, GDBMACH_SIZEOF_REGS );
203         stub->len = GDBMACH_SIZEOF_REGS * 2;
204         gdbstub_tx_packet ( stub );
205 }
206
207 static void gdbstub_write_regs ( struct gdbstub *stub ) {
208         if ( stub->len != 1 + GDBMACH_SIZEOF_REGS * 2 ) {
209                 gdbstub_send_errno ( stub, POSIX_EINVAL );
210                 return;
211         }
212         gdbstub_from_hex_buf ( ( char * ) stub->regs, &stub->payload [ 1 ], GDBMACH_SIZEOF_REGS );
213         gdbstub_send_ok ( stub );
214 }
215
216 static void gdbstub_read_mem ( struct gdbstub *stub ) {
217         unsigned long args [ 2 ];
218         if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], NULL ) ) {
219                 gdbstub_send_errno ( stub, POSIX_EINVAL );
220                 return;
221         }
222         args [ 1 ] = ( args [ 1 ] < SIZEOF_PAYLOAD / 2 ) ? args [ 1 ] : SIZEOF_PAYLOAD / 2;
223         gdbstub_to_hex_buf ( stub->payload, ( char * ) args [ 0 ], args [ 1 ] );
224         stub->len = args [ 1 ] * 2;
225         gdbstub_tx_packet ( stub );
226 }
227
228 static void gdbstub_write_mem ( struct gdbstub *stub ) {
229         unsigned long args [ 2 ];
230         int colon;
231         if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], &colon ) ||
232                         colon >= stub->len || stub->payload [ colon ] != ':' ||
233                         ( stub->len - colon - 1 ) % 2 != 0 ) {
234                 gdbstub_send_errno ( stub, POSIX_EINVAL );
235                 return;
236         }
237         gdbstub_from_hex_buf ( ( char * ) args [ 0 ], &stub->payload [ colon + 1 ], ( stub->len - colon - 1 ) / 2 );
238         gdbstub_send_ok ( stub );
239 }
240
241 static void gdbstub_continue ( struct gdbstub *stub, int single_step ) {
242         gdbreg_t pc;
243         if ( stub->len > 1 && gdbstub_get_packet_args ( stub, &pc, 1, NULL ) ) {
244                 gdbmach_set_pc ( stub->regs, pc );
245         }
246         gdbmach_set_single_step ( stub->regs, single_step );
247         stub->exit_handler = 1;
248         /* Reply will be sent when we hit the next breakpoint or interrupt */
249 }
250
251 static void gdbstub_breakpoint ( struct gdbstub *stub ) {
252         unsigned long args [ 3 ];
253         int enable = stub->payload [ 0 ] == 'Z' ? 1 : 0;
254         if ( !gdbstub_get_packet_args ( stub, args, sizeof args / sizeof args [ 0 ], NULL ) ) {
255                 gdbstub_send_errno ( stub, POSIX_EINVAL );
256                 return;
257         }
258         if ( gdbmach_set_breakpoint ( args [ 0 ], args [ 1 ], args [ 2 ], enable ) ) {
259                 gdbstub_send_ok ( stub );
260         } else {
261                 /* Not supported */
262                 stub->len = 0;
263                 gdbstub_tx_packet ( stub );
264         }
265 }
266
267 static void gdbstub_rx_packet ( struct gdbstub *stub ) {
268         switch ( stub->payload [ 0 ] ) {
269                 case '?':
270                         gdbstub_report_signal ( stub );
271                         break;
272                 case 'g':
273                         gdbstub_read_regs ( stub );
274                         break;
275                 case 'G':
276                         gdbstub_write_regs ( stub );
277                         break;
278                 case 'm':
279                         gdbstub_read_mem ( stub );
280                         break;
281                 case 'M':
282                         gdbstub_write_mem ( stub );
283                         break;
284                 case 'c': /* Continue */
285                 case 'k': /* Kill */
286                 case 's': /* Step */
287                 case 'D': /* Detach */
288                         gdbstub_continue ( stub, stub->payload [ 0 ] == 's' );
289                         if ( stub->payload [ 0 ] == 'D' ) {
290                                 gdbstub_send_ok ( stub );
291                         }
292                         break;
293                 case 'Z': /* Insert breakpoint */
294                 case 'z': /* Remove breakpoint */
295                         gdbstub_breakpoint ( stub );
296                         break;
297                 default:
298                         stub->len = 0;
299                         gdbstub_tx_packet ( stub );
300                         break;
301         }
302 }
303
304 /* GDB packet parser */
305 static void gdbstub_state_new ( struct gdbstub *stub, char ch ) {
306         if ( ch == '$' ) {
307                 stub->len = 0;
308                 stub->parse = gdbstub_state_data;
309         }
310 }
311
312 static void gdbstub_state_data ( struct gdbstub *stub, char ch ) {
313         if ( ch == '#' ) {
314                 stub->parse = gdbstub_state_cksum1;
315         } else if ( ch == '$' ) {
316                 stub->len = 0; /* retry new packet */
317         } else {
318                 /* If the length exceeds our buffer, let the checksum fail */
319                 if ( stub->len < SIZEOF_PAYLOAD ) {
320                         stub->payload [ stub->len++ ] = ch;
321                 }
322         }
323 }
324
325 static void gdbstub_state_cksum1 ( struct gdbstub *stub, char ch ) {
326         stub->cksum1 = gdbstub_from_hex_digit ( ch ) << 4;
327         stub->parse = gdbstub_state_cksum2;
328 }
329
330 static void gdbstub_state_cksum2 ( struct gdbstub *stub, char ch ) {
331         uint8_t their_cksum;
332         uint8_t our_cksum;
333
334         stub->parse = gdbstub_state_new;
335         their_cksum = stub->cksum1 + gdbstub_from_hex_digit ( ch );
336         our_cksum = gdbstub_cksum ( stub->payload, stub->len );
337         if ( their_cksum == our_cksum ) {
338                 stub->trans->send ( "+", 1 );
339                 if ( stub->len > 0 ) {
340                         gdbstub_rx_packet ( stub );
341                 }
342         } else {
343                 stub->trans->send ( "-", 1 );
344         }
345 }
346
347 static void gdbstub_state_wait_ack ( struct gdbstub *stub, char ch ) {
348         if ( ch == '+' ) {
349                 stub->parse = gdbstub_state_new;
350         } else {
351                 /* This retransmit is very aggressive but necessary to keep
352                  * in sync with GDB. */
353                 gdbstub_tx_packet ( stub );
354         }
355 }
356
357 static void gdbstub_parse ( struct gdbstub *stub, char ch ) {
358         stub->parse ( stub, ch );
359 }
360
361 static struct gdbstub stub = {
362         .parse = gdbstub_state_new
363 };
364
365 void gdbstub_handler ( int signo, gdbreg_t *regs ) {
366         char packet [ SIZEOF_PAYLOAD + 4 ];
367         size_t len, i;
368
369         /* A transport must be set up */
370         if ( !stub.trans ) {
371                 return;
372         }
373
374         stub.signo = signo;
375         stub.regs = regs;
376         stub.exit_handler = 0;
377         gdbstub_report_signal ( &stub );
378         while ( !stub.exit_handler && ( len = stub.trans->recv ( packet, sizeof ( packet ) ) ) > 0 ) {
379                 for ( i = 0; i < len; i++ ) {
380                         gdbstub_parse ( &stub, packet [ i ] );
381                 }
382         }
383 }
384
385 struct gdb_transport *find_gdb_transport ( const char *name ) {
386         struct gdb_transport *trans;
387
388         for_each_table_entry ( trans, GDB_TRANSPORTS ) {
389                 if ( strcmp ( trans->name, name ) == 0 ) {
390                         return trans;
391                 }
392         }
393         return NULL;
394 }
395
396 void gdbstub_start ( struct gdb_transport *trans ) {
397         stub.trans = trans;
398         stub.payload = &stub.buf [ 1 ];
399         gdbmach_init();
400         gdbmach_breakpoint();
401 }