aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/debug/gdbstub.c
diff options
context:
space:
mode:
authorJason Wessel <jason.wessel@windriver.com>2010-08-05 10:22:21 -0400
committerJason Wessel <jason.wessel@windriver.com>2010-08-05 10:22:21 -0400
commit55751145dc1e08e16df418cdd101661f5c6ac991 (patch)
treec166155b118da5768341e4678478c5dd508a2b17 /kernel/debug/gdbstub.c
parent22eeef4bb2a7fd225089c0044060ed1fbf091958 (diff)
gdbstub: Implement gdbserial 'p' and 'P' packets
The gdbserial 'p' and 'P' packets allow gdb to individually get and set registers instead of querying for all the available registers. Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug/gdbstub.c')
-rw-r--r--kernel/debug/gdbstub.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c
index 006bad8905d3..4ef9dddf4588 100644
--- a/kernel/debug/gdbstub.c
+++ b/kernel/debug/gdbstub.c
@@ -225,7 +225,7 @@ void gdbstub_msg_write(const char *s, int len)
225 * 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
226 * return an error. 226 * return an error.
227 */ 227 */
228int kgdb_mem2hex(char *mem, char *buf, int count) 228char *kgdb_mem2hex(char *mem, char *buf, int count)
229{ 229{
230 char *tmp; 230 char *tmp;
231 int err; 231 int err;
@@ -237,17 +237,16 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
237 tmp = buf + count; 237 tmp = buf + count;
238 238
239 err = probe_kernel_read(tmp, mem, count); 239 err = probe_kernel_read(tmp, mem, count);
240 if (!err) { 240 if (err)
241 while (count > 0) { 241 return NULL;
242 buf = pack_hex_byte(buf, *tmp); 242 while (count > 0) {
243 tmp++; 243 buf = pack_hex_byte(buf, *tmp);
244 count--; 244 tmp++;
245 } 245 count--;
246
247 *buf = 0;
248 } 246 }
247 *buf = 0;
249 248
250 return err; 249 return buf;
251} 250}
252 251
253/* 252/*
@@ -481,8 +480,7 @@ static void gdb_cmd_status(struct kgdb_state *ks)
481 pack_hex_byte(&remcom_out_buffer[1], ks->signo); 480 pack_hex_byte(&remcom_out_buffer[1], ks->signo);
482} 481}
483 482
484/* Handle the 'g' get registers request */ 483static void gdb_get_regs_helper(struct kgdb_state *ks)
485static void gdb_cmd_getregs(struct kgdb_state *ks)
486{ 484{
487 struct task_struct *thread; 485 struct task_struct *thread;
488 void *local_debuggerinfo; 486 void *local_debuggerinfo;
@@ -523,6 +521,12 @@ static void gdb_cmd_getregs(struct kgdb_state *ks)
523 */ 521 */
524 sleeping_thread_to_gdb_regs(gdb_regs, thread); 522 sleeping_thread_to_gdb_regs(gdb_regs, thread);
525 } 523 }
524}
525
526/* Handle the 'g' get registers request */
527static void gdb_cmd_getregs(struct kgdb_state *ks)
528{
529 gdb_get_regs_helper(ks);
526 kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES); 530 kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES);
527} 531}
528 532
@@ -545,13 +549,13 @@ static void gdb_cmd_memread(struct kgdb_state *ks)
545 char *ptr = &remcom_in_buffer[1]; 549 char *ptr = &remcom_in_buffer[1];
546 unsigned long length; 550 unsigned long length;
547 unsigned long addr; 551 unsigned long addr;
548 int err; 552 char *err;
549 553
550 if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' && 554 if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
551 kgdb_hex2long(&ptr, &length) > 0) { 555 kgdb_hex2long(&ptr, &length) > 0) {
552 err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length); 556 err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
553 if (err) 557 if (!err)
554 error_packet(remcom_out_buffer, err); 558 error_packet(remcom_out_buffer, -EINVAL);
555 } else { 559 } else {
556 error_packet(remcom_out_buffer, -EINVAL); 560 error_packet(remcom_out_buffer, -EINVAL);
557 } 561 }
@@ -568,6 +572,52 @@ static void gdb_cmd_memwrite(struct kgdb_state *ks)
568 strcpy(remcom_out_buffer, "OK"); 572 strcpy(remcom_out_buffer, "OK");
569} 573}
570 574
575#if DBG_MAX_REG_NUM > 0
576static char *gdb_hex_reg_helper(int regnum, char *out)
577{
578 int i;
579 int offset = 0;
580
581 for (i = 0; i < regnum; i++)
582 offset += dbg_reg_def[i].size;
583 return kgdb_mem2hex((char *)gdb_regs + offset, out,
584 dbg_reg_def[i].size);
585}
586
587/* Handle the 'p' individual regster get */
588static void gdb_cmd_reg_get(struct kgdb_state *ks)
589{
590 unsigned long regnum;
591 char *ptr = &remcom_in_buffer[1];
592
593 kgdb_hex2long(&ptr, &regnum);
594 if (regnum >= DBG_MAX_REG_NUM) {
595 error_packet(remcom_out_buffer, -EINVAL);
596 return;
597 }
598 gdb_get_regs_helper(ks);
599 gdb_hex_reg_helper(regnum, remcom_out_buffer);
600}
601
602/* Handle the 'P' individual regster set */
603static void gdb_cmd_reg_set(struct kgdb_state *ks)
604{
605 unsigned long regnum;
606 char *ptr = &remcom_in_buffer[1];
607
608 kgdb_hex2long(&ptr, &regnum);
609 if (*ptr++ != '=' ||
610 !(!kgdb_usethread || kgdb_usethread == current) ||
611 !dbg_get_reg(regnum, gdb_regs, ks->linux_regs)) {
612 error_packet(remcom_out_buffer, -EINVAL);
613 return;
614 }
615 kgdb_hex2mem(ptr, (char *)gdb_regs, dbg_reg_def[regnum].size);
616 dbg_set_reg(regnum, gdb_regs, ks->linux_regs);
617 strcpy(remcom_out_buffer, "OK");
618}
619#endif /* DBG_MAX_REG_NUM > 0 */
620
571/* Handle the 'X' memory binary write bytes */ 621/* Handle the 'X' memory binary write bytes */
572static void gdb_cmd_binwrite(struct kgdb_state *ks) 622static void gdb_cmd_binwrite(struct kgdb_state *ks)
573{ 623{
@@ -874,8 +924,11 @@ int gdb_serial_stub(struct kgdb_state *ks)
874 int error = 0; 924 int error = 0;
875 int tmp; 925 int tmp;
876 926
877 /* Clear the out buffer. */ 927 /* Initialize comm buffer and globals. */
878 memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer)); 928 memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
929 kgdb_usethread = kgdb_info[ks->cpu].task;
930 ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
931 ks->pass_exception = 0;
879 932
880 if (kgdb_connected) { 933 if (kgdb_connected) {
881 unsigned char thref[BUF_THREAD_ID_SIZE]; 934 unsigned char thref[BUF_THREAD_ID_SIZE];
@@ -892,10 +945,6 @@ int gdb_serial_stub(struct kgdb_state *ks)
892 put_packet(remcom_out_buffer); 945 put_packet(remcom_out_buffer);
893 } 946 }
894 947
895 kgdb_usethread = kgdb_info[ks->cpu].task;
896 ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
897 ks->pass_exception = 0;
898
899 while (1) { 948 while (1) {
900 error = 0; 949 error = 0;
901 950
@@ -920,6 +969,14 @@ int gdb_serial_stub(struct kgdb_state *ks)
920 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */ 969 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
921 gdb_cmd_memwrite(ks); 970 gdb_cmd_memwrite(ks);
922 break; 971 break;
972#if DBG_MAX_REG_NUM > 0
973 case 'p': /* pXX Return gdb register XX (in hex) */
974 gdb_cmd_reg_get(ks);
975 break;
976 case 'P': /* PXX=aaaa Set gdb register XX to aaaa (in hex) */
977 gdb_cmd_reg_set(ks);
978 break;
979#endif /* DBG_MAX_REG_NUM > 0 */
923 case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */ 980 case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
924 gdb_cmd_binwrite(ks); 981 gdb_cmd_binwrite(ks);
925 break; 982 break;