1ae2e6c43SIngo Weinhold /* 2ae2e6c43SIngo Weinhold * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. 3ae2e6c43SIngo Weinhold * Distributed under the terms of the MIT License. 4ae2e6c43SIngo Weinhold * 5ae2e6c43SIngo Weinhold * Copyright 2002, Manuel J. Petit. All rights reserved. 6ae2e6c43SIngo Weinhold * Distributed under the terms of the NewOS License. 7ae2e6c43SIngo Weinhold */ 8ae2e6c43SIngo Weinhold 9ae2e6c43SIngo Weinhold /** Contains the code to interface with a remote GDB */ 10ae2e6c43SIngo Weinhold 11ae2e6c43SIngo Weinhold #include "gdb.h" 12ae2e6c43SIngo Weinhold 13ae2e6c43SIngo Weinhold #include <string.h> 14ae2e6c43SIngo Weinhold #include <stdarg.h> 15ae2e6c43SIngo Weinhold #include <stdio.h> 16ae2e6c43SIngo Weinhold 17ae2e6c43SIngo Weinhold #include <ByteOrder.h> 18ae2e6c43SIngo Weinhold 19ae2e6c43SIngo Weinhold #include <arch/debug_console.h> 20ae2e6c43SIngo Weinhold #include <debug.h> 21ae2e6c43SIngo Weinhold #include <smp.h> 22ae2e6c43SIngo Weinhold #include <vm.h> 23ae2e6c43SIngo Weinhold 24ae2e6c43SIngo Weinhold 25ae2e6c43SIngo Weinhold enum { INIT = 0, CMDREAD, CKSUM1, CKSUM2, WAITACK, QUIT, GDBSTATES }; 26ae2e6c43SIngo Weinhold 27ae2e6c43SIngo Weinhold 28ae2e6c43SIngo Weinhold static char sCommand[512]; 29ae2e6c43SIngo Weinhold static int sCommandIndex; 30ae2e6c43SIngo Weinhold static int sCheckSum; 31ae2e6c43SIngo Weinhold 32ae2e6c43SIngo Weinhold static char sReply[512]; 33ae2e6c43SIngo Weinhold static char sSafeMemory[512]; 34ae2e6c43SIngo Weinhold 35ae2e6c43SIngo Weinhold 36ae2e6c43SIngo Weinhold // utility functions 37ae2e6c43SIngo Weinhold 38ae2e6c43SIngo Weinhold 39ae2e6c43SIngo Weinhold static int 40ae2e6c43SIngo Weinhold parse_nibble(int input) 41ae2e6c43SIngo Weinhold { 42ae2e6c43SIngo Weinhold int nibble = 0xff; 43ae2e6c43SIngo Weinhold 44ae2e6c43SIngo Weinhold if (input >= '0' && input <= '9') 45ae2e6c43SIngo Weinhold nibble = input - '0'; 46ae2e6c43SIngo Weinhold 47ae2e6c43SIngo Weinhold if (input >= 'A' && input <= 'F') 48ae2e6c43SIngo Weinhold nibble = 0x0a + input - 'A'; 49ae2e6c43SIngo Weinhold 50ae2e6c43SIngo Weinhold if (input >= 'a' && input <= 'f') 51ae2e6c43SIngo Weinhold nibble = 0x0a + input - 'a'; 52ae2e6c43SIngo Weinhold 53ae2e6c43SIngo Weinhold return nibble; 54ae2e6c43SIngo Weinhold } 55ae2e6c43SIngo Weinhold 56ae2e6c43SIngo Weinhold 57ae2e6c43SIngo Weinhold // #pragma mark - GDB protocol 58ae2e6c43SIngo Weinhold 59ae2e6c43SIngo Weinhold 60ae2e6c43SIngo Weinhold static void 61ae2e6c43SIngo Weinhold gdb_ack(void) 62ae2e6c43SIngo Weinhold { 63ae2e6c43SIngo Weinhold arch_debug_serial_putchar('+'); 64ae2e6c43SIngo Weinhold } 65ae2e6c43SIngo Weinhold 66ae2e6c43SIngo Weinhold 67ae2e6c43SIngo Weinhold static void 68ae2e6c43SIngo Weinhold gdb_nak(void) 69ae2e6c43SIngo Weinhold { 70ae2e6c43SIngo Weinhold arch_debug_serial_putchar('-'); 71ae2e6c43SIngo Weinhold } 72ae2e6c43SIngo Weinhold 73ae2e6c43SIngo Weinhold 74ae2e6c43SIngo Weinhold static void 75ae2e6c43SIngo Weinhold gdb_resend_reply(void) 76ae2e6c43SIngo Weinhold { 77ae2e6c43SIngo Weinhold arch_debug_serial_puts(sReply); 78ae2e6c43SIngo Weinhold } 79ae2e6c43SIngo Weinhold 80ae2e6c43SIngo Weinhold 81ae2e6c43SIngo Weinhold static void 82ae2e6c43SIngo Weinhold gdb_reply(char const* format, ...) 83ae2e6c43SIngo Weinhold { 84ae2e6c43SIngo Weinhold int i; 85ae2e6c43SIngo Weinhold int len; 86ae2e6c43SIngo Weinhold int sum; 87ae2e6c43SIngo Weinhold va_list args; 88ae2e6c43SIngo Weinhold 89ae2e6c43SIngo Weinhold va_start(args, format); 90ae2e6c43SIngo Weinhold sReply[0] = '$'; 91ae2e6c43SIngo Weinhold vsprintf(sReply + 1, format, args); 92ae2e6c43SIngo Weinhold va_end(args); 93ae2e6c43SIngo Weinhold 94ae2e6c43SIngo Weinhold len = strlen(sReply); 95ae2e6c43SIngo Weinhold sum = 0; 96ae2e6c43SIngo Weinhold for (i = 1; i < len; i++) { 97ae2e6c43SIngo Weinhold sum += sReply[i]; 98ae2e6c43SIngo Weinhold } 99ae2e6c43SIngo Weinhold sum %= 256; 100ae2e6c43SIngo Weinhold 101ae2e6c43SIngo Weinhold sprintf(sReply + len, "#%02x", sum); 102ae2e6c43SIngo Weinhold 103ae2e6c43SIngo Weinhold gdb_resend_reply(); 104ae2e6c43SIngo Weinhold } 105ae2e6c43SIngo Weinhold 106ae2e6c43SIngo Weinhold 107ae2e6c43SIngo Weinhold static void 108ae2e6c43SIngo Weinhold gdb_regreply(int const* regs, int numregs) 109ae2e6c43SIngo Weinhold { 110ae2e6c43SIngo Weinhold int i; 111ae2e6c43SIngo Weinhold int len; 112ae2e6c43SIngo Weinhold int sum; 113ae2e6c43SIngo Weinhold 114ae2e6c43SIngo Weinhold sReply[0] = '$'; 115ae2e6c43SIngo Weinhold for (i = 0; i < numregs; i++) 116ae2e6c43SIngo Weinhold sprintf(sReply + 1 + 8 * i, "%08lx", B_HOST_TO_BENDIAN_INT32(regs[i])); 117ae2e6c43SIngo Weinhold 118ae2e6c43SIngo Weinhold len = strlen(sReply); 119ae2e6c43SIngo Weinhold sum = 0; 120ae2e6c43SIngo Weinhold for (i = 1; i < len; i++) 121ae2e6c43SIngo Weinhold sum += sReply[i]; 122ae2e6c43SIngo Weinhold sum %= 256; 123ae2e6c43SIngo Weinhold 124ae2e6c43SIngo Weinhold sprintf(sReply + len, "#%02x", sum); 125ae2e6c43SIngo Weinhold 126ae2e6c43SIngo Weinhold gdb_resend_reply(); 127ae2e6c43SIngo Weinhold } 128ae2e6c43SIngo Weinhold 129ae2e6c43SIngo Weinhold 130ae2e6c43SIngo Weinhold static void 131ae2e6c43SIngo Weinhold gdb_memreply(char const* bytes, int numbytes) 132ae2e6c43SIngo Weinhold { 133ae2e6c43SIngo Weinhold int i; 134ae2e6c43SIngo Weinhold int len; 135ae2e6c43SIngo Weinhold int sum; 136ae2e6c43SIngo Weinhold 137ae2e6c43SIngo Weinhold sReply[0] = '$'; 138ae2e6c43SIngo Weinhold for (i = 0; i < numbytes; i++) 139ae2e6c43SIngo Weinhold sprintf(sReply + 1 + 2 * i, "%02x", (uint8)bytes[i]); 140ae2e6c43SIngo Weinhold 141ae2e6c43SIngo Weinhold len = strlen(sReply); 142ae2e6c43SIngo Weinhold sum = 0; 143ae2e6c43SIngo Weinhold for (i = 1; i < len; i++) 144ae2e6c43SIngo Weinhold sum += sReply[i]; 145ae2e6c43SIngo Weinhold sum %= 256; 146ae2e6c43SIngo Weinhold 147ae2e6c43SIngo Weinhold sprintf(sReply + len, "#%02x", sum); 148ae2e6c43SIngo Weinhold 149ae2e6c43SIngo Weinhold gdb_resend_reply(); 150ae2e6c43SIngo Weinhold } 151ae2e6c43SIngo Weinhold 152ae2e6c43SIngo Weinhold 153ae2e6c43SIngo Weinhold // #pragma mark - checksum verification 154ae2e6c43SIngo Weinhold 155ae2e6c43SIngo Weinhold 156ae2e6c43SIngo Weinhold static int 157ae2e6c43SIngo Weinhold gdb_verify_checksum(void) 158ae2e6c43SIngo Weinhold { 159ae2e6c43SIngo Weinhold int i; 160ae2e6c43SIngo Weinhold int len; 161ae2e6c43SIngo Weinhold int sum; 162ae2e6c43SIngo Weinhold 163ae2e6c43SIngo Weinhold len = strlen(sCommand); 164ae2e6c43SIngo Weinhold sum = 0; 165ae2e6c43SIngo Weinhold for (i = 0; i < len; i++) 166ae2e6c43SIngo Weinhold sum += sCommand[i]; 167ae2e6c43SIngo Weinhold sum %= 256; 168ae2e6c43SIngo Weinhold 169ae2e6c43SIngo Weinhold return (sum == sCheckSum) ? 1 : 0; 170ae2e6c43SIngo Weinhold } 171ae2e6c43SIngo Weinhold 172ae2e6c43SIngo Weinhold 173ae2e6c43SIngo Weinhold // #pragma mark - command parsing 174ae2e6c43SIngo Weinhold 175ae2e6c43SIngo Weinhold 176ae2e6c43SIngo Weinhold static int 177ae2e6c43SIngo Weinhold gdb_parse_command(void) 178ae2e6c43SIngo Weinhold { 179ae2e6c43SIngo Weinhold if (!gdb_verify_checksum()) { 180ae2e6c43SIngo Weinhold gdb_nak(); 181ae2e6c43SIngo Weinhold return INIT; 182ae2e6c43SIngo Weinhold } else 183ae2e6c43SIngo Weinhold gdb_ack(); 184ae2e6c43SIngo Weinhold 185ae2e6c43SIngo Weinhold switch (sCommand[0]) { 186ae2e6c43SIngo Weinhold case 'H': 187c970c6e8SIngo Weinhold // Command H (actually Hct) is used to select 188c970c6e8SIngo Weinhold // the current thread (-1 meaning all threads) 189c970c6e8SIngo Weinhold // We just fake we recognize the the command 190c970c6e8SIngo Weinhold // and send an 'OK' response. 191ae2e6c43SIngo Weinhold gdb_reply("OK"); 192ae2e6c43SIngo Weinhold break; 193ae2e6c43SIngo Weinhold 194ae2e6c43SIngo Weinhold case 'q': 195ae2e6c43SIngo Weinhold { 196ae2e6c43SIngo Weinhold extern unsigned __data_start; 197ae2e6c43SIngo Weinhold extern unsigned __bss_start; 198ae2e6c43SIngo Weinhold 199c970c6e8SIngo Weinhold // There are several q commands: 200c970c6e8SIngo Weinhold // 201c970c6e8SIngo Weinhold // qXXXX Request info about XXXX. 202c970c6e8SIngo Weinhold // QXXXX=yyyy Set value of XXXX to yyyy. 203c970c6e8SIngo Weinhold // qOffsets Get segment offsets 204c970c6e8SIngo Weinhold // 205c970c6e8SIngo Weinhold // Currently we only support the 'qOffsets' 206c970c6e8SIngo Weinhold // form. 207c970c6e8SIngo Weinhold // 208c970c6e8SIngo Weinhold // *Note* that we actually have to lie, 209c970c6e8SIngo Weinhold // At first thought looks like we should 210c970c6e8SIngo Weinhold // return '_start', '__data_start' & 211c970c6e8SIngo Weinhold // '__bss_start', however gdb gets 212c970c6e8SIngo Weinhold // confused because the kernel link script 213c970c6e8SIngo Weinhold // pre-links at 0x80000000. To keep gdb 214c970c6e8SIngo Weinhold // gdb happy we just substract that amount. 215ae2e6c43SIngo Weinhold if (strcmp(sCommand + 1, "Offsets") == 0) { 216ae2e6c43SIngo Weinhold gdb_reply("Text=%x;Data=%x;Bss=%x", 0, 217ae2e6c43SIngo Weinhold ((unsigned)(&__data_start)) - 0x80000000, 218ae2e6c43SIngo Weinhold ((unsigned)(&__bss_start)) - 0x80000000); 219ae2e6c43SIngo Weinhold } else 220ae2e6c43SIngo Weinhold gdb_reply("ENS"); 221*777ae2fbSIngo Weinhold 222ae2e6c43SIngo Weinhold break; 223*777ae2fbSIngo Weinhold } 224ae2e6c43SIngo Weinhold 225ae2e6c43SIngo Weinhold case '?': 226c970c6e8SIngo Weinhold // command '?' is used for retrieving the signal 227c970c6e8SIngo Weinhold // that stopped the program. Fully implemeting 228c970c6e8SIngo Weinhold // this command requires help from the debugger, 229c970c6e8SIngo Weinhold // by now we just fake a SIGKILL 230ae2e6c43SIngo Weinhold gdb_reply("S09"); /* SIGKILL = 9 */ 231ae2e6c43SIngo Weinhold break; 232ae2e6c43SIngo Weinhold 233ae2e6c43SIngo Weinhold case 'g': 234ae2e6c43SIngo Weinhold { 235ae2e6c43SIngo Weinhold int cpu; 236ae2e6c43SIngo Weinhold 237c970c6e8SIngo Weinhold // command 'g' is used for reading the register 238c970c6e8SIngo Weinhold // file. Faked by now. 239c970c6e8SIngo Weinhold // 240c970c6e8SIngo Weinhold // For x86 the register order is: 241c970c6e8SIngo Weinhold // 242c970c6e8SIngo Weinhold // eax, ebx, ecx, edx, 243c970c6e8SIngo Weinhold // esp, ebp, esi, edi, 244c970c6e8SIngo Weinhold // eip, eflags, 245c970c6e8SIngo Weinhold // cs, ss, ds, es 246c970c6e8SIngo Weinhold // 247c970c6e8SIngo Weinhold // Note that even thought the segment descriptors 248c970c6e8SIngo Weinhold // are actually 16 bits wide, gdb requires them 249c970c6e8SIngo Weinhold // as 32 bit integers. Note also that for some 250c970c6e8SIngo Weinhold // reason (unknown to me) gdb wants the register 251c970c6e8SIngo Weinhold // dump in *big endian* format. 252ae2e6c43SIngo Weinhold cpu = smp_get_current_cpu(); 253ae2e6c43SIngo Weinhold gdb_regreply(dbg_register_file[cpu], 14); 254*777ae2fbSIngo Weinhold 255ae2e6c43SIngo Weinhold break; 256*777ae2fbSIngo Weinhold } 257ae2e6c43SIngo Weinhold 258ae2e6c43SIngo Weinhold case 'm': 259ae2e6c43SIngo Weinhold { 260ae2e6c43SIngo Weinhold char* ptr; 261ae2e6c43SIngo Weinhold unsigned address; 262ae2e6c43SIngo Weinhold unsigned len; 263ae2e6c43SIngo Weinhold 264c970c6e8SIngo Weinhold // The 'm' command has the form mAAA,LLL 265c970c6e8SIngo Weinhold // where AAA is the address and LLL is the 266c970c6e8SIngo Weinhold // number of bytes. 267ae2e6c43SIngo Weinhold ptr = sCommand + 1; 268ae2e6c43SIngo Weinhold address = 0; 269ae2e6c43SIngo Weinhold len = 0; 270ae2e6c43SIngo Weinhold while (ptr && *ptr && (*ptr != ',')) { 271ae2e6c43SIngo Weinhold address <<= 4; 272ae2e6c43SIngo Weinhold address += parse_nibble(*ptr); 273ae2e6c43SIngo Weinhold ptr += 1; 274ae2e6c43SIngo Weinhold } 275ae2e6c43SIngo Weinhold if (*ptr == ',') 276ae2e6c43SIngo Weinhold ptr += 1; 277ae2e6c43SIngo Weinhold 278ae2e6c43SIngo Weinhold while (ptr && *ptr) { 279ae2e6c43SIngo Weinhold len <<= 4; 280ae2e6c43SIngo Weinhold len += parse_nibble(*ptr); 281ae2e6c43SIngo Weinhold ptr += 1; 282ae2e6c43SIngo Weinhold } 283ae2e6c43SIngo Weinhold 284ae2e6c43SIngo Weinhold if (len > 128) 285ae2e6c43SIngo Weinhold len = 128; 286ae2e6c43SIngo Weinhold 287c970c6e8SIngo Weinhold // We cannot directly access the requested memory 288c970c6e8SIngo Weinhold // for gdb may be trying to access an stray pointer 289c970c6e8SIngo Weinhold // We copy the memory to a safe buffer using 290c970c6e8SIngo Weinhold // the bulletproof user_memcpy(). 291ae2e6c43SIngo Weinhold if (user_memcpy(sSafeMemory, (char*)address, len) < 0) 292ae2e6c43SIngo Weinhold gdb_reply("E02"); 293ae2e6c43SIngo Weinhold else 294ae2e6c43SIngo Weinhold gdb_memreply(sSafeMemory, len); 295*777ae2fbSIngo Weinhold 296ae2e6c43SIngo Weinhold break; 297*777ae2fbSIngo Weinhold } 298ae2e6c43SIngo Weinhold 299ae2e6c43SIngo Weinhold case 'k': 300c970c6e8SIngo Weinhold // Command 'k' actual semantics is 'kill the damn thing'. 301c970c6e8SIngo Weinhold // However gdb sends that command when you disconnect 302c970c6e8SIngo Weinhold // from a debug session. I guess that 'kill' for the 303c970c6e8SIngo Weinhold // kernel would map to reboot... however that's a 304c970c6e8SIngo Weinhold // a very mean thing to do, instead we just quit 305c970c6e8SIngo Weinhold // the gdb state machine and fallback to the regular 306c970c6e8SIngo Weinhold // kernel debugger command prompt. 307ae2e6c43SIngo Weinhold return QUIT; 308ae2e6c43SIngo Weinhold 309ae2e6c43SIngo Weinhold default: 310ae2e6c43SIngo Weinhold gdb_reply("E01"); 311ae2e6c43SIngo Weinhold break; 312ae2e6c43SIngo Weinhold } 313ae2e6c43SIngo Weinhold 314ae2e6c43SIngo Weinhold return WAITACK; 315ae2e6c43SIngo Weinhold } 316ae2e6c43SIngo Weinhold 317ae2e6c43SIngo Weinhold 318ae2e6c43SIngo Weinhold // #pragma mark - protocol state machine 319ae2e6c43SIngo Weinhold 320ae2e6c43SIngo Weinhold 321ae2e6c43SIngo Weinhold static int 322ae2e6c43SIngo Weinhold gdb_init_handler(int input) 323ae2e6c43SIngo Weinhold { 324ae2e6c43SIngo Weinhold switch (input) { 325ae2e6c43SIngo Weinhold case '$': 326ae2e6c43SIngo Weinhold memset(sCommand, 0, sizeof(sCommand)); 327ae2e6c43SIngo Weinhold sCommandIndex = 0; 328ae2e6c43SIngo Weinhold return CMDREAD; 329ae2e6c43SIngo Weinhold 330ae2e6c43SIngo Weinhold default: 331ae2e6c43SIngo Weinhold #if 0 332ae2e6c43SIngo Weinhold gdb_nak(); 333ae2e6c43SIngo Weinhold #else 334c970c6e8SIngo Weinhold // looks to me like we should send 335c970c6e8SIngo Weinhold // a NAK here but it kinda works 336c970c6e8SIngo Weinhold // better if we just gobble all 337c970c6e8SIngo Weinhold // junk chars silently 338ae2e6c43SIngo Weinhold #endif 339ae2e6c43SIngo Weinhold return INIT; 340ae2e6c43SIngo Weinhold } 341ae2e6c43SIngo Weinhold } 342ae2e6c43SIngo Weinhold 343ae2e6c43SIngo Weinhold 344ae2e6c43SIngo Weinhold static int 345ae2e6c43SIngo Weinhold gdb_cmdread_handler(int input) 346ae2e6c43SIngo Weinhold { 347ae2e6c43SIngo Weinhold switch (input) { 348ae2e6c43SIngo Weinhold case '#': 349ae2e6c43SIngo Weinhold return CKSUM1; 350ae2e6c43SIngo Weinhold 351ae2e6c43SIngo Weinhold default: 352ae2e6c43SIngo Weinhold sCommand[sCommandIndex] = input; 353ae2e6c43SIngo Weinhold sCommandIndex += 1; 354ae2e6c43SIngo Weinhold return CMDREAD; 355ae2e6c43SIngo Weinhold } 356ae2e6c43SIngo Weinhold } 357ae2e6c43SIngo Weinhold 358ae2e6c43SIngo Weinhold 359ae2e6c43SIngo Weinhold static int 360ae2e6c43SIngo Weinhold gdb_cksum1_handler(int input) 361ae2e6c43SIngo Weinhold { 362ae2e6c43SIngo Weinhold int nibble = parse_nibble(input); 363ae2e6c43SIngo Weinhold 364ae2e6c43SIngo Weinhold if (nibble == 0xff) { 365ae2e6c43SIngo Weinhold #if 0 366ae2e6c43SIngo Weinhold gdb_nak(); 367ae2e6c43SIngo Weinhold return INIT; 368ae2e6c43SIngo Weinhold #else 369c970c6e8SIngo Weinhold // looks to me like we should send 370c970c6e8SIngo Weinhold // a NAK here but it kinda works 371c970c6e8SIngo Weinhold // better if we just gobble all 372c970c6e8SIngo Weinhold // junk chars silently 373ae2e6c43SIngo Weinhold #endif 374ae2e6c43SIngo Weinhold } 375ae2e6c43SIngo Weinhold 376ae2e6c43SIngo Weinhold sCheckSum = nibble << 4; 377ae2e6c43SIngo Weinhold 378ae2e6c43SIngo Weinhold return CKSUM2; 379ae2e6c43SIngo Weinhold } 380ae2e6c43SIngo Weinhold 381ae2e6c43SIngo Weinhold 382ae2e6c43SIngo Weinhold static int 383ae2e6c43SIngo Weinhold gdb_cksum2_handler(int input) 384ae2e6c43SIngo Weinhold { 385ae2e6c43SIngo Weinhold int nibble = parse_nibble(input); 386ae2e6c43SIngo Weinhold 387ae2e6c43SIngo Weinhold if (nibble == 0xff) { 388ae2e6c43SIngo Weinhold #if 0 389ae2e6c43SIngo Weinhold gdb_nak(); 390ae2e6c43SIngo Weinhold return INIT; 391ae2e6c43SIngo Weinhold #else 392c970c6e8SIngo Weinhold // looks to me like we should send 393c970c6e8SIngo Weinhold // a NAK here but it kinda works 394c970c6e8SIngo Weinhold // better if we just gobble all 395c970c6e8SIngo Weinhold // junk chars silently 396ae2e6c43SIngo Weinhold #endif 397ae2e6c43SIngo Weinhold } 398ae2e6c43SIngo Weinhold 399ae2e6c43SIngo Weinhold sCheckSum += nibble; 400ae2e6c43SIngo Weinhold 401ae2e6c43SIngo Weinhold return gdb_parse_command(); 402ae2e6c43SIngo Weinhold } 403ae2e6c43SIngo Weinhold 404ae2e6c43SIngo Weinhold 405ae2e6c43SIngo Weinhold static int 406ae2e6c43SIngo Weinhold gdb_waitack_handler(int input) 407ae2e6c43SIngo Weinhold { 408ae2e6c43SIngo Weinhold switch (input) { 409ae2e6c43SIngo Weinhold case '+': 410ae2e6c43SIngo Weinhold return INIT; 411ae2e6c43SIngo Weinhold case '-': 412ae2e6c43SIngo Weinhold gdb_resend_reply(); 413ae2e6c43SIngo Weinhold return WAITACK; 414ae2e6c43SIngo Weinhold 415ae2e6c43SIngo Weinhold default: 416c970c6e8SIngo Weinhold // looks like gdb and us are out of sync, 417c970c6e8SIngo Weinhold // send a NAK and retry from INIT state. 418ae2e6c43SIngo Weinhold gdb_nak(); 419ae2e6c43SIngo Weinhold return INIT; 420ae2e6c43SIngo Weinhold } 421ae2e6c43SIngo Weinhold } 422ae2e6c43SIngo Weinhold 423ae2e6c43SIngo Weinhold 424ae2e6c43SIngo Weinhold static int 425ae2e6c43SIngo Weinhold gdb_quit_handler(int input) 426ae2e6c43SIngo Weinhold { 427ae2e6c43SIngo Weinhold (void)(input); 428ae2e6c43SIngo Weinhold 429c970c6e8SIngo Weinhold // actually we should never be here 430ae2e6c43SIngo Weinhold return QUIT; 431ae2e6c43SIngo Weinhold } 432ae2e6c43SIngo Weinhold 433ae2e6c43SIngo Weinhold 434ae2e6c43SIngo Weinhold static int (*dispatch_table[GDBSTATES])(int) = { 435ae2e6c43SIngo Weinhold &gdb_init_handler, 436ae2e6c43SIngo Weinhold &gdb_cmdread_handler, 437ae2e6c43SIngo Weinhold &gdb_cksum1_handler, 438ae2e6c43SIngo Weinhold &gdb_cksum2_handler, 439ae2e6c43SIngo Weinhold &gdb_waitack_handler, 440ae2e6c43SIngo Weinhold &gdb_quit_handler 441ae2e6c43SIngo Weinhold }; 442ae2e6c43SIngo Weinhold 443ae2e6c43SIngo Weinhold 444ae2e6c43SIngo Weinhold static int 445ae2e6c43SIngo Weinhold gdb_state_dispatch(int curr, int input) 446ae2e6c43SIngo Weinhold { 447ae2e6c43SIngo Weinhold if (curr < INIT || curr >= GDBSTATES) 448ae2e6c43SIngo Weinhold return QUIT; 449ae2e6c43SIngo Weinhold 450ae2e6c43SIngo Weinhold return dispatch_table[curr](input); 451ae2e6c43SIngo Weinhold } 452ae2e6c43SIngo Weinhold 453ae2e6c43SIngo Weinhold 454ae2e6c43SIngo Weinhold static int 455ae2e6c43SIngo Weinhold gdb_state_machine(void) 456ae2e6c43SIngo Weinhold { 457ae2e6c43SIngo Weinhold int state = INIT; 458ae2e6c43SIngo Weinhold int c; 459ae2e6c43SIngo Weinhold 460ae2e6c43SIngo Weinhold while (state != QUIT) { 461ae2e6c43SIngo Weinhold c = arch_debug_serial_getchar(); 462ae2e6c43SIngo Weinhold state = gdb_state_dispatch(state, c); 463ae2e6c43SIngo Weinhold } 464ae2e6c43SIngo Weinhold 465ae2e6c43SIngo Weinhold return 0; 466ae2e6c43SIngo Weinhold } 467ae2e6c43SIngo Weinhold 468ae2e6c43SIngo Weinhold 469ae2e6c43SIngo Weinhold // #pragma mark - 470ae2e6c43SIngo Weinhold 471ae2e6c43SIngo Weinhold 472ae2e6c43SIngo Weinhold int 473ae2e6c43SIngo Weinhold cmd_gdb(int argc, char** argv) 474ae2e6c43SIngo Weinhold { 475ae2e6c43SIngo Weinhold (void)(argc); 476ae2e6c43SIngo Weinhold (void)(argv); 477ae2e6c43SIngo Weinhold 478ae2e6c43SIngo Weinhold return gdb_state_machine(); 479ae2e6c43SIngo Weinhold } 480