ia64/xen-unstable

annotate xen/common/gdbstub.c @ 11649:d78b31dd07e8

[XEN] gdbstub return value is used to determine whether or not
to continue execution.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Sep 27 14:28:26 2006 +0100 (2006-09-27)
parents b042bf974f3a
children 79b49fca62e8
rev   line source
kaf24@8607 1 /*
kaf24@8607 2 * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
kaf24@8607 3 * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp>
kaf24@8607 4 * VA Linux Systems Japan. K.K.
kaf24@8607 5 *
kaf24@8607 6 * gdbstub arch neutral part
kaf24@8607 7 * Based on x86 cdb (xen/arch/x86/cdb.c) and ppc gdbstub(xen/common/gdbstub.c)
kaf24@8607 8 * But extensively modified.
kaf24@8607 9 *
kaf24@8607 10 * This program is free software; you can redistribute it and/or modify
kaf24@8607 11 * it under the terms of the GNU General Public License as published by
kaf24@8607 12 * the Free Software Foundation; either version 2 of the License, or
kaf24@8607 13 * (at your option) any later version.
kaf24@8607 14 *
kaf24@8607 15 * This program is distributed in the hope that it will be useful,
kaf24@8607 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@8607 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@8607 18 * GNU General Public License for more details.
kaf24@8607 19 *
kaf24@8607 20 * You should have received a copy of the GNU General Public License
kaf24@8607 21 * along with this program; if not, write to the Free Software
kaf24@8607 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@8607 23 */
kaf24@8607 24
kaf24@8607 25 /*
kaf24@8607 26 * gdbstub: implements the architecture independant parts of the
kaf24@8607 27 * gdb remote protocol.
kaf24@8607 28 */
kaf24@8607 29
kaf24@8607 30 /* We try to avoid assuming much about what the rest of the system is
kaf24@8607 31 doing. In particular, dynamic memory allocation is out of the
kaf24@8607 32 question. */
kaf24@8607 33
kaf24@8607 34 /* Resuming after we've stopped used to work, but more through luck
kaf24@8607 35 than any actual intention. It doesn't at the moment. */
kaf24@8607 36
kaf24@8607 37 #include <xen/lib.h>
kaf24@8607 38 #include <xen/spinlock.h>
kaf24@8607 39 #include <xen/serial.h>
kaf24@8607 40 #include <xen/irq.h>
kaf24@8607 41 #include <asm/debugger.h>
kaf24@8607 42 #include <xen/init.h>
kaf24@8607 43 #include <xen/smp.h>
kaf24@8607 44 #include <xen/console.h>
kaf24@8607 45
kaf24@8607 46 /* Printk isn't particularly safe just after we've trapped to the
kaf24@8607 47 debugger. so avoid it. */
kaf24@8607 48 #define dbg_printk(...)
kaf24@8607 49 /*#define dbg_printk(...) printk(__VA_ARGS__)*/
kaf24@8607 50
kaf24@8607 51 #define GDB_RETRY_MAX 10
kaf24@8607 52
kaf24@8607 53 static char opt_gdb[30] = "none";
kaf24@8607 54 string_param("gdb", opt_gdb);
kaf24@8607 55
kaf24@11627 56 static void gdbstub_console_puts(const char *str);
kaf24@11627 57
kaf24@8607 58 /* value <-> char (de)serialzers */
kaf24@8607 59 char
kaf24@8607 60 hex2char(unsigned long x)
kaf24@8607 61 {
kaf24@8607 62 const char array[] = "0123456789abcdef";
kaf24@8607 63
kaf24@8607 64 return array[x & 15];
kaf24@8607 65 }
kaf24@8607 66
kaf24@8607 67 int
kaf24@8607 68 char2hex(unsigned char c)
kaf24@8607 69 {
kaf24@8607 70 if ( (c >= '0') && (c <= '9') )
kaf24@8607 71 return c - '0';
kaf24@8607 72 else if ( (c >= 'a') && (c <= 'f') )
kaf24@8607 73 return c - 'a' + 10;
kaf24@8607 74 else if ( (c >= 'A') && (c <= 'F') )
kaf24@8607 75 return c - 'A' + 10;
kaf24@8607 76 else
kaf24@8607 77 BUG();
kaf24@8607 78 return -1;
kaf24@8607 79 }
kaf24@8607 80
kaf24@8607 81 char
kaf24@8607 82 str2hex(const char *str)
kaf24@8607 83 {
kaf24@8607 84 return (char2hex(str[0]) << 4) | char2hex(str[1]);
kaf24@8607 85 }
kaf24@8607 86
kaf24@8607 87 unsigned long
kaf24@8607 88 str2ulong(const char *str, unsigned long bytes)
kaf24@8607 89 {
kaf24@8607 90 unsigned long x = 0;
kaf24@8607 91 unsigned long i = 0;
kaf24@8607 92
kaf24@8607 93 while ( *str && (i < (bytes * 2)) )
kaf24@8607 94 {
kaf24@8607 95 x <<= 4;
kaf24@8607 96 x += char2hex(*str);
kaf24@8607 97 ++str;
kaf24@8607 98 ++i;
kaf24@8607 99 }
kaf24@8607 100
kaf24@8607 101 return x;
kaf24@8607 102 }
kaf24@8607 103
kaf24@8607 104 /* gdb io wrappers */
kaf24@8607 105 static signed long
kaf24@8607 106 gdb_io_write(const char *buf, unsigned long len, struct gdb_context *ctx)
kaf24@8607 107 {
kaf24@8607 108 int i;
kaf24@8607 109 for ( i = 0; i < len; i++ )
kaf24@8607 110 serial_putc(ctx->serhnd, buf[i]);
kaf24@8607 111 return i;
kaf24@8607 112 }
kaf24@8607 113
kaf24@8607 114 static int
kaf24@8607 115 gdb_io_write_char(u8 data, struct gdb_context *ctx)
kaf24@8607 116 {
kaf24@8607 117 return gdb_io_write((char*)&data, 1, ctx);
kaf24@8607 118 }
kaf24@8607 119
kaf24@8607 120 static unsigned char
kaf24@8607 121 gdb_io_read(struct gdb_context *ctx)
kaf24@8607 122 {
kaf24@8607 123 return serial_getc(ctx->serhnd);
kaf24@8607 124 }
kaf24@8607 125
kaf24@8607 126 /* Receive a command. Returns -1 on csum error, 0 otherwise. */
kaf24@8607 127 /* Does not acknowledge. */
kaf24@8607 128 static int
kaf24@8607 129 attempt_receive_packet(struct gdb_context *ctx)
kaf24@8607 130 {
kaf24@8607 131 u8 csum;
kaf24@8607 132 u8 received_csum;
kaf24@8607 133 u8 ch;
kaf24@8607 134
kaf24@8607 135 /* Skip over everything up to the first '$' */
kaf24@8607 136 while ( (ch = gdb_io_read(ctx)) != '$' )
kaf24@8607 137 continue;
kaf24@8607 138
kaf24@8607 139 csum = 0;
kaf24@8607 140 for ( ctx->in_bytes = 0;
kaf24@8607 141 ctx->in_bytes < sizeof(ctx->in_buf);
kaf24@8607 142 ctx->in_bytes++ )
kaf24@8607 143 {
kaf24@8607 144 ch = gdb_io_read(ctx);
kaf24@8607 145 if ( ch == '#' )
kaf24@8607 146 break;
kaf24@8607 147 ctx->in_buf[ctx->in_bytes] = ch;
kaf24@8607 148 csum += ch;
kaf24@8607 149 }
kaf24@8607 150
kaf24@8607 151 if ( ctx->in_bytes == sizeof(ctx->in_buf) )
kaf24@8607 152 {
kaf24@8607 153 dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
kaf24@8607 154 return -1;
kaf24@8607 155 }
kaf24@8607 156
kaf24@8607 157 ctx->in_buf[ctx->in_bytes] = '\0';
kaf24@8607 158 received_csum = char2hex(gdb_io_read(ctx)) * 16 +
kaf24@8607 159 char2hex(gdb_io_read(ctx));
kaf24@8607 160
kaf24@8607 161 return (received_csum == csum) ? 0 : -1;
kaf24@8607 162 }
kaf24@8607 163
kaf24@8607 164 /* Receive a command, discarding up to ten packets with csum
kaf24@8607 165 * errors. Acknowledges all received packets. */
kaf24@8607 166 static int
kaf24@8607 167 receive_command(struct gdb_context *ctx)
kaf24@8607 168 {
kaf24@8607 169 int r, count = 0;
kaf24@8607 170
kaf24@8607 171 count = 0;
kaf24@8607 172 do {
kaf24@8607 173 r = attempt_receive_packet(ctx);
kaf24@8607 174 gdb_io_write_char((r < 0) ? '-' : '+', ctx);
kaf24@8607 175 count++;
kaf24@8607 176 } while ( (r < 0) && (count < GDB_RETRY_MAX) );
kaf24@8607 177
kaf24@8607 178 return r;
kaf24@8607 179 }
kaf24@8607 180
kaf24@8607 181 /* routines to send reply packets */
kaf24@8607 182
kaf24@8607 183 static void
kaf24@8607 184 gdb_start_packet(struct gdb_context *ctx)
kaf24@8607 185 {
kaf24@8607 186 ctx->out_buf[0] = '$';
kaf24@8607 187 ctx->out_offset = 1;
kaf24@8607 188 ctx->out_csum = 0;
kaf24@8607 189 }
kaf24@8607 190
kaf24@8607 191 static void
kaf24@8607 192 gdb_write_to_packet_char(u8 data, struct gdb_context *ctx)
kaf24@8607 193 {
kaf24@8607 194 ctx->out_csum += data;
kaf24@8607 195 ctx->out_buf[ctx->out_offset] = data;
kaf24@8607 196 ctx->out_offset++;
kaf24@8607 197 }
kaf24@8607 198
kaf24@8607 199 void
kaf24@8607 200 gdb_write_to_packet(const char *buf, int count, struct gdb_context *ctx)
kaf24@8607 201 {
kaf24@8607 202 int x;
kaf24@8607 203 for ( x = 0; x < count; x++ )
kaf24@8607 204 gdb_write_to_packet_char(buf[x], ctx);
kaf24@8607 205 }
kaf24@8607 206
kaf24@8607 207 void
kaf24@8607 208 gdb_write_to_packet_str(const char *buf, struct gdb_context *ctx)
kaf24@8607 209 {
kaf24@8607 210 gdb_write_to_packet(buf, strlen(buf), ctx);
kaf24@8607 211 }
kaf24@8607 212
kaf24@8607 213 void
kaf24@8607 214 gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
kaf24@8607 215 {
kaf24@8607 216 char buf[sizeof(unsigned long) * 2 + 1];
kaf24@8607 217 int i = sizeof(unsigned long) * 2;
kaf24@8607 218 int width = int_size * 2;
kaf24@8607 219
kaf24@8607 220 buf[sizeof(unsigned long) * 2] = 0;
kaf24@8607 221
kaf24@8607 222 switch ( int_size )
kaf24@8607 223 {
kaf24@8607 224 case sizeof(u8):
kaf24@8607 225 case sizeof(u16):
kaf24@8607 226 case sizeof(u32):
kaf24@8607 227 case sizeof(u64):
kaf24@8607 228 break;
kaf24@8607 229 default:
kaf24@8607 230 dbg_printk("WARNING: %s x: 0x%lx int_size: %d\n",
kaf24@8607 231 __func__, x, int_size);
kaf24@8607 232 break;
kaf24@8607 233 }
kaf24@8607 234
kaf24@8607 235 do {
kaf24@8607 236 buf[--i] = hex2char(x & 15);
kaf24@8607 237 x >>= 4;
kaf24@8607 238 } while ( x );
kaf24@8607 239
kaf24@8607 240 while ( (i + width) > (sizeof(unsigned long) * 2) )
kaf24@8607 241 buf[--i] = '0';
kaf24@8607 242
kaf24@8607 243 gdb_write_to_packet(&buf[i], width, ctx);
kaf24@8607 244 }
kaf24@8607 245
kaf24@8607 246 static int
kaf24@8607 247 gdb_check_ack(struct gdb_context *ctx)
kaf24@8607 248 {
kaf24@8607 249 u8 c = gdb_io_read(ctx);
kaf24@8607 250
kaf24@8607 251 switch ( c )
kaf24@8607 252 {
kaf24@8607 253 case '+':
kaf24@8607 254 return 1;
kaf24@8607 255 case '-':
kaf24@8607 256 return 0;
kaf24@8607 257 default:
kaf24@8607 258 printk("Bad ack: %c\n", c);
kaf24@8607 259 return 0;
kaf24@8607 260 }
kaf24@8607 261 }
kaf24@8607 262
kaf24@8607 263 /* Return 0 if the reply was successfully received, !0 otherwise. */
kaf24@8607 264 void
kaf24@8607 265 gdb_send_packet(struct gdb_context *ctx)
kaf24@8607 266 {
kaf24@8607 267 char buf[3];
kaf24@8607 268 int count;
kaf24@8607 269
kaf24@8607 270 sprintf(buf, "%.02x\n", ctx->out_csum);
kaf24@8607 271
kaf24@8607 272 gdb_write_to_packet_char('#', ctx);
kaf24@8607 273 gdb_write_to_packet(buf, 2, ctx);
kaf24@8607 274
kaf24@8607 275 count = 0;
kaf24@8607 276 do {
kaf24@8607 277 gdb_io_write(ctx->out_buf, ctx->out_offset, ctx);
kaf24@8607 278 } while ( !gdb_check_ack(ctx) && (count++ < GDB_RETRY_MAX) );
kaf24@8607 279
kaf24@8607 280 if ( count == GDB_RETRY_MAX )
kaf24@8607 281 dbg_printk("WARNING: %s reached max retry %d\n",
kaf24@8607 282 __func__, GDB_RETRY_MAX);
kaf24@8607 283 }
kaf24@8607 284
kaf24@8607 285 void
kaf24@8607 286 gdb_send_reply(const char *buf, struct gdb_context *ctx)
kaf24@8607 287 {
kaf24@8607 288 gdb_start_packet(ctx);
kaf24@8607 289 gdb_write_to_packet_str(buf, ctx);
kaf24@8607 290 gdb_send_packet(ctx);
kaf24@8607 291 }
kaf24@8607 292
kaf24@8607 293 /* arch neutral command handlers */
kaf24@8607 294
kaf24@8607 295 static void
kaf24@8607 296 gdb_cmd_signum(struct gdb_context *ctx)
kaf24@8607 297 {
kaf24@8607 298 gdb_write_to_packet_char('S', ctx);
kaf24@8607 299 gdb_write_to_packet_hex(ctx->signum, sizeof(ctx->signum), ctx);
kaf24@8607 300 gdb_send_packet(ctx);
kaf24@8607 301 }
kaf24@8607 302
kaf24@8607 303 static void
kaf24@8607 304 gdb_cmd_read_mem(unsigned long addr, unsigned long length,
kaf24@8607 305 struct gdb_context *ctx)
kaf24@8607 306 {
kaf24@8607 307 int x, r;
kaf24@8607 308 unsigned char val;
kaf24@8607 309
kaf24@8607 310 dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
kaf24@8607 311 length);
kaf24@8607 312
kaf24@8607 313 for ( x = 0; x < length; x++ )
kaf24@8607 314 {
kaf24@8607 315 r = gdb_arch_copy_from_user(&val, (void *)(addr + x), 1);
kaf24@8607 316 if ( r != 0 )
kaf24@8607 317 {
kaf24@8607 318 dbg_printk("Error reading from %lx.\n", addr + x);
kaf24@8607 319 break;
kaf24@8607 320 }
kaf24@8607 321 gdb_write_to_packet_hex(val, sizeof(val), ctx);
kaf24@8607 322 }
kaf24@8607 323
kaf24@8607 324 if ( x == 0 )
kaf24@8607 325 gdb_write_to_packet_str("E05", ctx);
kaf24@8607 326
kaf24@8607 327 dbg_printk("Read done.\n");
kaf24@8607 328
kaf24@8607 329 gdb_send_packet(ctx);
kaf24@8607 330 }
kaf24@8607 331
kaf24@8607 332 static void
kaf24@8607 333 gdb_cmd_write_mem(unsigned long addr, unsigned long length,
kaf24@8607 334 const char *buf, struct gdb_context *ctx)
kaf24@8607 335 {
kaf24@8607 336 int x, r;
kaf24@8607 337 unsigned char val;
kaf24@8607 338
kaf24@8607 339 dbg_printk("Memory write starting at %lx, length %lx.\n", addr, length);
kaf24@8607 340
kaf24@8607 341 for ( x = 0; x < length; x++, addr++, buf += 2 )
kaf24@8607 342 {
kaf24@8607 343 val = str2ulong(buf, sizeof(val));
kaf24@8607 344 r = gdb_arch_copy_to_user((void*)addr, (void*)&val, 1);
kaf24@8607 345 if ( r != 0 )
kaf24@8607 346 {
kaf24@8607 347 dbg_printk("Error writing to %lx.\n", addr);
kaf24@8607 348 break;
kaf24@8607 349 }
kaf24@8607 350 }
kaf24@8607 351
kaf24@9179 352 if (x == length)
kaf24@9179 353 gdb_write_to_packet_str("OK", ctx);
kaf24@9179 354 else
kaf24@9179 355 gdb_write_to_packet_str("E11", ctx);
kaf24@8607 356
kaf24@8607 357 dbg_printk("Write done.\n");
kaf24@8607 358
kaf24@8607 359 gdb_send_packet(ctx);
kaf24@8607 360 }
kaf24@8607 361
kfraser@11602 362 static void
kfraser@11602 363 gdbstub_attach(struct gdb_context *ctx)
kfraser@11602 364 {
kfraser@11602 365 if ( ctx->currently_attached )
kfraser@11602 366 return;
kfraser@11602 367 ctx->currently_attached = 1;
kfraser@11602 368 ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts);
kfraser@11602 369 }
kfraser@11602 370
kfraser@11602 371 static void
kfraser@11602 372 gdbstub_detach(struct gdb_context *ctx)
kfraser@11602 373 {
kfraser@11602 374 if ( !ctx->currently_attached )
kfraser@11602 375 return;
kfraser@11602 376 ctx->currently_attached = 0;
kfraser@11602 377 console_giveback(ctx->console_steal_id);
kfraser@11602 378 }
kfraser@11602 379
kaf24@8607 380 /* command dispatcher */
kaf24@8607 381 static int
kaf24@8607 382 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
kaf24@8607 383 {
kaf24@8607 384 char *ptr;
kaf24@8607 385 unsigned long addr, length;
kaf24@8607 386 int resume = 0;
kaf24@8607 387
kaf24@8607 388 /* XXX check ctx->in_bytes >= 2 or similar. */
kaf24@8607 389
kaf24@8607 390 gdb_start_packet(ctx);
kaf24@8607 391 switch ( ctx->in_buf[0] )
kaf24@8607 392 {
kaf24@8607 393 case '?': /* query signal number */
kaf24@8607 394 gdb_cmd_signum(ctx);
kaf24@8607 395 break;
kaf24@8607 396 case 'H': /* thread operations */
kaf24@8607 397 gdb_send_reply("OK", ctx);
kaf24@8607 398 break;
kaf24@8607 399 case 'g': /* Read registers */
kaf24@8607 400 gdb_arch_read_reg_array(regs, ctx);
kaf24@8607 401 break;
kaf24@8607 402 case 'G': /* Write registers */
kaf24@8607 403 gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx);
kaf24@8607 404 break;
kaf24@8607 405 case 'm': /* Read memory */
kaf24@8607 406 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 407 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8607 408 {
kaf24@8607 409 gdb_send_reply("E03", ctx);
kaf24@8607 410 return 0;
kaf24@8607 411 }
kaf24@8607 412 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@8607 413 if ( ptr[0] != 0 )
kaf24@8607 414 {
kaf24@8607 415 gdb_send_reply("E04", ctx);
kaf24@8607 416 return 0;
kaf24@8607 417 }
kaf24@8607 418 gdb_cmd_read_mem(addr, length, ctx);
kaf24@8607 419 break;
kaf24@8607 420 case 'M': /* Write memory */
kaf24@8607 421 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@9179 422 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8607 423 {
kaf24@8607 424 gdb_send_reply("E03", ctx);
kaf24@8607 425 return 0;
kaf24@8607 426 }
kaf24@8607 427 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@9179 428 if ( ptr[0] != ':')
kaf24@9179 429 {
kaf24@9179 430 gdb_send_reply("E04", ctx);
kaf24@9179 431 return 0;
kaf24@9179 432 }
kaf24@9179 433 gdb_cmd_write_mem(addr, length, ptr + 1, ctx);
kaf24@8607 434 break;
kaf24@8607 435 case 'p': /* read register */
kaf24@8607 436 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8607 437 if ( ptr == (ctx->in_buf + 1) )
kaf24@8607 438 {
kaf24@8607 439 gdb_send_reply("E03", ctx);
kaf24@8607 440 return 0;
kaf24@8607 441 }
kaf24@8607 442 if ( ptr[0] != 0 )
kaf24@8607 443 {
kaf24@8607 444 gdb_send_reply("E04", ctx);
kaf24@8607 445 return 0;
kaf24@8607 446 }
kaf24@8607 447 gdb_arch_read_reg(addr, regs, ctx);
kaf24@8607 448 break;
kaf24@8607 449 case 'D':
kfraser@11602 450 gdbstub_detach(ctx);
kaf24@8607 451 gdb_send_reply("OK", ctx);
kaf24@8607 452 /* fall through */
kaf24@8607 453 case 'k':
kaf24@8607 454 ctx->connected = 0;
kaf24@8607 455 /* fall through */
kaf24@8607 456 case 's': /* Single step */
kaf24@8607 457 case 'c': /* Resume at current address */
kaf24@8607 458 {
kaf24@8607 459 unsigned long addr = ~((unsigned long)0);
kaf24@8607 460 unsigned long type = GDB_CONTINUE;
kaf24@8607 461 if ( ctx->in_buf[0] == 's' )
kaf24@8607 462 type = GDB_STEP;
kaf24@8607 463 if ( ((ctx->in_buf[0] == 's') || (ctx->in_buf[0] == 'c')) &&
kaf24@8607 464 ctx->in_buf[1] )
kaf24@8607 465 addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long));
kaf24@8607 466 if ( ctx->in_buf[0] != 'D' )
kfraser@11602 467 gdbstub_attach(ctx);
kaf24@8607 468 resume = 1;
kaf24@8607 469 gdb_arch_resume(regs, addr, type, ctx);
kaf24@8607 470 break;
kaf24@8607 471 }
kaf24@8607 472
kaf24@8607 473 default:
kaf24@8607 474 gdb_send_reply("", ctx);
kaf24@8607 475 break;
kaf24@8607 476 }
kaf24@8607 477 return resume;
kaf24@8607 478 }
kaf24@8607 479
kaf24@8607 480 static struct gdb_context
kaf24@8607 481 __gdb_ctx = {
kfraser@11602 482 .serhnd = -1,
kfraser@11602 483 .running = ATOMIC_INIT(1),
kfraser@11602 484 .signum = 1
kaf24@8607 485 };
kaf24@8607 486 static struct gdb_context *gdb_ctx = &__gdb_ctx;
kaf24@8607 487
kfraser@11602 488 static void
kfraser@11602 489 gdbstub_console_puts(const char *str)
kfraser@11602 490 {
kfraser@11602 491 const char *p;
kfraser@11602 492
kfraser@11602 493 gdb_start_packet(gdb_ctx);
kfraser@11602 494 gdb_write_to_packet_char('O', gdb_ctx);
kfraser@11602 495
kfraser@11602 496 for ( p = str; *p != '\0'; p++ )
kfraser@11602 497 {
kfraser@11602 498 gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx );
kfraser@11602 499 gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx );
kfraser@11602 500 }
kfraser@11602 501
kfraser@11602 502 gdb_send_packet(gdb_ctx);
kfraser@11602 503 }
kfraser@11602 504
kaf24@8607 505 /* trap handler: main entry point */
kaf24@8607 506 int
kaf24@8607 507 __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
kaf24@8607 508 {
kfraser@11649 509 int rc = 0;
kaf24@9117 510 unsigned long flags;
kaf24@8607 511
kaf24@8607 512 if ( gdb_ctx->serhnd < 0 )
kaf24@8607 513 {
kaf24@8607 514 dbg_printk("Debugger not ready yet.\n");
kfraser@11649 515 return -EBUSY;
kaf24@8607 516 }
kaf24@8607 517
kaf24@8607 518 /* We rely on our caller to ensure we're only on one processor
kaf24@8607 519 * at a time... We should probably panic here, but given that
kaf24@8607 520 * we're a debugger we should probably be a little tolerant of
kaf24@8607 521 * things going wrong. */
kaf24@8607 522 /* We don't want to use a spin lock here, because we're doing
kaf24@8607 523 two distinct things:
kaf24@8607 524
kaf24@8607 525 1 -- we don't want to run on more than one processor at a time,
kaf24@8607 526 and
kaf24@8607 527 2 -- we want to do something sensible if we re-enter ourselves.
kaf24@8607 528
kaf24@8607 529 Spin locks are good for 1, but useless for 2. */
kaf24@8607 530 if ( !atomic_dec_and_test(&gdb_ctx->running) )
kaf24@8607 531 {
kaf24@8607 532 printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n");
kaf24@8607 533 atomic_inc(&gdb_ctx->running);
kfraser@11649 534 return -EBUSY;
kaf24@8607 535 }
kaf24@8607 536
kaf24@8607 537 if ( !gdb_ctx->connected )
kaf24@8607 538 {
kaf24@9117 539 printk("GDB connection activated.\n");
kaf24@8607 540 gdb_arch_print_state(regs);
kaf24@8607 541 gdb_ctx->connected = 1;
kaf24@8607 542 }
kaf24@8607 543
kaf24@8607 544 smp_send_stop();
kaf24@8607 545
kaf24@8607 546 /* Try to make things a little more stable by disabling
kaf24@8607 547 interrupts while we're here. */
kaf24@8607 548 local_irq_save(flags);
kaf24@8607 549
kaf24@8607 550 watchdog_disable();
kaf24@8607 551 console_start_sync();
kaf24@8607 552
kaf24@8607 553 /* Shouldn't really do this, but otherwise we stop for no
kaf24@8607 554 obvious reason, which is Bad */
kaf24@9117 555 printk("Waiting for GDB to attach...\n");
kaf24@8607 556
kaf24@8607 557 gdb_arch_enter(regs);
kaf24@8607 558 gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
kfraser@11602 559
kaf24@8607 560 /* If gdb is already attached, tell it we've stopped again. */
kaf24@8607 561 if ( gdb_ctx->currently_attached )
kaf24@8607 562 {
kaf24@8607 563 gdb_start_packet(gdb_ctx);
kaf24@8607 564 gdb_cmd_signum(gdb_ctx);
kaf24@8607 565 }
kaf24@8607 566
kfraser@11649 567 do {
kfraser@11649 568 if ( receive_command(gdb_ctx) < 0 )
kaf24@8607 569 {
kfraser@11649 570 dbg_printk("Error in GDB session...\n");
kfraser@11649 571 rc = -EIO;
kfraser@11649 572 break;
kaf24@8607 573 }
kfraser@11649 574 } while ( process_command(regs, gdb_ctx) == 0 );
kaf24@8607 575
kaf24@8607 576 gdb_arch_exit(regs);
kaf24@8607 577 console_end_sync();
kaf24@8607 578 watchdog_enable();
kaf24@8607 579 atomic_inc(&gdb_ctx->running);
kaf24@8607 580
kaf24@8607 581 local_irq_restore(flags);
kaf24@8607 582
kfraser@11649 583 return rc;
kaf24@8607 584 }
kaf24@8607 585
kaf24@9117 586 void
kaf24@9117 587 initialise_gdb(void)
kaf24@8607 588 {
kaf24@8607 589 gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
kaf24@9117 590 if ( gdb_ctx->serhnd != -1 )
kaf24@9117 591 printk("GDB stub initialised.\n");
kaf24@9437 592 serial_start_sync(gdb_ctx->serhnd);
kaf24@8607 593 }
kaf24@8607 594
kaf24@8607 595 /*
kaf24@8607 596 * Local variables:
kaf24@8607 597 * mode: C
kaf24@8607 598 * c-set-style: "BSD"
kaf24@8607 599 * c-basic-offset: 4
kaf24@8607 600 * tab-width: 4
kaf24@8607 601 * End:
kaf24@8607 602 */