diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-05 18:59:48 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-05 18:59:48 -0400 |
| commit | 89a6c8cb9e6e11b6e3671dce7e037789b8f7cf62 (patch) | |
| tree | 12b16a8abe303fd86c156ddfbb86caa469e45a98 /kernel/debug | |
| parent | 03c0c29aff7e56b722eb6c47eace222b140d0377 (diff) | |
| parent | 3fa43aba08c5b5a4b407e402606fbe463239b14a (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb:
debug_core,kdb: fix crash when arch does not have single step
kgdb,x86: use macro HBP_NUM to replace magic number 4
kgdb,mips: remove unused kgdb_cpu_doing_single_step operations
mm,kdb,kgdb: Add a debug reference for the kdb kmap usage
KGDB: Remove set but unused newPC
ftrace,kdb: Allow dumping a specific cpu's buffer with ftdump
ftrace,kdb: Extend kdb to be able to dump the ftrace buffer
kgdb,powerpc: Replace hardcoded offset by BREAK_INSTR_SIZE
arm,kgdb: Add ability to trap into debugger on notify_die
gdbstub: do not directly use dbg_reg_def[] in gdb_cmd_reg_set()
gdbstub: Implement gdbserial 'p' and 'P' packets
kgdb,arm: Individual register get/set for arm
kgdb,mips: Individual register get/set for mips
kgdb,x86: Individual register get/set for x86
kgdb,kdb: individual register set and and get API
gdbstub: Optimize kgdb's "thread:" response for the gdb serial protocol
kgdb: remove custom hex_to_bin()implementation
Diffstat (limited to 'kernel/debug')
| -rw-r--r-- | kernel/debug/debug_core.c | 2 | ||||
| -rw-r--r-- | kernel/debug/gdbstub.c | 189 | ||||
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 132 |
3 files changed, 257 insertions, 66 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 51d14fe87648..3c2d4972d235 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
| @@ -605,6 +605,8 @@ cpu_master_loop: | |||
| 605 | if (dbg_kdb_mode) { | 605 | if (dbg_kdb_mode) { |
| 606 | kgdb_connected = 1; | 606 | kgdb_connected = 1; |
| 607 | error = kdb_stub(ks); | 607 | error = kdb_stub(ks); |
| 608 | if (error == -1) | ||
| 609 | continue; | ||
| 608 | kgdb_connected = 0; | 610 | kgdb_connected = 0; |
| 609 | } else { | 611 | } else { |
| 610 | error = gdb_serial_stub(ks); | 612 | error = gdb_serial_stub(ks); |
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 6e81fd59566b..481a7bd2dfe7 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c | |||
| @@ -52,17 +52,6 @@ static unsigned long gdb_regs[(NUMREGBYTES + | |||
| 52 | * GDB remote protocol parser: | 52 | * GDB remote protocol parser: |
| 53 | */ | 53 | */ |
| 54 | 54 | ||
| 55 | static int hex(char ch) | ||
| 56 | { | ||
| 57 | if ((ch >= 'a') && (ch <= 'f')) | ||
| 58 | return ch - 'a' + 10; | ||
| 59 | if ((ch >= '0') && (ch <= '9')) | ||
| 60 | return ch - '0'; | ||
| 61 | if ((ch >= 'A') && (ch <= 'F')) | ||
| 62 | return ch - 'A' + 10; | ||
| 63 | return -1; | ||
| 64 | } | ||
| 65 | |||
| 66 | #ifdef CONFIG_KGDB_KDB | 55 | #ifdef CONFIG_KGDB_KDB |
| 67 | static int gdbstub_read_wait(void) | 56 | static int gdbstub_read_wait(void) |
| 68 | { | 57 | { |
| @@ -123,8 +112,8 @@ static void get_packet(char *buffer) | |||
| 123 | buffer[count] = 0; | 112 | buffer[count] = 0; |
| 124 | 113 | ||
| 125 | if (ch == '#') { | 114 | if (ch == '#') { |
| 126 | xmitcsum = hex(gdbstub_read_wait()) << 4; | 115 | xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4; |
| 127 | xmitcsum += hex(gdbstub_read_wait()); | 116 | xmitcsum += hex_to_bin(gdbstub_read_wait()); |
| 128 | 117 | ||
| 129 | if (checksum != xmitcsum) | 118 | if (checksum != xmitcsum) |
| 130 | /* failed checksum */ | 119 | /* failed checksum */ |
| @@ -236,7 +225,7 @@ void gdbstub_msg_write(const char *s, int len) | |||
| 236 | * buf. Return a pointer to the last char put in buf (null). May | 225 | * buf. Return a pointer to the last char put in buf (null). May |
| 237 | * return an error. | 226 | * return an error. |
| 238 | */ | 227 | */ |
| 239 | int kgdb_mem2hex(char *mem, char *buf, int count) | 228 | char *kgdb_mem2hex(char *mem, char *buf, int count) |
| 240 | { | 229 | { |
| 241 | char *tmp; | 230 | char *tmp; |
| 242 | int err; | 231 | int err; |
| @@ -248,17 +237,16 @@ int kgdb_mem2hex(char *mem, char *buf, int count) | |||
| 248 | tmp = buf + count; | 237 | tmp = buf + count; |
| 249 | 238 | ||
| 250 | err = probe_kernel_read(tmp, mem, count); | 239 | err = probe_kernel_read(tmp, mem, count); |
| 251 | if (!err) { | 240 | if (err) |
| 252 | while (count > 0) { | 241 | return NULL; |
| 253 | buf = pack_hex_byte(buf, *tmp); | 242 | while (count > 0) { |
| 254 | tmp++; | 243 | buf = pack_hex_byte(buf, *tmp); |
| 255 | count--; | 244 | tmp++; |
| 256 | } | 245 | count--; |
| 257 | |||
| 258 | *buf = 0; | ||
| 259 | } | 246 | } |
| 247 | *buf = 0; | ||
| 260 | 248 | ||
| 261 | return err; | 249 | return buf; |
| 262 | } | 250 | } |
| 263 | 251 | ||
| 264 | /* | 252 | /* |
| @@ -280,8 +268,8 @@ int kgdb_hex2mem(char *buf, char *mem, int count) | |||
| 280 | tmp_hex = tmp_raw - 1; | 268 | tmp_hex = tmp_raw - 1; |
| 281 | while (tmp_hex >= buf) { | 269 | while (tmp_hex >= buf) { |
| 282 | tmp_raw--; | 270 | tmp_raw--; |
| 283 | *tmp_raw = hex(*tmp_hex--); | 271 | *tmp_raw = hex_to_bin(*tmp_hex--); |
| 284 | *tmp_raw |= hex(*tmp_hex--) << 4; | 272 | *tmp_raw |= hex_to_bin(*tmp_hex--) << 4; |
| 285 | } | 273 | } |
| 286 | 274 | ||
| 287 | return probe_kernel_write(mem, tmp_raw, count); | 275 | return probe_kernel_write(mem, tmp_raw, count); |
| @@ -304,7 +292,7 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val) | |||
| 304 | (*ptr)++; | 292 | (*ptr)++; |
| 305 | } | 293 | } |
| 306 | while (**ptr) { | 294 | while (**ptr) { |
| 307 | hex_val = hex(**ptr); | 295 | hex_val = hex_to_bin(**ptr); |
| 308 | if (hex_val < 0) | 296 | if (hex_val < 0) |
| 309 | break; | 297 | break; |
| 310 | 298 | ||
| @@ -339,6 +327,32 @@ static int kgdb_ebin2mem(char *buf, char *mem, int count) | |||
| 339 | return probe_kernel_write(mem, c, size); | 327 | return probe_kernel_write(mem, c, size); |
| 340 | } | 328 | } |
| 341 | 329 | ||
| 330 | #if DBG_MAX_REG_NUM > 0 | ||
| 331 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
| 332 | { | ||
| 333 | int i; | ||
| 334 | int idx = 0; | ||
| 335 | char *ptr = (char *)gdb_regs; | ||
| 336 | |||
| 337 | for (i = 0; i < DBG_MAX_REG_NUM; i++) { | ||
| 338 | dbg_get_reg(i, ptr + idx, regs); | ||
| 339 | idx += dbg_reg_def[i].size; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
| 344 | { | ||
| 345 | int i; | ||
| 346 | int idx = 0; | ||
| 347 | char *ptr = (char *)gdb_regs; | ||
| 348 | |||
| 349 | for (i = 0; i < DBG_MAX_REG_NUM; i++) { | ||
| 350 | dbg_set_reg(i, ptr + idx, regs); | ||
| 351 | idx += dbg_reg_def[i].size; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | #endif /* DBG_MAX_REG_NUM > 0 */ | ||
| 355 | |||
| 342 | /* Write memory due to an 'M' or 'X' packet. */ | 356 | /* Write memory due to an 'M' or 'X' packet. */ |
| 343 | static int write_mem_msg(int binary) | 357 | static int write_mem_msg(int binary) |
| 344 | { | 358 | { |
| @@ -378,28 +392,31 @@ static void error_packet(char *pkt, int error) | |||
| 378 | * remapped to negative TIDs. | 392 | * remapped to negative TIDs. |
| 379 | */ | 393 | */ |
| 380 | 394 | ||
| 381 | #define BUF_THREAD_ID_SIZE 16 | 395 | #define BUF_THREAD_ID_SIZE 8 |
| 382 | 396 | ||
| 383 | static char *pack_threadid(char *pkt, unsigned char *id) | 397 | static char *pack_threadid(char *pkt, unsigned char *id) |
| 384 | { | 398 | { |
| 385 | char *limit; | 399 | unsigned char *limit; |
| 400 | int lzero = 1; | ||
| 401 | |||
| 402 | limit = id + (BUF_THREAD_ID_SIZE / 2); | ||
| 403 | while (id < limit) { | ||
| 404 | if (!lzero || *id != 0) { | ||
| 405 | pkt = pack_hex_byte(pkt, *id); | ||
| 406 | lzero = 0; | ||
| 407 | } | ||
| 408 | id++; | ||
| 409 | } | ||
| 386 | 410 | ||
| 387 | limit = pkt + BUF_THREAD_ID_SIZE; | 411 | if (lzero) |
| 388 | while (pkt < limit) | 412 | pkt = pack_hex_byte(pkt, 0); |
| 389 | pkt = pack_hex_byte(pkt, *id++); | ||
| 390 | 413 | ||
| 391 | return pkt; | 414 | return pkt; |
| 392 | } | 415 | } |
| 393 | 416 | ||
| 394 | static void int_to_threadref(unsigned char *id, int value) | 417 | static void int_to_threadref(unsigned char *id, int value) |
| 395 | { | 418 | { |
| 396 | unsigned char *scan; | 419 | put_unaligned_be32(value, id); |
| 397 | int i = 4; | ||
| 398 | |||
| 399 | scan = (unsigned char *)id; | ||
| 400 | while (i--) | ||
| 401 | *scan++ = 0; | ||
| 402 | |||
