00001 #include <console/console.h>
00002 #include <string.h>
00003
00004 #if CONFIG_GDB_STUB == 1
00005
00006
00007
00008
00009 #define BUFMAX 400
00010 enum regnames {
00011 EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
00012 PC ,
00013 PS ,
00014 CS, SS, DS, ES, FS, GS,
00015 NUM_REGS
00016 };
00017
00018 static uint32_t gdb_stub_registers[NUM_REGS];
00019
00020 #define GDB_SIG0 0
00021 #define GDB_SIGHUP 1
00022 #define GDB_SIGINT 2
00023 #define GDB_SIGQUIT 3
00024 #define GDB_SIGILL 4
00025 #define GDB_SIGTRAP 5
00026 #define GDB_SIGABRT 6
00027 #define GDB_SIGEMT 7
00028 #define GDB_SIGFPE 8
00029 #define GDB_SIGKILL 9
00030 #define GDB_SIGBUS 10
00031 #define GDB_SIGSEGV 11
00032 #define GDB_SIGSYS 12
00033 #define GDB_SIGPIPE 13
00034 #define GDB_SIGALRM 14
00035 #define GDB_SIGTERM 15
00036 #define GDB_SIGURG 16
00037 #define GDB_SIGSTOP 17
00038 #define GDB_SIGTSTP 18
00039 #define GDB_SIGCONT 19
00040 #define GDB_SIGCHLD 20
00041 #define GDB_SIGTTIN 21
00042 #define GDB_SIGTTOU 22
00043 #define GDB_SIGIO 23
00044 #define GDB_SIGXCPU 24
00045 #define GDB_SIGXFSZ 25
00046 #define GDB_SIGVTALRM 26
00047 #define GDB_SIGPROF 27
00048 #define GDB_SIGWINCH 28
00049 #define GDB_SIGLOST 29
00050 #define GDB_SIGUSR1 30
00051 #define GDB_SUGUSR2 31
00052 #define GDB_SIGPWR 32
00053 #define GDB_SIGPOLL 33
00054 #define GDB_SIGWIND 34
00055 #define GDB_SIGPHONE 35
00056 #define GDB_SIGWAITING 36
00057 #define GDB_SIGLWP 37
00058 #define GDB_SIGDANGER 38
00059 #define GDB_SIGGRANT 39
00060 #define GDB_SIGRETRACT 40
00061 #define GDB_SIGMSG 41
00062 #define GDB_SIGSOUND 42
00063 #define GDB_SIGSAK 43
00064 #define GDB_SIGPRIO 44
00065
00066 #define GDB_SIG33 45
00067 #define GDB_SIG34 46
00068 #define GDB_SIG35 47
00069 #define GDB_SIG36 48
00070 #define GDB_SIG37 49
00071 #define GDB_SIG38 50
00072 #define GDB_SIG39 51
00073 #define GDB_SIG40 52
00074 #define GDB_SIG41 53
00075 #define GDB_SIG42 54
00076 #define GDB_SIG43 55
00077 #define GDB_SIG44 56
00078 #define GDB_SIG45 57
00079 #define GDB_SIG46 58
00080 #define GDB_SIG47 59
00081 #define GDB_SIG48 60
00082 #define GDB_SIG49 61
00083 #define GDB_SIG50 62
00084 #define GDB_SIG51 63
00085 #define GDB_SIG52 64
00086 #define GDB_SIG53 65
00087 #define GDB_SIG54 66
00088 #define GDB_SIG55 67
00089 #define GDB_SIG56 68
00090 #define GDB_SIG57 69
00091 #define GDB_SIG58 70
00092 #define GDB_SIG59 71
00093 #define GDB_SIG60 72
00094 #define GDB_SIG61 73
00095 #define GDB_SIG62 74
00096 #define GDB_SIG63 75
00097 #define GDB_SIGCANCEL 76
00098 #define GDB_SIG32 77
00099 #define GDB_SIG64 78
00100 #define GDB_SIG65 79
00101 #define GDB_SIG66 80
00102 #define GDB_SIG67 81
00103 #define GDB_SIG68 82
00104 #define GDB_SIG69 83
00105 #define GDB_SIG70 84
00106 #define GDB_SIG71 85
00107 #define GDB_SIG72 86
00108 #define GDB_SIG73 87
00109 #define GDB_SIG74 88
00110 #define GDB_SIG75 89
00111 #define GDB_SIG76 90
00112 #define GDB_SIG77 91
00113 #define GDB_SIG78 92
00114 #define GDB_SIG79 93
00115 #define GDB_SIG80 94
00116 #define GDB_SIG81 95
00117 #define GDB_SIG82 96
00118 #define GDB_SIG83 97
00119 #define GDB_SIG84 98
00120 #define GDB_SIG85 99
00121 #define GDB_SIG86 100
00122 #define GDB_SIG87 101
00123 #define GDB_SIG88 102
00124 #define GDB_SIG89 103
00125 #define GDB_SIG90 104
00126 #define GDB_SIG91 105
00127 #define GDB_SIG92 106
00128 #define GDB_SIG93 107
00129 #define GDB_SIG94 108
00130 #define GDB_SIG95 109
00131 #define GDB_SIG96 110
00132 #define GDB_SIG97 111
00133 #define GDB_SIG98 112
00134 #define GDB_SIG99 113
00135 #define GDB_SIG100 114
00136 #define GDB_SIG101 115
00137 #define GDB_SIG102 116
00138 #define GDB_SIG103 117
00139 #define GDB_SIG104 118
00140 #define GDB_SIG105 119
00141 #define GDB_SIG106 120
00142 #define GDB_SIG107 121
00143 #define GDB_SIG108 122
00144 #define GDB_SIG109 123
00145 #define GDB_SIG110 124
00146 #define GDB_SIG111 125
00147 #define GDB_SIG112 126
00148 #define GDB_SIG113 127
00149 #define GDB_SIG114 128
00150 #define GDB_SIG115 129
00151 #define GDB_SIG116 130
00152 #define GDB_SIG117 131
00153 #define GDB_SIG118 132
00154 #define GDB_SIG119 133
00155 #define GDB_SIG120 134
00156 #define GDB_SIG121 135
00157 #define GDB_SIG122 136
00158 #define GDB_SIG123 137
00159 #define GDB_SIG124 138
00160 #define GDB_SIG125 139
00161 #define GDB_SIG126 140
00162 #define GDB_SIG127 141
00163 #define GDB_SIGINFO 142
00164 #define GDB_UNKNOWN 143
00165 #define GDB_DEFAULT 144
00166
00167 #define GDB_EXC_BAD_ACCESS 145
00168 #define GDB_EXC_BAD_INSTRCTION 146
00169 #define GDB_EXC_ARITHMETIC 147
00170 #define GDB_EXC_EMULATION 148
00171 #define GDB_EXC_SOFTWARE 149
00172 #define GDB_EXC_BREAKPOINT 150
00173
00174
00175
00176 static unsigned char exception_to_signal[] =
00177 {
00178 [0] = GDB_SIGFPE,
00179 [1] = GDB_SIGTRAP,
00180 [2] = GDB_SIGSEGV,
00181 [3] = GDB_SIGTRAP,
00182 [4] = GDB_SIGSEGV,
00183 [5] = GDB_SIGSEGV,
00184 [6] = GDB_SIGILL,
00185 [7] = GDB_SIGSEGV,
00186 [8] = GDB_SIGSEGV,
00187 [9] = GDB_SIGFPE,
00188 [10] = GDB_SIGSEGV,
00189 [11] = GDB_SIGBUS,
00190 [12] = GDB_SIGBUS,
00191 [13] = GDB_SIGSEGV,
00192 [14] = GDB_SIGSEGV,
00193 [15] = GDB_UNKNOWN,
00194 [16] = GDB_SIGEMT,
00195 [17] = GDB_SIGBUS,
00196 [18] = GDB_SIGSEGV,
00197 [19] = GDB_SIGFPE,
00198 [20] = GDB_UNKNOWN,
00199 [21] = GDB_UNKNOWN,
00200 [22] = GDB_UNKNOWN,
00201 [23] = GDB_UNKNOWN,
00202 [24] = GDB_UNKNOWN,
00203 [25] = GDB_UNKNOWN,
00204 [26] = GDB_UNKNOWN,
00205 [27] = GDB_UNKNOWN,
00206 [28] = GDB_UNKNOWN,
00207 [29] = GDB_UNKNOWN,
00208 [30] = GDB_UNKNOWN,
00209 [31] = GDB_UNKNOWN,
00210 [32] = GDB_SIGINT,
00211 };
00212
00213 static const char hexchars[] = "0123456789abcdef";
00214 static char in_buffer[BUFMAX];
00215 static char out_buffer[BUFMAX];
00216
00217
00218 static inline void stub_putc(int ch)
00219 {
00220 console_tx_byte(ch);
00221 }
00222
00223 static inline int stub_getc(void)
00224 {
00225 return console_rx_byte();
00226 }
00227
00228 static int hex(char ch)
00229 {
00230 if ((ch >= 'a') && (ch <= 'f'))
00231 return (ch - 'a' + 10);
00232 if ((ch >= '0') && (ch <= '9'))
00233 return (ch - '0');
00234 if ((ch >= 'A') && (ch <= 'F'))
00235 return (ch - 'A' + 10);
00236 return (-1);
00237 }
00238
00239
00240
00241
00242
00243 static int parse_ulong(char **ptr, unsigned long *value)
00244 {
00245 int digit;
00246 char *start;
00247
00248 start = *ptr;
00249 *value = 0;
00250
00251 while((digit = hex(**ptr)) >= 0) {
00252 *value = ((*value) << 4) | digit;
00253 (*ptr)++;
00254 }
00255 return start != *ptr;
00256 }
00257
00258
00259
00260 static void copy_to_hex(char *buf, void *addr, unsigned long count)
00261 {
00262 unsigned char ch;
00263 char *mem = addr;
00264
00265 while(count--) {
00266 ch = *mem++;
00267 *buf++ = hexchars[ch >> 4];
00268 *buf++ = hexchars[ch & 0x0f];
00269 }
00270 *buf = 0;
00271 return;
00272 }
00273
00274
00275
00276
00277 static void copy_from_hex(void *addr, char *buf, unsigned long count)
00278 {
00279 unsigned char ch;
00280 char *mem = addr;
00281
00282 while(count--) {
00283 ch = hex (*buf++) << 4;
00284 ch = ch + hex (*buf++);
00285 *mem++ = ch;
00286 }
00287 }
00288
00289
00290
00291
00292 static int get_packet(char *buffer)
00293 {
00294 unsigned char checksum;
00295 unsigned char xmitcsum;
00296 int count;
00297 char ch;
00298
00299
00300 do {
00301
00302 while ((ch = (stub_getc() & 0x7f)) != '$');
00303 checksum = 0;
00304 xmitcsum = -1;
00305
00306 count = 0;
00307
00308
00309 while (count < BUFMAX) {
00310 ch = stub_getc() & 0x7f;
00311 if (ch == '#')
00312 break;
00313 checksum = checksum + ch;
00314 buffer[count] = ch;
00315 count = count + 1;
00316 }
00317 buffer[count] = 0;
00318
00319 if (ch == '#') {
00320 xmitcsum = hex(stub_getc() & 0x7f) << 4;
00321 xmitcsum += hex(stub_getc() & 0x7f);
00322
00323 if (checksum != xmitcsum) {
00324 stub_putc('-');
00325 }
00326 else {
00327 stub_putc('+');
00328 }
00329 }
00330 } while(checksum != xmitcsum);
00331 return 1;
00332 }
00333
00334
00335 static void put_packet(char *buffer)
00336 {
00337 unsigned char checksum;
00338 int count;
00339 char ch;
00340
00341
00342 do {
00343 stub_putc('$');
00344 checksum = 0;
00345 count = 0;
00346
00347 while ((ch = buffer[count])) {
00348 stub_putc(ch);
00349 checksum += ch;
00350 count += 1;
00351 }
00352
00353 stub_putc('#');
00354 stub_putc(hexchars[checksum >> 4]);
00355 stub_putc(hexchars[checksum % 16]);
00356
00357 } while ((stub_getc() & 0x7f) != '+');
00358
00359 }
00360 #endif
00361
00362 struct eregs {
00363 uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
00364 uint32_t vector;
00365 uint32_t error_code;
00366 uint32_t eip;
00367 uint32_t cs;
00368 uint32_t eflags;
00369 };
00370
00371 void x86_exception(struct eregs *info)
00372 {
00373 #if CONFIG_GDB_STUB == 1
00374 int signo;
00375 memcpy(gdb_stub_registers, info, 8*sizeof(uint32_t));
00376 gdb_stub_registers[PC] = info->eip;
00377 gdb_stub_registers[CS] = info->cs;
00378 gdb_stub_registers[PS] = info->eflags;
00379 signo = GDB_UNKNOWN;
00380 if (info->vector < ARRAY_SIZE(exception_to_signal)) {
00381 signo = exception_to_signal[info->vector];
00382 }
00383
00384
00385 out_buffer[0] = 'S';
00386 out_buffer[1] = hexchars[(signo>>4) & 0xf];
00387 out_buffer[2] = hexchars[signo & 0xf];
00388 out_buffer[3] = '\0';
00389 put_packet(out_buffer);
00390
00391 while(1) {
00392 unsigned long addr, length;
00393 char *ptr;
00394 out_buffer[0] = '\0';
00395 out_buffer[1] = '\0';
00396 if (!get_packet(in_buffer)) {
00397 break;
00398 }
00399 switch(in_buffer[0]) {
00400 case '?':
00401 out_buffer[0] = 'S';
00402 out_buffer[1] = hexchars[(signo >> 4) & 0xf];
00403 out_buffer[2] = hexchars[signo & 0xf];
00404 out_buffer[3] = '\0';
00405 break;
00406 case 'g':
00407 copy_to_hex(out_buffer, &gdb_stub_registers, sizeof(gdb_stub_registers));
00408 break;
00409 case 'G':
00410 copy_from_hex(&gdb_stub_registers, in_buffer + 1, sizeof(gdb_stub_registers));
00411 memcpy(info, gdb_stub_registers, 8*sizeof(uint32_t));
00412 info->eip = gdb_stub_registers[PC];
00413 info->cs = gdb_stub_registers[CS];
00414 info->eflags = gdb_stub_registers[PS];
00415 memcpy(out_buffer, "OK",3);
00416 break;
00417 case 'm':
00418
00419 ptr = &in_buffer[1];
00420 if ( parse_ulong(&ptr, &addr) &&
00421 (*ptr++ == ',') &&
00422 parse_ulong(&ptr, &length)) {
00423 copy_to_hex(out_buffer, (void *)addr, length);
00424 } else {
00425 memcpy(out_buffer, "E01", 4);
00426 }
00427 break;
00428 case 'M':
00429
00430 ptr = &in_buffer[1];
00431 if ( parse_ulong(&ptr, &addr) &&
00432 (*(ptr++) == ',') &&
00433 parse_ulong(&ptr, &length) &&
00434 (*(ptr++) == ':')) {
00435 copy_from_hex((void *)addr, ptr, length);
00436 memcpy(out_buffer, "OK", 3);
00437 }
00438 else {
00439 memcpy(out_buffer, "E02", 4);
00440 }
00441 break;
00442 case 's':
00443 case 'c':
00444
00445
00446 ptr = &in_buffer[1];
00447 if (parse_ulong(&ptr, &addr)) {
00448 info->eip = addr;
00449 }
00450
00451
00452 info->eflags &= ~(1 << 8);
00453
00454 if (in_buffer[0] == 's') {
00455 info->eflags |= (1 << 8);
00456 }
00457 return;
00458 break;
00459 case 'D':
00460 memcpy(out_buffer, "OK", 3);
00461 break;
00462 case 'k':
00463 break;
00464 case 'q':
00465 break;
00466 case 'z':
00467
00468
00469
00470
00471 case 'Z':
00472
00473
00474
00475
00476 break;
00477 default:
00478 break;
00479 }
00480 put_packet(out_buffer);
00481 }
00482 #else
00483 printk_emerg(
00484 "Unexpected Exception: %d @ %02x:%08lx - Halting\n"
00485 "Code: %d eflags: %08lx\n"
00486 "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n"
00487 "edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n",
00488 info->vector, info->cs, info->eip,
00489 info->error_code, info->eflags,
00490 info->eax, info->ebx, info->ecx, info->edx,
00491 info->edi, info->esi, info->ebp, info->esp);
00492 die("");
00493 #endif
00494 }