1/** \file 2 * \brief Architecture-independent parts of in-kernel GDB stub. 3 * 4 * This file implements the kernel-side GDB stubs for remote debugging when 5 * running on hardware. It is loosely based on the public domain i386-stub.c 6 * which is part of the GDB sources. 7 * 8 * The following gdb commands are supported: 9 * 10 *<table> 11 *<tr><td>command</td><td>function</td><td>Return value</td></tr> 12 *<tr><td>?</td><td>What was the last sigval ?</td><td>SNN (signal NN)</td></tr> 13 *<tr><td>g</td><td>return the value of the CPU registers</td><td>hex data or ENN</td></tr> 14 *<tr><td>G</td><td>set the value of the CPU registers</td><td>OK or ENN</td></tr> 15 *<tr><td>p</td><td>read the value of a single CPU register</td><td>hex data or ENN</td></tr> 16 *<tr><td>P</td><td>set the value of a single CPU register</td><td>OK or ENN</td></tr> 17 *<tr><td>mAA..AA,LLLL</td><td>Read LLLL bytes at address AA..AA</td><td>hex data or ENN</td></tr> 18 *<tr><td>MAA..AA,LLLL:</td><td>Write LLLL bytes at address AA.AA</td><td>OK or ENN</td></tr> 19 *<tr><td>c</td><td>Resume at current address</td><td>SNN (signal NN)</td></tr> 20 *<tr><td>cAA..AA</td><td>Continue at address AA..AA</td><td>SNN</td></tr> 21 *<tr><td>s</td><td>Step one instruction</td><td>SNN</td></tr> 22 *<tr><td>sAA..AA</td><td>Step one instruction from AA..AA</td><td>SNN</td></tr> 23 *<tr><td>D</td><td>GDB detached -- attempt to resume</td><td>(no reply)</td></tr> 24 *<tr><td>k</td><td>kill -- reboots the system</td><td>(no reply)</td></tr> 25 *</table> 26 * 27 * All commands and responses are sent with a packet which includes a 28 * checksum. A packet consists of $\<packet info\>#\<checksum\> where: 29 * 30 * - \<packet info\> :: characters representing the command or response 31 * - \<checksum\> :: two hex digits computed as mod-256 sum of \<packet info\> 32 * 33 * When a packet is received, it is first acknowledged with either '+' or '-'. 34 * '+' indicates a successful transfer. '-' indicates a failed transfer. 35 * 36 * Example: 37 * - Host: $m0,10#2a 38 * - Reply: +$00010203040506070809101112131415#42 39 */ 40 41/* 42 * Copyright (c) 2007, ETH Zurich. 43 * All rights reserved. 44 * 45 * This file is distributed under the terms in the attached LICENSE file. 46 * If you do not find this file, copies can be found by writing to: 47 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 48 */ 49 50#include <kernel.h> 51#include <barrelfish_kpi/cpu.h> 52#include <stdio.h> 53#include <string.h> 54#include <serial.h> 55#include <exec.h> 56#include <gdb_stub.h> 57#include <arch_gdb_stub.h> 58 59/** \brief Flag. Enables debug messages from the stub itself. */ 60#define DEBUG_ENABLED true 61 62/** \brief Quick-and-dirty debug message macro. */ 63#define DEBUG(...) \ 64 if (DEBUG_ENABLED) { \ 65 debug(SUBSYS_GDB, __VA_ARGS__); \ 66 } 67 68/** \brief Defines the maximum number of characters in in/outbound buffers. 69 * 70 * At least NUMREGBYTES * 2 are needed for register packets. */ 71#define BUFMAX 512 72 73/** \brief Wrapper for debugger output. */ 74static inline void myputchar(char c) 75{ 76 serial_debug_putchar(c); 77} 78 79/** \brief Wrapper for debugger input. */ 80static inline char mygetchar(void) 81{ 82 return serial_debug_getchar(); 83} 84 85/** \brief Convert an ASCII hex character to its numeric value. 86 * \return -1 if the character is invalid. */ 87static int fromhex(char ch) 88{ 89 if ((ch >= 'a') && (ch <= 'f')) { 90 return ch - 'a' + 10; 91 } else if ((ch >= '0') && (ch <= '9')) { 92 return ch - '0'; 93 } else if ((ch >= 'A') && (ch <= 'F')) { 94 return ch - 'A' + 10; 95 } else { 96 return -1; 97 } 98} 99 100/** \brief Convert a number 0..15 to the corresponding hex character. */ 101static char tohex(int i) 102{ 103 static const char hexchars[] = "0123456789abcdef"; 104 assert(i >= 0 && i <= 0xf); 105 return hexchars[i]; 106} 107 108/** \brief Parse a hex-encoded integer 109 * 110 * Reads a hex-encoded integer into val, stopping at the first non-hex character 111 * \return first position after the end of the consumed characters 112 */ 113static const char * NONNULL NTS parse_hex_val(const char * NONNULL NTS str, 114 uintptr_t * NONNULL val) 115{ 116 uintptr_t ret = 0; 117 118 for (int pos = 0; true; pos++) { 119 int value = fromhex(str[pos]); 120 if (value >= 0) { 121 assert(pos < sizeof(uintptr_t) * 2); // overflow 122 ret = (ret << 4) | value; 123 } else { 124 *val = ret; 125 return &str[pos]; 126 } 127 } 128} 129 130/** \brief Read memory region into a buffer as a hex string. 131 * 132 * Converts the memory pointed to by mem (of length memlen) into a hex string, 133 * placing the result into buf (of length buflen), and terminating with a \\0. 134 * \return Number of characters written on success, negative on failure. 135 * May fail if a page fault would be incurred. 136 */ 137static int mem_to_hex(lvaddr_t mem, size_t memlen, 138 char * NONNULL COUNT(buflen) buf, size_t buflen) 139{ 140 int bufpos = 0; 141 uint8_t ch; 142 int r; 143 144 if (buflen < memlen * 2 + 1) { 145 return -1; // not enough space in output buffer 146 } 147 148 for (int mempos = 0; mempos < memlen; mempos++) { 149 r = gdb_arch_read_byte((uint8_t * SAFE NONNULL)TC(mem + mempos), &ch); 150 if (r != 0) { 151 return r; 152 } 153 154 buf[bufpos++] = tohex(ch >> 4); // top bits of char 155 buf[bufpos++] = tohex(ch & 0xf); // bottom bits of char 156 } 157 158 buf[bufpos++] = '\0'; 159 return bufpos; 160} 161 162/** \brief Copy data from hex string in buffer to raw memory region. 163 * 164 * Writes data in the provided hex string buffer into the given memory region. 165 * \return zero on success, negative on failure. 166 * May fail if a page fault would be incurred. 167 */ 168static int hex_to_mem(const char * NONNULL NT COUNT(memlen * 2) buf, 169 lvaddr_t mem, size_t memlen) 170{ 171 for (int mempos = 0; mempos < memlen; mempos++) { 172 uint8_t ch; 173 174 assert(*buf != '\0'); 175 ch = fromhex(*buf++) << 4; 176 assert(*buf != '\0'); 177 ch += fromhex(*buf++); 178 179 int r = gdb_arch_write_byte(&((uint8_t * SAFE NONNULL)TC(mem))[mempos], 180 ch); 181 if (r != 0) { 182 return r; 183 } 184 } 185 186 return 0; 187} 188 189/** \brief Wait to receive a valid checksummed packet from GDB. 190 * 191 * Scans input for the sequence $\<packet info\>#\<checksum\>. If the 192 * checksum is valid, acknowledges it to the sender and returns the buffer. 193 * If invalid, reports failure to the sender and waits for the retransmission. 194 */ 195static const char * NONNULL NTS getpacket(void) 196{ 197 static char (NT buffer)[BUFMAX]; 198 uint8_t checksum, xmitcsum; 199 int bufpos; 200 char ch = 0; /* shut up a useless deputy warning */ 201 202 while (true) { 203 /* wait around for the start character, ignore all other characters */ 204 while (mygetchar() != '$') {} 205 206retry: 207 checksum = 0; 208 bufpos = 0; 209 210 /* now, read until a # or end of buffer is found */ 211 while (bufpos < BUFMAX - 1) { 212 ch = mygetchar(); 213 if (ch == '$') { 214 goto retry; // invalid 215 } else if (ch == '#') { 216 break; // found start of checksum 217 } 218 checksum += ch; 219 buffer[bufpos++] = ch; 220 } 221 buffer[bufpos] = 0; 222 223 if (bufpos == BUFMAX - 1) { 224 DEBUG("Warning: Incoming buffer full in getpacket()"); 225 } 226 227 if (ch == '#') { 228 xmitcsum = fromhex(mygetchar()) << 4; 229 xmitcsum += fromhex(mygetchar()); 230 231 if (checksum != xmitcsum) { 232 DEBUG("bad checksum. My count=0x%x, sent=0x%x. buf='%s'", 233 checksum, xmitcsum, buffer); 234 myputchar('-'); // failed checksum 235 } else { 236 myputchar('+'); // successful transfer 237 return buffer; 238 } 239 } 240 } 241} 242 243/** \brief Send the packet in the buffer, adding a checksum. 244 * 245 * Sends the packet, using the format: $\<packet info\>#\<checksum\>. 246 * Loops until it receives an acknowledgement response ('+') from GDB. 247 */ 248static void putpacket(char * NONNULL NTS buffer) 249{ 250 do { 251 uint8_t checksum = 0; 252 myputchar('$'); 253 254 for (int pos = 0; buffer[pos] != '\0'; pos++) { 255 char ch = buffer[pos]; 256 myputchar(ch); 257 checksum += ch; 258 } 259 260 myputchar('#'); 261 myputchar(tohex(checksum >> 4)); // top bits of checksum 262 myputchar(tohex(checksum & 0xf)); // bottom bits of checksum 263 } while (mygetchar() != '+'); 264} 265 266/** \brief Generic entry point to the GDB stub. 267 * 268 * Wait for a remote GDB to start talking to us, and then service its requests. 269 * This function should run on a different stack the main kernel, and does not 270 * return. 271 * \param signal_code Unix-style signal value indicating reason for interruption 272 * \param init_message Optional initial message to send to the remote GDB 273 */ 274void gdb_stub_entry(int signal_code, char * OPT NTS init_message) 275{ 276 const char * NONNULL NTS request; 277 const char * NONNULL NTS newpos; 278 static char (NT buffer)[BUFMAX]; 279 static bool gdb_connected = false; 280 char *reply; 281 uintptr_t addr, length, regnum, value; 282 int r; 283 284 /* send initial message, if gdb is listening for it */ 285 if (init_message && gdb_connected) { 286 putpacket(init_message); 287 } else if (!gdb_connected) { 288 printk(LOG_NOTE, "Waiting for GDB connection...\n"); 289 } 290 291 /* loop handling requests */ 292 while (true) { 293 request = getpacket(); 294 gdb_connected = true; 295 reply = buffer; 296 297 switch (*request++) { 298 299 case '?': 300 /* Indicate reason target halted */ 301 r = snprintf(buffer, sizeof(buffer), "S%02hhx", signal_code); 302 assert(r < sizeof(buffer)); 303 if (r >= sizeof(buffer)) { 304 /* ensure termination */ 305 buffer[sizeof(buffer) - 1] = '\0'; 306 } 307 break; 308 309 case 'g': 310 /* Read general registers */ 311 r = mem_to_hex((lvaddr_t)GDB_ARCH_REGADDR, GDB_ARCH_REGBYTES, 312 buffer, sizeof(buffer)); 313 if (r < 0) { 314 reply = "E03"; 315 } 316 break; 317 318 case 'G': 319 /* Write general registers */ 320 r = hex_to_mem(request, (lvaddr_t)GDB_ARCH_REGADDR, 321 GDB_ARCH_REGBYTES); 322 if (r == 0) { 323 reply = "OK"; 324 } else { 325 reply = "E03"; 326 } 327 break; 328 329 case 'p': 330 /* Read a single register */ 331 newpos = parse_hex_val(request, ®num); 332 if (newpos == request) { 333 reply = "E01"; 334 break; 335 } 336 337 r = gdb_arch_get_register(regnum, &value); 338 if (r != 0) { 339 reply = "E02"; 340 break; 341 } 342 343 r = mem_to_hex((lvaddr_t)&value, sizeof(uintptr_t), buffer, 344 sizeof(buffer)); 345 if (r < 0) { 346 reply = "E03"; 347 } 348 break; 349 350 case 'P': 351 /* Write a single register */ 352 newpos = parse_hex_val(request, ®num); 353 if (newpos == request || *newpos != '=') { 354 reply = "E01"; 355 break; 356 } 357 request = newpos + 1; 358 newpos = parse_hex_val(request, &value); 359 if (newpos == request) { 360 reply = "E01"; 361 break; 362 } 363 364 r = gdb_arch_set_register(regnum, value); 365 if (r == 0) { 366 reply = "OK"; 367 } else { 368 reply = "E02"; 369 } 370 break; 371 372 case 'm': 373 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 374 request = parse_hex_val(request, &addr); 375 if (addr == 0 || *(request++) != ',') { 376 reply = "E01"; 377 break; 378 } 379 request = parse_hex_val(request, &length); 380 if (length == 0) { 381 reply = "E01"; 382 break; 383 } 384 r = mem_to_hex(addr, length, buffer, sizeof(buffer)); 385 if (r < 0) { 386 reply = "E03"; 387 } 388 break; 389 390 case 'M': 391 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 392 request = parse_hex_val(request, &addr); 393 if (addr == 0 || *request++ != ',') { 394 reply = "E01"; 395 break; 396 } 397 request = parse_hex_val(request, &length); 398 if (length == 0 || *request++ != ':') { 399 reply = "E01"; 400 break; 401 } 402 r = hex_to_mem(request, addr, length); 403 if (r == 0) { 404 reply = "OK"; 405 } else { 406 reply = "E03"; 407 } 408 break; 409 410 case 's': 411 /* Single step */ 412 parse_hex_val(request, &addr); // try to read optional parameter 413 gdb_arch_single_step(addr); // should not return 414 reply = "E02"; 415 break; 416 417 case 'c': 418 /* Continue execution */ 419 parse_hex_val(request, &addr); // try to read optional parameter 420 gdb_arch_continue(addr); // should not return 421 reply = "E02"; 422 break; 423 424 case 'D': 425 /* GDB detached, try to continue */ 426 printk(LOG_NOTE, "GDB has detached. Attempting to continue..."); 427 gdb_connected = false; 428 gdb_arch_continue(0); 429 break; 430 431 case 'k': 432 /* Kill the program */ 433 printk(LOG_NOTE, "Kill requested by remote GDB.\n"); 434 reboot(); 435 break; 436 437 default: 438 /* unsupported command */ 439 reply = ""; 440 break; 441 } 442 443 putpacket(reply); 444 } 445} 446