]> git.ipfire.org Git - people/ms/u-boot.git/blob - common/kgdb.c
Merge branch 'cleanups' into next
[people/ms/u-boot.git] / common / kgdb.c
1 /* taken from arch/ppc/kernel/ppc-stub.c */
2
3 /****************************************************************************
4
5 THIS SOFTWARE IS NOT COPYRIGHTED
6
7 HP offers the following for use in the public domain. HP makes no
8 warranty with regard to the software or its performance and the
9 user accepts the software "AS IS" with all faults.
10
11 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
12 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
13 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14
15 ****************************************************************************/
16
17 /****************************************************************************
18 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
19 *
20 * Module name: remcom.c $
21 * Revision: 1.34 $
22 * Date: 91/03/09 12:29:49 $
23 * Contributor: Lake Stevens Instrument Division$
24 *
25 * Description: low level support for gdb debugger. $
26 *
27 * Considerations: only works on target hardware $
28 *
29 * Written by: Glenn Engel $
30 * ModuleState: Experimental $
31 *
32 * NOTES: See Below $
33 *
34 * Modified for SPARC by Stu Grossman, Cygnus Support.
35 *
36 * This code has been extensively tested on the Fujitsu SPARClite demo board.
37 *
38 * To enable debugger support, two things need to happen. One, a
39 * call to set_debug_traps() is necessary in order to allow any breakpoints
40 * or error conditions to be properly intercepted and reported to gdb.
41 * Two, a breakpoint needs to be generated to begin communication. This
42 * is most easily accomplished by a call to breakpoint(). Breakpoint()
43 * simulates a breakpoint by executing a trap #1.
44 *
45 *************
46 *
47 * The following gdb commands are supported:
48 *
49 * command function Return value
50 *
51 * g return the value of the CPU registers hex data or ENN
52 * G set the value of the CPU registers OK or ENN
53 * qOffsets Get section offsets. Reply is Text=xxx;Data=yyy;Bss=zzz
54 *
55 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
56 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
57 *
58 * c Resume at current address SNN ( signal NN)
59 * cAA..AA Continue at address AA..AA SNN
60 *
61 * s Step one instruction SNN
62 * sAA..AA Step one instruction from AA..AA SNN
63 *
64 * k kill
65 *
66 * ? What was the last sigval ? SNN (signal NN)
67 *
68 * bBB..BB Set baud rate to BB..BB OK or BNN, then sets
69 * baud rate
70 *
71 * All commands and responses are sent with a packet which includes a
72 * checksum. A packet consists of
73 *
74 * $<packet info>#<checksum>.
75 *
76 * where
77 * <packet info> :: <characters representing the command or response>
78 * <checksum> :: <two hex digits computed as modulo 256 sum of <packetinfo>>
79 *
80 * When a packet is received, it is first acknowledged with either '+' or '-'.
81 * '+' indicates a successful transfer. '-' indicates a failed transfer.
82 *
83 * Example:
84 *
85 * Host: Reply:
86 * $m0,10#2a +$00010203040506070809101112131415#42
87 *
88 ****************************************************************************/
89
90 #include <common.h>
91
92 #include <kgdb.h>
93 #include <command.h>
94
95 #undef KGDB_DEBUG
96
97 /*
98 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
99 */
100 #define BUFMAX 1024
101 static char remcomInBuffer[BUFMAX];
102 static char remcomOutBuffer[BUFMAX];
103 static char remcomRegBuffer[BUFMAX];
104
105 static int initialized = 0;
106 static int kgdb_active = 0, first_entry = 1;
107 static struct pt_regs entry_regs;
108 static long error_jmp_buf[BUFMAX/2];
109 static int longjmp_on_fault = 0;
110 #ifdef KGDB_DEBUG
111 static int kdebug = 1;
112 #endif
113
114 static const char hexchars[]="0123456789abcdef";
115
116 /* Convert ch from a hex digit to an int */
117 static int
118 hex(unsigned char ch)
119 {
120 if (ch >= 'a' && ch <= 'f')
121 return ch-'a'+10;
122 if (ch >= '0' && ch <= '9')
123 return ch-'0';
124 if (ch >= 'A' && ch <= 'F')
125 return ch-'A'+10;
126 return -1;
127 }
128
129 /* Convert the memory pointed to by mem into hex, placing result in buf.
130 * Return a pointer to the last char put in buf (null).
131 */
132 static unsigned char *
133 mem2hex(char *mem, char *buf, int count)
134 {
135 unsigned char ch;
136
137 longjmp_on_fault = 1;
138 while (count-- > 0) {
139 ch = *mem++;
140 *buf++ = hexchars[ch >> 4];
141 *buf++ = hexchars[ch & 0xf];
142 }
143 *buf = 0;
144 longjmp_on_fault = 0;
145 return (unsigned char *)buf;
146 }
147
148 /* convert the hex array pointed to by buf into binary to be placed in mem
149 * return a pointer to the character AFTER the last byte fetched from buf.
150 */
151 static char *
152 hex2mem(char *buf, char *mem, int count)
153 {
154 int i, hexValue;
155 unsigned char ch;
156 char *mem_start = mem;
157
158 longjmp_on_fault = 1;
159 for (i=0; i<count; i++) {
160 if ((hexValue = hex(*buf++)) < 0)
161 kgdb_error(KGDBERR_NOTHEXDIG);
162 ch = hexValue << 4;
163 if ((hexValue = hex(*buf++)) < 0)
164 kgdb_error(KGDBERR_NOTHEXDIG);
165 ch |= hexValue;
166 *mem++ = ch;
167 }
168 kgdb_flush_cache_range((void *)mem_start, (void *)(mem - 1));
169 longjmp_on_fault = 0;
170
171 return buf;
172 }
173
174 /*
175 * While we find nice hex chars, build an int.
176 * Return number of chars processed.
177 */
178 static int
179 hexToInt(char **ptr, int *intValue)
180 {
181 int numChars = 0;
182 int hexValue;
183
184 *intValue = 0;
185
186 longjmp_on_fault = 1;
187 while (**ptr) {
188 hexValue = hex(**ptr);
189 if (hexValue < 0)
190 break;
191
192 *intValue = (*intValue << 4) | hexValue;
193 numChars ++;
194
195 (*ptr)++;
196 }
197 longjmp_on_fault = 0;
198
199 return (numChars);
200 }
201
202 /* scan for the sequence $<data>#<checksum> */
203 static void
204 getpacket(char *buffer)
205 {
206 unsigned char checksum;
207 unsigned char xmitcsum;
208 int i;
209 int count;
210 unsigned char ch;
211
212 do {
213 /* wait around for the start character, ignore all other
214 * characters */
215 while ((ch = (getDebugChar() & 0x7f)) != '$') {
216 #ifdef KGDB_DEBUG
217 if (kdebug)
218 putc(ch);
219 #endif
220 ;
221 }
222
223 checksum = 0;
224 xmitcsum = -1;
225
226 count = 0;
227
228 /* now, read until a # or end of buffer is found */
229 while (count < BUFMAX) {
230 ch = getDebugChar() & 0x7f;
231 if (ch == '#')
232 break;
233 checksum = checksum + ch;
234 buffer[count] = ch;
235 count = count + 1;
236 }
237
238 if (count >= BUFMAX)
239 continue;
240
241 buffer[count] = 0;
242
243 if (ch == '#') {
244 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
245 xmitcsum |= hex(getDebugChar() & 0x7f);
246 if (checksum != xmitcsum)
247 putDebugChar('-'); /* failed checksum */
248 else {
249 putDebugChar('+'); /* successful transfer */
250 /* if a sequence char is present, reply the ID */
251 if (buffer[2] == ':') {
252 putDebugChar(buffer[0]);
253 putDebugChar(buffer[1]);
254 /* remove sequence chars from buffer */
255 count = strlen(buffer);
256 for (i=3; i <= count; i++)
257 buffer[i-3] = buffer[i];
258 }
259 }
260 }
261 } while (checksum != xmitcsum);
262 }
263
264 /* send the packet in buffer. */
265 static void
266 putpacket(unsigned char *buffer)
267 {
268 unsigned char checksum;
269 int count;
270 unsigned char ch, recv;
271
272 /* $<packet info>#<checksum>. */
273 do {
274 putDebugChar('$');
275 checksum = 0;
276 count = 0;
277
278 while ((ch = buffer[count])) {
279 putDebugChar(ch);
280 checksum += ch;
281 count += 1;
282 }
283
284 putDebugChar('#');
285 putDebugChar(hexchars[checksum >> 4]);
286 putDebugChar(hexchars[checksum & 0xf]);
287 recv = getDebugChar();
288 } while ((recv & 0x7f) != '+');
289 }
290
291 /*
292 * This function does all command processing for interfacing to gdb.
293 */
294 static int
295 handle_exception (struct pt_regs *regs)
296 {
297 int addr;
298 int length;
299 char *ptr;
300 kgdb_data kd;
301 int i;
302
303 if (!initialized) {
304 printf("kgdb: exception before kgdb is initialized! huh?\n");
305 return (0);
306 }
307
308 /* probably should check which exception occured as well */
309 if (longjmp_on_fault) {
310 longjmp_on_fault = 0;
311 kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT);
312 panic("kgdb longjump failed!\n");
313 }
314
315 if (kgdb_active) {
316 printf("kgdb: unexpected exception from within kgdb\n");
317 return (0);
318 }
319 kgdb_active = 1;
320
321 kgdb_interruptible(0);
322
323 printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
324
325 if (kgdb_setjmp(error_jmp_buf) != 0)
326 panic("kgdb: error or fault in entry init!\n");
327
328 kgdb_enter(regs, &kd);
329
330 if (first_entry) {
331 /*
332 * the first time we enter kgdb, we save the processor
333 * state so that we can return to the monitor if the
334 * remote end quits gdb (or at least, tells us to quit
335 * with the 'k' packet)
336 */
337 entry_regs = *regs;
338 first_entry = 0;
339 }
340
341 ptr = remcomOutBuffer;
342
343 *ptr++ = 'T';
344
345 *ptr++ = hexchars[kd.sigval >> 4];
346 *ptr++ = hexchars[kd.sigval & 0xf];
347
348 for (i = 0; i < kd.nregs; i++) {
349 kgdb_reg *rp = &kd.regs[i];
350
351 *ptr++ = hexchars[rp->num >> 4];
352 *ptr++ = hexchars[rp->num & 0xf];
353 *ptr++ = ':';
354 ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
355 *ptr++ = ';';
356 }
357
358 *ptr = 0;
359
360 #ifdef KGDB_DEBUG
361 if (kdebug)
362 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
363 #endif
364
365 putpacket((unsigned char *)&remcomOutBuffer);
366
367 while (1) {
368 volatile int errnum;
369
370 remcomOutBuffer[0] = 0;
371
372 getpacket(remcomInBuffer);
373 ptr = &remcomInBuffer[1];
374
375 #ifdef KGDB_DEBUG
376 if (kdebug)
377 printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer);
378 #endif
379
380 errnum = kgdb_setjmp(error_jmp_buf);
381
382 if (errnum == 0) switch (remcomInBuffer[0]) {
383
384 case '?': /* report most recent signal */
385 remcomOutBuffer[0] = 'S';
386 remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
387 remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
388 remcomOutBuffer[3] = 0;
389 break;
390
391 #ifdef KGDB_DEBUG
392 case 'd':
393 /* toggle debug flag */
394 kdebug ^= 1;
395 break;
396 #endif
397
398 case 'g': /* return the value of the CPU registers. */
399 length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
400 mem2hex(remcomRegBuffer, remcomOutBuffer, length);
401 break;
402
403 case 'G': /* set the value of the CPU registers */
404 length = strlen(ptr);
405 if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
406 hex2mem(ptr, remcomRegBuffer, length/2);
407 kgdb_putregs(regs, remcomRegBuffer, length/2);
408 strcpy(remcomOutBuffer,"OK");
409 break;
410
411 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
412 /* Try to read %x,%x. */
413
414 if (hexToInt(&ptr, &addr)
415 && *ptr++ == ','
416 && hexToInt(&ptr, &length)) {
417 mem2hex((char *)addr, remcomOutBuffer, length);
418 } else {
419 kgdb_error(KGDBERR_BADPARAMS);
420 }
421 break;
422
423 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
424 /* Try to read '%x,%x:'. */
425
426 if (hexToInt(&ptr, &addr)
427 && *ptr++ == ','
428 && hexToInt(&ptr, &length)
429 && *ptr++ == ':') {
430 hex2mem(ptr, (char *)addr, length);
431 strcpy(remcomOutBuffer, "OK");
432 } else {
433 kgdb_error(KGDBERR_BADPARAMS);
434 }
435 break;
436
437
438 case 'k': /* kill the program, actually return to monitor */
439 kd.extype = KGDBEXIT_KILL;
440 *regs = entry_regs;
441 first_entry = 1;
442 goto doexit;
443
444 case 'C': /* CSS continue with signal SS */
445 *ptr = '\0'; /* ignore the signal number for now */
446 /* fall through */
447
448 case 'c': /* cAA..AA Continue; address AA..AA optional */
449 /* try to read optional parameter, pc unchanged if no parm */
450 kd.extype = KGDBEXIT_CONTINUE;
451
452 if (hexToInt(&ptr, &addr)) {
453 kd.exaddr = addr;
454 kd.extype |= KGDBEXIT_WITHADDR;
455 }
456
457 goto doexit;
458
459 case 'S': /* SSS single step with signal SS */
460 *ptr = '\0'; /* ignore the signal number for now */
461 /* fall through */
462
463 case 's':
464 kd.extype = KGDBEXIT_SINGLE;
465
466 if (hexToInt(&ptr, &addr)) {
467 kd.exaddr = addr;
468 kd.extype |= KGDBEXIT_WITHADDR;
469 }
470
471 doexit:
472 /* Need to flush the instruction cache here, as we may have deposited a
473 * breakpoint, and the icache probably has no way of knowing that a data ref to
474 * some location may have changed something that is in the instruction cache.
475 */
476 kgdb_flush_cache_all();
477 kgdb_exit(regs, &kd);
478 kgdb_active = 0;
479 kgdb_interruptible(1);
480 return (1);
481
482 case 'r': /* Reset (if user process..exit ???)*/
483 panic("kgdb reset.");
484 break;
485
486 case 'P': /* Pr=v set reg r to value v (r and v are hex) */
487 if (hexToInt(&ptr, &addr)
488 && *ptr++ == '='
489 && ((length = strlen(ptr)) & 1) == 0) {
490 hex2mem(ptr, remcomRegBuffer, length/2);
491 kgdb_putreg(regs, addr,
492 remcomRegBuffer, length/2);
493 strcpy(remcomOutBuffer,"OK");
494 } else {
495 kgdb_error(KGDBERR_BADPARAMS);
496 }
497 break;
498 } /* switch */
499
500 if (errnum != 0)
501 sprintf(remcomOutBuffer, "E%02d", errnum);
502
503 #ifdef KGDB_DEBUG
504 if (kdebug)
505 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
506 #endif
507
508 /* reply to the request */
509 putpacket((unsigned char *)&remcomOutBuffer);
510
511 } /* while(1) */
512 }
513
514 /*
515 * kgdb_init must be called *after* the
516 * monitor is relocated into ram
517 */
518 void
519 kgdb_init(void)
520 {
521 kgdb_serial_init();
522 debugger_exception_handler = handle_exception;
523 initialized = 1;
524
525 putDebugStr("kgdb ready\n");
526 puts("ready\n");
527 }
528
529 void
530 kgdb_error(int errnum)
531 {
532 longjmp_on_fault = 0;
533 kgdb_longjmp(error_jmp_buf, errnum);
534 panic("kgdb_error: longjmp failed!\n");
535 }
536
537 /* Output string in GDB O-packet format if GDB has connected. If nothing
538 output, returns 0 (caller must then handle output). */
539 int
540 kgdb_output_string (const char* s, unsigned int count)
541 {
542 char buffer[512];
543
544 count = (count <= (sizeof(buffer) / 2 - 2))
545 ? count : (sizeof(buffer) / 2 - 2);
546
547 buffer[0] = 'O';
548 mem2hex ((char *)s, &buffer[1], count);
549 putpacket((unsigned char *)&buffer);
550
551 return 1;
552 }
553
554 void
555 breakpoint(void)
556 {
557 if (!initialized) {
558 printf("breakpoint() called b4 kgdb init\n");
559 return;
560 }
561
562 kgdb_breakpoint(0, 0);
563 }
564
565 int
566 do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
567 {
568 printf("Entering KGDB mode via exception handler...\n\n");
569 kgdb_breakpoint(argc - 1, argv + 1);
570 printf("\nReturned from KGDB mode\n");
571 return 0;
572 }
573
574 U_BOOT_CMD(
575 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb,
576 "enter gdb remote debug mode",
577 "[arg0 arg1 .. argN]\n"
578 " - executes a breakpoint so that kgdb mode is\n"
579 " entered via the exception handler. To return\n"
580 " to the monitor, the remote gdb debugger must\n"
581 " execute a \"continue\" or \"quit\" command.\n"
582 "\n"
583 " if a program is loaded by the remote gdb, any args\n"
584 " passed to the kgdb command are given to the loaded\n"
585 " program if it is executed (see the \"hello_world\"\n"
586 " example program in the U-Boot examples directory)."
587 );