debuggers.hg

annotate xen/common/gdbstub.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents df955a89b53c
children
rev   line source
kaf24@8645 1 /*
kaf24@8645 2 * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
kaf24@8645 3 * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp>
kaf24@8645 4 * VA Linux Systems Japan. K.K.
kaf24@8645 5 *
kaf24@8645 6 * gdbstub arch neutral part
kaf24@8645 7 * Based on x86 cdb (xen/arch/x86/cdb.c) and ppc gdbstub(xen/common/gdbstub.c)
kaf24@8645 8 * But extensively modified.
kaf24@8645 9 *
kaf24@8645 10 * This program is free software; you can redistribute it and/or modify
kaf24@8645 11 * it under the terms of the GNU General Public License as published by
kaf24@8645 12 * the Free Software Foundation; either version 2 of the License, or
kaf24@8645 13 * (at your option) any later version.
kaf24@8645 14 *
kaf24@8645 15 * This program is distributed in the hope that it will be useful,
kaf24@8645 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@8645 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@8645 18 * GNU General Public License for more details.
kaf24@8645 19 *
kaf24@8645 20 * You should have received a copy of the GNU General Public License
kaf24@8645 21 * along with this program; if not, write to the Free Software
kaf24@8645 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@8645 23 */
kaf24@8645 24
kaf24@8645 25 /*
kaf24@8645 26 * gdbstub: implements the architecture independant parts of the
kaf24@8645 27 * gdb remote protocol.
kaf24@8645 28 */
kaf24@8645 29
kaf24@8645 30 /* We try to avoid assuming much about what the rest of the system is
kaf24@8645 31 doing. In particular, dynamic memory allocation is out of the
kaf24@8645 32 question. */
kaf24@8645 33
kaf24@8645 34 /* Resuming after we've stopped used to work, but more through luck
kaf24@8645 35 than any actual intention. It doesn't at the moment. */
kaf24@8645 36
kaf24@8645 37 #include <xen/lib.h>
kaf24@8645 38 #include <xen/spinlock.h>
kaf24@8645 39 #include <xen/serial.h>
kaf24@8645 40 #include <xen/irq.h>
kaf24@8645 41 #include <asm/debugger.h>
kaf24@8645 42 #include <xen/init.h>
kaf24@8645 43 #include <xen/smp.h>
kaf24@8645 44 #include <xen/console.h>
hollisb@13018 45 #include <xen/errno.h>
keir@16705 46 #include <xen/delay.h>
keir@21429 47 #include <xen/init.h>
keir@16634 48 #include <asm/byteorder.h>
kaf24@8645 49
kaf24@8645 50 /* Printk isn't particularly safe just after we've trapped to the
kaf24@8645 51 debugger. so avoid it. */
kaf24@8645 52 #define dbg_printk(...)
kaf24@8645 53 /*#define dbg_printk(...) printk(__VA_ARGS__)*/
kaf24@8645 54
kaf24@8645 55 #define GDB_RETRY_MAX 10
kaf24@8645 56
keir@16705 57 struct gdb_cpu_info
keir@16705 58 {
keir@16705 59 atomic_t paused;
keir@16705 60 atomic_t ack;
keir@16705 61 };
keir@16705 62
keir@16705 63 static struct gdb_cpu_info gdb_cpu[NR_CPUS];
keir@16705 64 static atomic_t gdb_smp_paused_count;
keir@16705 65
keir@16705 66 static void gdb_smp_pause(void);
keir@16705 67 static void gdb_smp_resume(void);
keir@16705 68
keir@20173 69 static char __initdata opt_gdb[30];
kaf24@8645 70 string_param("gdb", opt_gdb);
kaf24@8645 71
kaf24@11655 72 static void gdbstub_console_puts(const char *str);
kaf24@11655 73
kaf24@8645 74 /* value <-> char (de)serialzers */
keir@20093 75 static char
kaf24@8645 76 hex2char(unsigned long x)
kaf24@8645 77 {
kaf24@8645 78 const char array[] = "0123456789abcdef";
kaf24@8645 79 return array[x & 15];
kaf24@8645 80 }
kaf24@8645 81
keir@20093 82 static unsigned int
kaf24@8645 83 char2hex(unsigned char c)
kaf24@8645 84 {
kaf24@8645 85 if ( (c >= '0') && (c <= '9') )
kaf24@8645 86 return c - '0';
kaf24@8645 87 else if ( (c >= 'a') && (c <= 'f') )
kaf24@8645 88 return c - 'a' + 10;
kaf24@8645 89 else if ( (c >= 'A') && (c <= 'F') )
kaf24@8645 90 return c - 'A' + 10;
kaf24@8645 91 else
kaf24@8645 92 BUG();
kaf24@8645 93 return -1;
kaf24@8645 94 }
kaf24@8645 95
keir@20093 96 static unsigned char
kaf24@8645 97 str2hex(const char *str)
kaf24@8645 98 {
kaf24@8645 99 return (char2hex(str[0]) << 4) | char2hex(str[1]);
kaf24@8645 100 }
kaf24@8645 101
keir@20093 102 static unsigned long
kaf24@8645 103 str2ulong(const char *str, unsigned long bytes)
kaf24@8645 104 {
kaf24@8645 105 unsigned long x = 0;
kaf24@8645 106 unsigned long i = 0;
kaf24@8645 107
kaf24@8645 108 while ( *str && (i < (bytes * 2)) )
kaf24@8645 109 {
kaf24@8645 110 x <<= 4;
kaf24@8645 111 x += char2hex(*str);
kaf24@8645 112 ++str;
kaf24@8645 113 ++i;
kaf24@8645 114 }
kaf24@8645 115
kaf24@8645 116 return x;
kaf24@8645 117 }
kaf24@8645 118
keir@20093 119 static unsigned long
keir@20092 120 str_to_native_ulong(const char *str)
keir@20092 121 {
keir@20092 122 unsigned long x = 0, i = 0;
keir@20092 123
keir@20092 124 while ( *str && (i < BYTES_PER_LONG) )
keir@20092 125 {
keir@20092 126 #ifdef __BIG_ENDIAN
keir@20092 127 x <<= 8;
keir@20093 128 x += str2hex(str);
keir@20092 129 #elif defined(__LITTLE_ENDIAN)
keir@20093 130 x += (unsigned long)str2hex(str) << (i*8);
keir@20092 131 #else
keir@20092 132 # error unknown endian
keir@20092 133 #endif
keir@20092 134 str += 2;
keir@20092 135 i++;
keir@20092 136 }
keir@20092 137
keir@20092 138 return x;
keir@20092 139 }
keir@20092 140
kaf24@8645 141 /* gdb io wrappers */
kaf24@8645 142 static signed long
kaf24@8645 143 gdb_io_write(const char *buf, unsigned long len, struct gdb_context *ctx)
kaf24@8645 144 {
kaf24@8645 145 int i;
kaf24@8645 146 for ( i = 0; i < len; i++ )
kaf24@8645 147 serial_putc(ctx->serhnd, buf[i]);
kaf24@8645 148 return i;
kaf24@8645 149 }
kaf24@8645 150
kaf24@8645 151 static int
kaf24@8645 152 gdb_io_write_char(u8 data, struct gdb_context *ctx)
kaf24@8645 153 {
kaf24@8645 154 return gdb_io_write((char*)&data, 1, ctx);
kaf24@8645 155 }
kaf24@8645 156
kaf24@8645 157 static unsigned char
kaf24@8645 158 gdb_io_read(struct gdb_context *ctx)
kaf24@8645 159 {
kaf24@8645 160 return serial_getc(ctx->serhnd);
kaf24@8645 161 }
kaf24@8645 162
kaf24@8645 163 /* Receive a command. Returns -1 on csum error, 0 otherwise. */
kaf24@8645 164 /* Does not acknowledge. */
kaf24@8645 165 static int
kaf24@8645 166 attempt_receive_packet(struct gdb_context *ctx)
kaf24@8645 167 {
kaf24@8645 168 u8 csum;
kaf24@8645 169 u8 received_csum;
kaf24@8645 170 u8 ch;
kaf24@8645 171
kaf24@8645 172 /* Skip over everything up to the first '$' */
kaf24@8645 173 while ( (ch = gdb_io_read(ctx)) != '$' )
kaf24@8645 174 continue;
kaf24@8645 175
kaf24@8645 176 csum = 0;
kaf24@8645 177 for ( ctx->in_bytes = 0;
kaf24@8645 178 ctx->in_bytes < sizeof(ctx->in_buf);
kaf24@8645 179 ctx->in_bytes++ )
kaf24@8645 180 {
kaf24@8645 181 ch = gdb_io_read(ctx);
kaf24@8645 182 if ( ch == '#' )
kaf24@8645 183 break;
kaf24@8645 184 ctx->in_buf[ctx->in_bytes] = ch;
kaf24@8645 185 csum += ch;
kaf24@8645 186 }
kaf24@8645 187
kaf24@8645 188 if ( ctx->in_bytes == sizeof(ctx->in_buf) )
kaf24@8645 189 {
kaf24@8645 190 dbg_printk("WARNING: GDB sent a stupidly big packet.\n");
kaf24@8645 191 return -1;
kaf24@8645 192 }
kaf24@8645 193
kaf24@8645 194 ctx->in_buf[ctx->in_bytes] = '\0';
kaf24@8645 195 received_csum = char2hex(gdb_io_read(ctx)) * 16 +
kaf24@8645 196 char2hex(gdb_io_read(ctx));
kaf24@8645 197
kaf24@8645 198 return (received_csum == csum) ? 0 : -1;
kaf24@8645 199 }
kaf24@8645 200
kaf24@8645 201 /* Receive a command, discarding up to ten packets with csum
kaf24@8645 202 * errors. Acknowledges all received packets. */
kaf24@8645 203 static int
kaf24@8645 204 receive_command(struct gdb_context *ctx)
kaf24@8645 205 {
kaf24@8645 206 int r, count = 0;
kaf24@8645 207
kaf24@8645 208 count = 0;
kaf24@8645 209 do {
kaf24@8645 210 r = attempt_receive_packet(ctx);
kaf24@8645 211 gdb_io_write_char((r < 0) ? '-' : '+', ctx);
kaf24@8645 212 count++;
kaf24@8645 213 } while ( (r < 0) && (count < GDB_RETRY_MAX) );
kaf24@8645 214
kaf24@8645 215 return r;
kaf24@8645 216 }
kaf24@8645 217
kaf24@8645 218 /* routines to send reply packets */
kaf24@8645 219
kaf24@8645 220 static void
kaf24@8645 221 gdb_start_packet(struct gdb_context *ctx)
kaf24@8645 222 {
kaf24@8645 223 ctx->out_buf[0] = '$';
kaf24@8645 224 ctx->out_offset = 1;
kaf24@8645 225 ctx->out_csum = 0;
kaf24@8645 226 }
kaf24@8645 227
kaf24@8645 228 static void
kaf24@8645 229 gdb_write_to_packet_char(u8 data, struct gdb_context *ctx)
kaf24@8645 230 {
kaf24@8645 231 ctx->out_csum += data;
kaf24@8645 232 ctx->out_buf[ctx->out_offset] = data;
kaf24@8645 233 ctx->out_offset++;
kaf24@8645 234 }
kaf24@8645 235
kaf24@8645 236 void
kaf24@8645 237 gdb_write_to_packet(const char *buf, int count, struct gdb_context *ctx)
kaf24@8645 238 {
kaf24@8645 239 int x;
kaf24@8645 240 for ( x = 0; x < count; x++ )
kaf24@8645 241 gdb_write_to_packet_char(buf[x], ctx);
kaf24@8645 242 }
kaf24@8645 243
kaf24@8645 244 void
kaf24@8645 245 gdb_write_to_packet_str(const char *buf, struct gdb_context *ctx)
kaf24@8645 246 {
kaf24@8645 247 gdb_write_to_packet(buf, strlen(buf), ctx);
kaf24@8645 248 }
kaf24@8645 249
kaf24@8645 250 void
kaf24@8645 251 gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
kaf24@8645 252 {
kaf24@8645 253 char buf[sizeof(unsigned long) * 2 + 1];
keir@16634 254 int i, width = int_size * 2;
kaf24@8645 255
kaf24@8645 256 buf[sizeof(unsigned long) * 2] = 0;
kaf24@8645 257
kaf24@8645 258 switch ( int_size )
kaf24@8645 259 {
kaf24@8645 260 case sizeof(u8):
kaf24@8645 261 case sizeof(u16):
kaf24@8645 262 case sizeof(u32):
kaf24@8645 263 case sizeof(u64):
kaf24@8645 264 break;
kaf24@8645 265 default:
kaf24@8645 266 dbg_printk("WARNING: %s x: 0x%lx int_size: %d\n",
kaf24@8645 267 __func__, x, int_size);
kaf24@8645 268 break;
kaf24@8645 269 }
kaf24@8645 270
keir@16634 271 #ifdef __BIG_ENDIAN
keir@16705 272 i = sizeof(unsigned long) * 2
kaf24@8645 273 do {
kaf24@8645 274 buf[--i] = hex2char(x & 15);
kaf24@8645 275 x >>= 4;
kaf24@8645 276 } while ( x );
kaf24@8645 277
kaf24@8645 278 while ( (i + width) > (sizeof(unsigned long) * 2) )
kaf24@8645 279 buf[--i] = '0';
kaf24@8645 280
kaf24@8645 281 gdb_write_to_packet(&buf[i], width, ctx);
keir@16634 282 #elif defined(__LITTLE_ENDIAN)
keir@16705 283 i = 0;
keir@16705 284 while ( i < width )
keir@16705 285 {
keir@16705 286 buf[i++] = hex2char(x>>4);
keir@16705 287 buf[i++] = hex2char(x);
keir@16705 288 x >>= 8;
keir@16705 289 }
keir@16705 290 gdb_write_to_packet(buf, width, ctx);
keir@16634 291 #else
keir@16634 292 # error unknown endian
keir@16634 293 #endif
kaf24@8645 294 }
kaf24@8645 295
kaf24@8645 296 static int
kaf24@8645 297 gdb_check_ack(struct gdb_context *ctx)
kaf24@8645 298 {
kaf24@8645 299 u8 c = gdb_io_read(ctx);
kaf24@8645 300
kaf24@8645 301 switch ( c )
kaf24@8645 302 {
kaf24@8645 303 case '+':
kaf24@8645 304 return 1;
kaf24@8645 305 case '-':
kaf24@8645 306 return 0;
kaf24@8645 307 default:
kaf24@8645 308 printk("Bad ack: %c\n", c);
kaf24@8645 309 return 0;
kaf24@8645 310 }
kaf24@8645 311 }
kaf24@8645 312
kaf24@8645 313 /* Return 0 if the reply was successfully received, !0 otherwise. */
kaf24@8645 314 void
kaf24@8645 315 gdb_send_packet(struct gdb_context *ctx)
kaf24@8645 316 {
kaf24@8645 317 char buf[3];
kaf24@8645 318 int count;
kaf24@8645 319
kfraser@13697 320 snprintf(buf, sizeof(buf), "%.02x\n", ctx->out_csum);
kaf24@8645 321
kaf24@8645 322 gdb_write_to_packet_char('#', ctx);
kaf24@8645 323 gdb_write_to_packet(buf, 2, ctx);
kaf24@8645 324
kaf24@8645 325 count = 0;
kaf24@8645 326 do {
kaf24@8645 327 gdb_io_write(ctx->out_buf, ctx->out_offset, ctx);
kaf24@8645 328 } while ( !gdb_check_ack(ctx) && (count++ < GDB_RETRY_MAX) );
kaf24@8645 329
kaf24@8645 330 if ( count == GDB_RETRY_MAX )
kaf24@8645 331 dbg_printk("WARNING: %s reached max retry %d\n",
kaf24@8645 332 __func__, GDB_RETRY_MAX);
kaf24@8645 333 }
kaf24@8645 334
kaf24@8645 335 void
kaf24@8645 336 gdb_send_reply(const char *buf, struct gdb_context *ctx)
kaf24@8645 337 {
kaf24@8645 338 gdb_start_packet(ctx);
kaf24@8645 339 gdb_write_to_packet_str(buf, ctx);
kaf24@8645 340 gdb_send_packet(ctx);
kaf24@8645 341 }
kaf24@8645 342
kaf24@8645 343 /* arch neutral command handlers */
kaf24@8645 344
kaf24@8645 345 static void
kaf24@8645 346 gdb_cmd_signum(struct gdb_context *ctx)
kaf24@8645 347 {
kaf24@8645 348 gdb_write_to_packet_char('S', ctx);
kaf24@8645 349 gdb_write_to_packet_hex(ctx->signum, sizeof(ctx->signum), ctx);
kaf24@8645 350 gdb_send_packet(ctx);
kaf24@8645 351 }
kaf24@8645 352
kaf24@8645 353 static void
kaf24@8645 354 gdb_cmd_read_mem(unsigned long addr, unsigned long length,
kaf24@8645 355 struct gdb_context *ctx)
kaf24@8645 356 {
kaf24@8645 357 int x, r;
kaf24@8645 358 unsigned char val;
kaf24@8645 359
kaf24@8645 360 dbg_printk("Memory read starting at %lx, length %lx.\n", addr,
kaf24@8645 361 length);
kaf24@8645 362
kaf24@8645 363 for ( x = 0; x < length; x++ )
kaf24@8645 364 {
kaf24@8645 365 r = gdb_arch_copy_from_user(&val, (void *)(addr + x), 1);
kaf24@8645 366 if ( r != 0 )
kaf24@8645 367 {
kaf24@8645 368 dbg_printk("Error reading from %lx.\n", addr + x);
kaf24@8645 369 break;
kaf24@8645 370 }
kaf24@8645 371 gdb_write_to_packet_hex(val, sizeof(val), ctx);
kaf24@8645 372 }
kaf24@8645 373
kaf24@8645 374 if ( x == 0 )
kaf24@8645 375 gdb_write_to_packet_str("E05", ctx);
kaf24@8645 376
kaf24@8645 377 dbg_printk("Read done.\n");
kaf24@8645 378
kaf24@8645 379 gdb_send_packet(ctx);
kaf24@8645 380 }
kaf24@8645 381
kaf24@8645 382 static void
kaf24@8645 383 gdb_cmd_write_mem(unsigned long addr, unsigned long length,
kaf24@8645 384 const char *buf, struct gdb_context *ctx)
kaf24@8645 385 {
kaf24@8645 386 int x, r;
kaf24@8645 387 unsigned char val;
kaf24@8645 388
kaf24@8645 389 dbg_printk("Memory write starting at %lx, length %lx.\n", addr, length);
kaf24@8645 390
kaf24@8645 391 for ( x = 0; x < length; x++, addr++, buf += 2 )
kaf24@8645 392 {
kaf24@8645 393 val = str2ulong(buf, sizeof(val));
kaf24@8645 394 r = gdb_arch_copy_to_user((void*)addr, (void*)&val, 1);
kaf24@8645 395 if ( r != 0 )
kaf24@8645 396 {
kaf24@8645 397 dbg_printk("Error writing to %lx.\n", addr);
kaf24@8645 398 break;
kaf24@8645 399 }
kaf24@8645 400 }
kaf24@8645 401
kaf24@9193 402 if (x == length)
kaf24@9193 403 gdb_write_to_packet_str("OK", ctx);
kaf24@9193 404 else
kaf24@9193 405 gdb_write_to_packet_str("E11", ctx);
kaf24@8645 406
kaf24@8645 407 dbg_printk("Write done.\n");
kaf24@8645 408
kaf24@8645 409 gdb_send_packet(ctx);
kaf24@8645 410 }
kaf24@8645 411
kfraser@11636 412 static void
kfraser@11636 413 gdbstub_attach(struct gdb_context *ctx)
kfraser@11636 414 {
kfraser@11636 415 if ( ctx->currently_attached )
kfraser@11636 416 return;
kfraser@11636 417 ctx->currently_attached = 1;
kfraser@11636 418 ctx->console_steal_id = console_steal(ctx->serhnd, gdbstub_console_puts);
kfraser@11636 419 }
kfraser@11636 420
kfraser@11636 421 static void
kfraser@11636 422 gdbstub_detach(struct gdb_context *ctx)
kfraser@11636 423 {
kfraser@11636 424 if ( !ctx->currently_attached )
kfraser@11636 425 return;
kfraser@11636 426 ctx->currently_attached = 0;
kfraser@11636 427 console_giveback(ctx->console_steal_id);
kfraser@11636 428 }
kfraser@11636 429
kaf24@8645 430 /* command dispatcher */
kaf24@8645 431 static int
kaf24@8645 432 process_command(struct cpu_user_regs *regs, struct gdb_context *ctx)
kaf24@8645 433 {
kaf24@13174 434 const char *ptr;
keir@16705 435 unsigned long addr, length, val;
kaf24@8645 436 int resume = 0;
keir@16705 437 unsigned long type = GDB_CONTINUE;
kaf24@8645 438
kaf24@8645 439 /* XXX check ctx->in_bytes >= 2 or similar. */
kaf24@8645 440
kaf24@8645 441 gdb_start_packet(ctx);
kaf24@8645 442 switch ( ctx->in_buf[0] )
kaf24@8645 443 {
kaf24@8645 444 case '?': /* query signal number */
kaf24@8645 445 gdb_cmd_signum(ctx);
kaf24@8645 446 break;
kaf24@8645 447 case 'H': /* thread operations */
kaf24@8645 448 gdb_send_reply("OK", ctx);
kaf24@8645 449 break;
kaf24@8645 450 case 'g': /* Read registers */
kaf24@8645 451 gdb_arch_read_reg_array(regs, ctx);
kaf24@8645 452 break;
kaf24@8645 453 case 'G': /* Write registers */
kaf24@8645 454 gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx);
kaf24@8645 455 break;
kaf24@8645 456 case 'm': /* Read memory */
kaf24@8645 457 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8645 458 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8645 459 {
kaf24@8645 460 gdb_send_reply("E03", ctx);
kaf24@8645 461 return 0;
kaf24@8645 462 }
kaf24@8645 463 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@8645 464 if ( ptr[0] != 0 )
kaf24@8645 465 {
kaf24@8645 466 gdb_send_reply("E04", ctx);
kaf24@8645 467 return 0;
kaf24@8645 468 }
kaf24@8645 469 gdb_cmd_read_mem(addr, length, ctx);
kaf24@8645 470 break;
kaf24@8645 471 case 'M': /* Write memory */
kaf24@8645 472 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@9193 473 if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') )
kaf24@8645 474 {
kaf24@8645 475 gdb_send_reply("E03", ctx);
kaf24@8645 476 return 0;
kaf24@8645 477 }
kaf24@8645 478 length = simple_strtoul(ptr + 1, &ptr, 16);
kaf24@9193 479 if ( ptr[0] != ':')
kaf24@9193 480 {
kaf24@9193 481 gdb_send_reply("E04", ctx);
kaf24@9193 482 return 0;
kaf24@9193 483 }
kaf24@9193 484 gdb_cmd_write_mem(addr, length, ptr + 1, ctx);
kaf24@8645 485 break;
kaf24@8645 486 case 'p': /* read register */
kaf24@8645 487 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
kaf24@8645 488 if ( ptr == (ctx->in_buf + 1) )
kaf24@8645 489 {
kaf24@8645 490 gdb_send_reply("E03", ctx);
kaf24@8645 491 return 0;
kaf24@8645 492 }
kaf24@8645 493 if ( ptr[0] != 0 )
kaf24@8645 494 {
kaf24@8645 495 gdb_send_reply("E04", ctx);
kaf24@8645 496 return 0;
kaf24@8645 497 }
kaf24@8645 498 gdb_arch_read_reg(addr, regs, ctx);
kaf24@8645 499 break;
keir@16705 500 case 'P': /* write register */
keir@16705 501 addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16);
keir@16705 502 if ( ptr == (ctx->in_buf + 1) )
keir@16705 503 {
keir@16705 504 gdb_send_reply("E03", ctx);
keir@16705 505 return 0;
keir@16705 506 }
keir@16705 507 if ( ptr[0] != '=' )
keir@16705 508 {
keir@16705 509 gdb_send_reply("E04", ctx);
keir@16705 510 return 0;
keir@16705 511 }
keir@16705 512 ptr++;
keir@20092 513 val = str_to_native_ulong(ptr);
keir@16705 514 gdb_arch_write_reg(addr, val, regs, ctx);
keir@16705 515 break;
kaf24@8645 516 case 'D':
keir@16705 517 case 'k':
kfraser@11636 518 gdbstub_detach(ctx);
kaf24@8645 519 gdb_send_reply("OK", ctx);
kaf24@8645 520 ctx->connected = 0;
keir@16705 521 resume = 1;
keir@16705 522 break;
kaf24@8645 523 case 's': /* Single step */
keir@16705 524 type = GDB_STEP;
kaf24@8645 525 case 'c': /* Resume at current address */
keir@16705 526 addr = ~((unsigned long)0);
keir@16705 527
keir@16705 528 if ( ctx->in_buf[1] )
kaf24@8645 529 addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long));
keir@16705 530 gdbstub_attach(ctx);
kaf24@8645 531 resume = 1;
kaf24@8645 532 gdb_arch_resume(regs, addr, type, ctx);
kaf24@8645 533 break;
kaf24@8645 534 default:
kaf24@8645 535 gdb_send_reply("", ctx);
kaf24@8645 536 break;
kaf24@8645 537 }
kaf24@8645 538 return resume;
kaf24@8645 539 }
kaf24@8645 540
kaf24@8645 541 static struct gdb_context
kaf24@8645 542 __gdb_ctx = {
kfraser@11636 543 .serhnd = -1,
kfraser@11636 544 .running = ATOMIC_INIT(1),
kfraser@11636 545 .signum = 1
kaf24@8645 546 };
kaf24@8645 547 static struct gdb_context *gdb_ctx = &__gdb_ctx;
kaf24@8645 548
kfraser@11636 549 static void
kfraser@11636 550 gdbstub_console_puts(const char *str)
kfraser@11636 551 {
kfraser@11636 552 const char *p;
kfraser@11636 553
kfraser@11636 554 gdb_start_packet(gdb_ctx);
kfraser@11636 555 gdb_write_to_packet_char('O', gdb_ctx);
kfraser@11636 556
kfraser@11636 557 for ( p = str; *p != '\0'; p++ )
kfraser@11636 558 {
kfraser@11636 559 gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx );
kfraser@11636 560 gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx );
kfraser@11636 561 }
kfraser@11636 562
kfraser@11636 563 gdb_send_packet(gdb_ctx);
kfraser@11636 564 }
kfraser@11636 565
kaf24@8645 566 /* trap handler: main entry point */
kaf24@8645 567 int
kaf24@8645 568 __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
kaf24@8645 569 {
kfraser@11670 570 int rc = 0;
kaf24@9150 571 unsigned long flags;
kaf24@8645 572
kaf24@8645 573 if ( gdb_ctx->serhnd < 0 )
kaf24@8645 574 {
keir@16634 575 printk("Debugging connection not set up.\n");
kfraser@11670 576 return -EBUSY;
kaf24@8645 577 }
kaf24@8645 578
kaf24@8645 579 /* We rely on our caller to ensure we're only on one processor
kaf24@8645 580 * at a time... We should probably panic here, but given that
kaf24@8645 581 * we're a debugger we should probably be a little tolerant of
kaf24@8645 582 * things going wrong. */
kaf24@8645 583 /* We don't want to use a spin lock here, because we're doing
kaf24@8645 584 two distinct things:
kaf24@8645 585
kaf24@8645 586 1 -- we don't want to run on more than one processor at a time,
kaf24@8645 587 and
kaf24@8645 588 2 -- we want to do something sensible if we re-enter ourselves.
kaf24@8645 589
kaf24@8645 590 Spin locks are good for 1, but useless for 2. */
kaf24@8645 591 if ( !atomic_dec_and_test(&gdb_ctx->running) )
kaf24@8645 592 {
kaf24@8645 593 printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n");
kaf24@8645 594 atomic_inc(&gdb_ctx->running);
kfraser@11670 595 return -EBUSY;
kaf24@8645 596 }
kaf24@8645 597
kaf24@8645 598 if ( !gdb_ctx->connected )
kaf24@8645 599 {
kaf24@9150 600 printk("GDB connection activated.\n");
kaf24@8645 601 gdb_arch_print_state(regs);
kaf24@8645 602 gdb_ctx->connected = 1;
kaf24@8645 603 }
kaf24@8645 604
keir@16705 605 gdb_smp_pause();
kaf24@8645 606
kaf24@8645 607 local_irq_save(flags);
kaf24@8645 608
kaf24@8645 609 watchdog_disable();
kaf24@8645 610 console_start_sync();
kaf24@8645 611
kaf24@8645 612 gdb_arch_enter(regs);
kaf24@8645 613 gdb_ctx->signum = gdb_arch_signal_num(regs, cookie);
kfraser@11636 614
kaf24@8645 615 /* If gdb is already attached, tell it we've stopped again. */
kaf24@8645 616 if ( gdb_ctx->currently_attached )
kaf24@8645 617 {
kaf24@8645 618 gdb_start_packet(gdb_ctx);
kaf24@8645 619 gdb_cmd_signum(gdb_ctx);
kaf24@8645 620 }
kaf24@8645 621
kfraser@11670 622 do {
kfraser@11670 623 if ( receive_command(gdb_ctx) < 0 )
kaf24@8645 624 {
kfraser@11670 625 dbg_printk("Error in GDB session...\n");
kfraser@11670 626 rc = -EIO;
kfraser@11670 627 break;
kaf24@8645 628 }
kfraser@11670 629 } while ( process_command(regs, gdb_ctx) == 0 );
kaf24@8645 630
keir@16705 631 gdb_smp_resume();
keir@16705 632
kaf24@8645 633 gdb_arch_exit(regs);
kaf24@8645 634 console_end_sync();
kaf24@8645 635 watchdog_enable();
kaf24@8645 636 atomic_inc(&gdb_ctx->running);
kaf24@8645 637
kaf24@8645 638 local_irq_restore(flags);
kaf24@8645 639
kfraser@11670 640 return rc;
kaf24@8645 641 }
kaf24@8645 642
keir@21429 643 static int __init initialise_gdb(void)
kaf24@8645 644 {
keir@18511 645 if ( *opt_gdb == '\0' )
keir@21429 646 return 0;
keir@18511 647
kaf24@8645 648 gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
keir@18511 649 if ( gdb_ctx->serhnd == -1 )
keir@18511 650 {
keir@18511 651 printk("Bad gdb= option '%s'\n", opt_gdb);
keir@21429 652 return 0;
keir@18511 653 }
keir@18511 654
kaf24@9457 655 serial_start_sync(gdb_ctx->serhnd);
keir@18511 656
keir@18511 657 printk("GDB stub initialised.\n");
keir@21429 658
keir@21429 659 return 0;
kaf24@8645 660 }
keir@21429 661 presmp_initcall(initialise_gdb);
kaf24@8645 662
keir@16705 663 static void gdb_pause_this_cpu(void *unused)
keir@16705 664 {
keir@16705 665 unsigned long flags;
keir@16705 666
keir@16705 667 local_irq_save(flags);
keir@16705 668
keir@16705 669 atomic_set(&gdb_cpu[smp_processor_id()].ack, 1);
keir@16705 670 atomic_inc(&gdb_smp_paused_count);
keir@16705 671
keir@16705 672 while ( atomic_read(&gdb_cpu[smp_processor_id()].paused) )
keir@16705 673 mdelay(1);
keir@16705 674
keir@16705 675 atomic_dec(&gdb_smp_paused_count);
keir@16705 676 atomic_set(&gdb_cpu[smp_processor_id()].ack, 0);
keir@16705 677
keir@16705 678 /* Restore interrupts */
keir@16705 679 local_irq_restore(flags);
keir@16705 680 }
keir@16705 681
keir@16705 682 static void gdb_smp_pause(void)
keir@16705 683 {
keir@16705 684 int timeout = 100;
keir@16705 685 int cpu;
keir@16705 686
keir@16705 687 for_each_online_cpu(cpu)
keir@16705 688 {
keir@16705 689 atomic_set(&gdb_cpu[cpu].ack, 0);
keir@16705 690 atomic_set(&gdb_cpu[cpu].paused, 1);
keir@16705 691 }
keir@16705 692
keir@16705 693 atomic_set(&gdb_smp_paused_count, 0);
keir@16705 694
keir@19690 695 smp_call_function(gdb_pause_this_cpu, NULL, /* dont wait! */0);
keir@16705 696
keir@16705 697 /* Wait 100ms for all other CPUs to enter pause loop */
keir@16705 698 while ( (atomic_read(&gdb_smp_paused_count) < (num_online_cpus() - 1))
keir@16705 699 && (timeout-- > 0) )
keir@16705 700 mdelay(1);
keir@16705 701
keir@16705 702 if ( atomic_read(&gdb_smp_paused_count) < (num_online_cpus() - 1) )
keir@16705 703 {
keir@16705 704 printk("GDB: Not all CPUs have paused, missing CPUs ");
keir@16705 705 for_each_online_cpu(cpu)
keir@16705 706 {
keir@16705 707 if ( (cpu != smp_processor_id()) &&
keir@16705 708 !atomic_read(&gdb_cpu[cpu].ack) )
keir@16705 709 printk("%d ", cpu);
keir@16705 710 }
keir@16705 711 printk("\n");
keir@16705 712 }
keir@16705 713 }
keir@16705 714
keir@16705 715 static void gdb_smp_resume(void)
keir@16705 716 {
keir@16705 717 int cpu;
keir@16705 718 int timeout = 100;
keir@16705 719
keir@16705 720 for_each_online_cpu(cpu)
keir@16705 721 atomic_set(&gdb_cpu[cpu].paused, 0);
keir@16705 722
keir@16705 723 /* Make sure all CPUs resume */
keir@16705 724 while ( (atomic_read(&gdb_smp_paused_count) > 0)
keir@16705 725 && (timeout-- > 0) )
keir@16705 726 mdelay(1);
keir@16705 727
keir@16705 728 if ( atomic_read(&gdb_smp_paused_count) > 0 )
keir@16705 729 {
keir@16705 730 printk("GDB: Not all CPUs have resumed execution, missing CPUs ");
keir@16705 731 for_each_online_cpu(cpu)
keir@16705 732 {
keir@16705 733 if ( (cpu != smp_processor_id()) &&
keir@16705 734 atomic_read(&gdb_cpu[cpu].ack) )
keir@16705 735 printk("%d ", cpu);
keir@16705 736 }
keir@16705 737 printk("\n");
keir@16705 738 }
keir@16705 739 }
keir@16705 740
kaf24@8645 741 /*
kaf24@8645 742 * Local variables:
kaf24@8645 743 * mode: C
kaf24@8645 744 * c-set-style: "BSD"
kaf24@8645 745 * c-basic-offset: 4
kaf24@8645 746 * tab-width: 4
kaf24@8645 747 * End:
kaf24@8645 748 */