1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90#include <common.h>
91
92#include <kgdb.h>
93#include <command.h>
94
95#undef KGDB_DEBUG
96
97
98
99
100#define BUFMAX 1024
101static char remcomInBuffer[BUFMAX];
102static char remcomOutBuffer[BUFMAX];
103static char remcomRegBuffer[BUFMAX];
104
105static int initialized = 0;
106static int kgdb_active = 0, first_entry = 1;
107static struct pt_regs entry_regs;
108static long error_jmp_buf[BUFMAX/2];
109static int longjmp_on_fault = 0;
110#ifdef KGDB_DEBUG
111static int kdebug = 1;
112#endif
113
114static const char hexchars[]="0123456789abcdef";
115
116
117static int
118hex(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
130
131
132static unsigned char *
133mem2hex(char *mem, char *buf, int count)
134{
135 char *tmp;
136 unsigned char ch;
137
138
139
140
141
142 tmp = buf + count;
143 longjmp_on_fault = 1;
144
145 memcpy(tmp, mem, count);
146
147 while (count-- > 0) {
148 ch = *tmp++;
149 *buf++ = hexchars[ch >> 4];
150 *buf++ = hexchars[ch & 0xf];
151 }
152 *buf = 0;
153 longjmp_on_fault = 0;
154 return (unsigned char *)buf;
155}
156
157
158
159
160static char *
161hex2mem(char *buf, char *mem, int count)
162{
163 int hexValue;
164 char *tmp_raw, *tmp_hex;
165
166
167
168
169
170 tmp_raw = buf + count * 2;
171 tmp_hex = tmp_raw - 1;
172
173 longjmp_on_fault = 1;
174 while (tmp_hex >= buf) {
175 tmp_raw--;
176 hexValue = hex(*tmp_hex--);
177 if (hexValue < 0)
178 kgdb_error(KGDBERR_NOTHEXDIG);
179 *tmp_raw = hexValue;
180 hexValue = hex(*tmp_hex--);
181 if (hexValue < 0)
182 kgdb_error(KGDBERR_NOTHEXDIG);
183 *tmp_raw |= hexValue << 4;
184
185 }
186
187 memcpy(mem, tmp_raw, count);
188
189 kgdb_flush_cache_range((void *)mem, (void *)(mem+count));
190 longjmp_on_fault = 0;
191
192 return buf;
193}
194
195
196
197
198
199static int
200hexToInt(char **ptr, int *intValue)
201{
202 int numChars = 0;
203 int hexValue;
204
205 *intValue = 0;
206
207 longjmp_on_fault = 1;
208 while (**ptr) {
209 hexValue = hex(**ptr);
210 if (hexValue < 0)
211 break;
212
213 *intValue = (*intValue << 4) | hexValue;
214 numChars ++;
215
216 (*ptr)++;
217 }
218 longjmp_on_fault = 0;
219
220 return (numChars);
221}
222
223
224static void
225getpacket(char *buffer)
226{
227 unsigned char checksum;
228 unsigned char xmitcsum;
229 int i;
230 int count;
231 unsigned char ch;
232
233 do {
234
235
236 while ((ch = (getDebugChar() & 0x7f)) != '$') {
237#ifdef KGDB_DEBUG
238 if (kdebug)
239 putc(ch);
240#endif
241 ;
242 }
243
244 checksum = 0;
245 xmitcsum = -1;
246
247 count = 0;
248
249
250 while (count < BUFMAX) {
251 ch = getDebugChar() & 0x7f;
252 if (ch == '#')
253 break;
254 checksum = checksum + ch;
255 buffer[count] = ch;
256 count = count + 1;
257 }
258
259 if (count >= BUFMAX)
260 continue;
261
262 buffer[count] = 0;
263
264 if (ch == '#') {
265 xmitcsum = hex(getDebugChar() & 0x7f) << 4;
266 xmitcsum |= hex(getDebugChar() & 0x7f);
267 if (checksum != xmitcsum)
268 putDebugChar('-');
269 else {
270 putDebugChar('+');
271
272 if (buffer[2] == ':') {
273 putDebugChar(buffer[0]);
274 putDebugChar(buffer[1]);
275
276 count = strlen(buffer);
277 for (i=3; i <= count; i++)
278 buffer[i-3] = buffer[i];
279 }
280 }
281 }
282 } while (checksum != xmitcsum);
283}
284
285
286static void
287putpacket(unsigned char *buffer)
288{
289 unsigned char checksum;
290 int count;
291 unsigned char ch, recv;
292
293
294 do {
295 putDebugChar('$');
296 checksum = 0;
297 count = 0;
298
299 while ((ch = buffer[count])) {
300 putDebugChar(ch);
301 checksum += ch;
302 count += 1;
303 }
304
305 putDebugChar('#');
306 putDebugChar(hexchars[checksum >> 4]);
307 putDebugChar(hexchars[checksum & 0xf]);
308 recv = getDebugChar();
309 } while ((recv & 0x7f) != '+');
310}
311
312
313
314
315static int
316handle_exception (struct pt_regs *regs)
317{
318 int addr;
319 int length;
320 char *ptr;
321 kgdb_data kd;
322 int i;
323
324 if (!initialized) {
325 printf("kgdb: exception before kgdb is initialized! huh?\n");
326 return (0);
327 }
328
329
330 if (longjmp_on_fault) {
331 longjmp_on_fault = 0;
332 kgdb_longjmp(error_jmp_buf, KGDBERR_MEMFAULT);
333 panic("kgdb longjump failed!\n");
334 }
335
336 if (kgdb_active) {
337 printf("kgdb: unexpected exception from within kgdb\n");
338 return (0);
339 }
340 kgdb_active = 1;
341
342 kgdb_interruptible(0);
343
344 printf("kgdb: handle_exception; trap [0x%x]\n", kgdb_trap(regs));
345
346 if (kgdb_setjmp(error_jmp_buf) != 0)
347 panic("kgdb: error or fault in entry init!\n");
348
349 kgdb_enter(regs, &kd);
350
351 if (first_entry) {
352
353
354
355
356
357
358 entry_regs = *regs;
359 first_entry = 0;
360 }
361
362 ptr = remcomOutBuffer;
363
364 *ptr++ = 'T';
365
366 *ptr++ = hexchars[kd.sigval >> 4];
367 *ptr++ = hexchars[kd.sigval & 0xf];
368
369 for (i = 0; i < kd.nregs; i++) {
370 kgdb_reg *rp = &kd.regs[i];
371
372 *ptr++ = hexchars[rp->num >> 4];
373 *ptr++ = hexchars[rp->num & 0xf];
374 *ptr++ = ':';
375 ptr = (char *)mem2hex((char *)&rp->val, ptr, 4);
376 *ptr++ = ';';
377 }
378
379 *ptr = 0;
380
381#ifdef KGDB_DEBUG
382 if (kdebug)
383 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
384#endif
385
386 putpacket((unsigned char *)&remcomOutBuffer);
387
388 while (1) {
389 volatile int errnum;
390
391 remcomOutBuffer[0] = 0;
392
393 getpacket(remcomInBuffer);
394 ptr = &remcomInBuffer[1];
395
396#ifdef KGDB_DEBUG
397 if (kdebug)
398 printf("kgdb: remcomInBuffer: %s\n", remcomInBuffer);
399#endif
400
401 errnum = kgdb_setjmp(error_jmp_buf);
402
403 if (errnum == 0) switch (remcomInBuffer[0]) {
404
405 case '?':
406 remcomOutBuffer[0] = 'S';
407 remcomOutBuffer[1] = hexchars[kd.sigval >> 4];
408 remcomOutBuffer[2] = hexchars[kd.sigval & 0xf];
409 remcomOutBuffer[3] = 0;
410 break;
411
412#ifdef KGDB_DEBUG
413 case 'd':
414
415 kdebug ^= 1;
416 break;
417#endif
418
419 case 'g':
420 length = kgdb_getregs(regs, remcomRegBuffer, BUFMAX);
421 mem2hex(remcomRegBuffer, remcomOutBuffer, length);
422 break;
423
424 case 'G':
425 length = strlen(ptr);
426 if ((length & 1) != 0) kgdb_error(KGDBERR_BADPARAMS);
427 hex2mem(ptr, remcomRegBuffer, length/2);
428 kgdb_putregs(regs, remcomRegBuffer, length/2);
429 strcpy(remcomOutBuffer,"OK");
430 break;
431
432 case 'm':
433
434
435 if (hexToInt(&ptr, &addr)
436 && *ptr++ == ','
437 && hexToInt(&ptr, &length)) {
438 mem2hex((char *)addr, remcomOutBuffer, length);
439 } else {
440 kgdb_error(KGDBERR_BADPARAMS);
441 }
442 break;
443
444 case 'M':
445
446
447 if (hexToInt(&ptr, &addr)
448 && *ptr++ == ','
449 && hexToInt(&ptr, &length)
450 && *ptr++ == ':') {
451 hex2mem(ptr, (char *)addr, length);
452 strcpy(remcomOutBuffer, "OK");
453 } else {
454 kgdb_error(KGDBERR_BADPARAMS);
455 }
456 break;
457
458
459 case 'k':
460 kd.extype = KGDBEXIT_KILL;
461 *regs = entry_regs;
462 first_entry = 1;
463 goto doexit;
464
465 case 'C':
466 *ptr = '\0';
467
468
469 case 'c':
470
471 kd.extype = KGDBEXIT_CONTINUE;
472
473 if (hexToInt(&ptr, &addr)) {
474 kd.exaddr = addr;
475 kd.extype |= KGDBEXIT_WITHADDR;
476 }
477
478 goto doexit;
479
480 case 'S':
481 *ptr = '\0';
482
483
484 case 's':
485 kd.extype = KGDBEXIT_SINGLE;
486
487 if (hexToInt(&ptr, &addr)) {
488 kd.exaddr = addr;
489 kd.extype |= KGDBEXIT_WITHADDR;
490 }
491
492 doexit:
493
494
495
496
497 kgdb_flush_cache_all();
498 kgdb_exit(regs, &kd);
499 kgdb_active = 0;
500 kgdb_interruptible(1);
501 return (1);
502
503 case 'r':
504 panic("kgdb reset.");
505 break;
506
507 case 'P':
508 if (hexToInt(&ptr, &addr)
509 && *ptr++ == '='
510 && ((length = strlen(ptr)) & 1) == 0) {
511 hex2mem(ptr, remcomRegBuffer, length/2);
512 kgdb_putreg(regs, addr,
513 remcomRegBuffer, length/2);
514 strcpy(remcomOutBuffer,"OK");
515 } else {
516 kgdb_error(KGDBERR_BADPARAMS);
517 }
518 break;
519 }
520
521 if (errnum != 0)
522 sprintf(remcomOutBuffer, "E%02d", errnum);
523
524#ifdef KGDB_DEBUG
525 if (kdebug)
526 printf("kgdb: remcomOutBuffer: %s\n", remcomOutBuffer);
527#endif
528
529
530 putpacket((unsigned char *)&remcomOutBuffer);
531
532 }
533}
534
535
536
537
538
539void
540kgdb_init(void)
541{
542 kgdb_serial_init();
543 debugger_exception_handler = handle_exception;
544 initialized = 1;
545
546 putDebugStr("kgdb ready\n");
547 puts("ready\n");
548}
549
550void
551kgdb_error(int errnum)
552{
553 longjmp_on_fault = 0;
554 kgdb_longjmp(error_jmp_buf, errnum);
555 panic("kgdb_error: longjmp failed!\n");
556}
557
558
559
560int
561kgdb_output_string (const char* s, unsigned int count)
562{
563 char buffer[512];
564
565 count = (count <= (sizeof(buffer) / 2 - 2))
566 ? count : (sizeof(buffer) / 2 - 2);
567
568 buffer[0] = 'O';
569 mem2hex ((char *)s, &buffer[1], count);
570 putpacket((unsigned char *)&buffer);
571
572 return 1;
573}
574
575void
576breakpoint(void)
577{
578 if (!initialized) {
579 printf("breakpoint() called b4 kgdb init\n");
580 return;
581 }
582
583 kgdb_breakpoint(0, 0);
584}
585
586int
587do_kgdb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
588{
589 printf("Entering KGDB mode via exception handler...\n\n");
590 kgdb_breakpoint(argc - 1, argv + 1);
591 printf("\nReturned from KGDB mode\n");
592 return 0;
593}
594
595U_BOOT_CMD(
596 kgdb, CONFIG_SYS_MAXARGS, 1, do_kgdb,
597 "enter gdb remote debug mode",
598 "[arg0 arg1 .. argN]\n"
599 " - executes a breakpoint so that kgdb mode is\n"
600 " entered via the exception handler. To return\n"
601 " to the monitor, the remote gdb debugger must\n"
602 " execute a \"continue\" or \"quit\" command.\n"
603 "\n"
604 " if a program is loaded by the remote gdb, any args\n"
605 " passed to the kgdb command are given to the loaded\n"
606 " program if it is executed (see the \"hello_world\"\n"
607 " example program in the U-Boot examples directory)."
608);
609