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