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