diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:24 -0400 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2010-05-20 22:04:24 -0400 |
commit | a0de055cf61338549b13079a5677ef2e1b6472ef (patch) | |
tree | 6191bbd6b3d567350b12ad973356995dbeffeeb3 /kernel/debug | |
parent | 6d45a1aed34b0cd7b298967eb9cb72b77afcb33b (diff) |
kgdb: gdb "monitor" -> kdb passthrough
One of the driving forces behind integrating another front end (kdb)
to the debug core is to allow front end commands to be accessible via
gdb's monitor command. It is true that you could write gdb macros to
get certain data, but you may want to just use gdb to access the
commands that are available in the kdb front end.
This patch implements the Rcmd gdb stub packet. In gdb you access
this with the "monitor" command. For instance you could type "monitor
help", "monitor lsmod" or "monitor ps A" etc...
There is no error checking or command restrictions on what you can and
cannot access at this point. Doing something like trying to set
breakpoints with the monitor command is going to cause nothing but
problems. Perhaps in the future only the commands that are actually
known to work with the gdb monitor command will be available.
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'kernel/debug')
-rw-r--r-- | kernel/debug/debug_core.c | 2 | ||||
-rw-r--r-- | kernel/debug/debug_core.h | 2 | ||||
-rw-r--r-- | kernel/debug/gdbstub.c | 22 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_io.c | 13 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_private.h | 1 |
5 files changed, 34 insertions, 6 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 1d71df66f3fa..1aed37b4c564 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
@@ -82,7 +82,7 @@ static int kgdb_use_con; | |||
82 | int dbg_switch_cpu; | 82 | int dbg_switch_cpu; |
83 | 83 | ||
84 | /* Use kdb or gdbserver mode */ | 84 | /* Use kdb or gdbserver mode */ |
85 | static int dbg_kdb_mode = 1; | 85 | int dbg_kdb_mode = 1; |
86 | 86 | ||
87 | static int __init opt_kgdb_con(char *str) | 87 | static int __init opt_kgdb_con(char *str) |
88 | { | 88 | { |
diff --git a/kernel/debug/debug_core.h b/kernel/debug/debug_core.h index 44cf3de8cf9e..c5d753d80f67 100644 --- a/kernel/debug/debug_core.h +++ b/kernel/debug/debug_core.h | |||
@@ -66,9 +66,11 @@ extern void gdbstub_msg_write(const char *s, int len); | |||
66 | 66 | ||
67 | /* gdbstub functions used for kdb <-> gdbstub transition */ | 67 | /* gdbstub functions used for kdb <-> gdbstub transition */ |
68 | extern int gdbstub_state(struct kgdb_state *ks, char *cmd); | 68 | extern int gdbstub_state(struct kgdb_state *ks, char *cmd); |
69 | extern int dbg_kdb_mode; | ||
69 | 70 | ||
70 | #ifdef CONFIG_KGDB_KDB | 71 | #ifdef CONFIG_KGDB_KDB |
71 | extern int kdb_stub(struct kgdb_state *ks); | 72 | extern int kdb_stub(struct kgdb_state *ks); |
73 | extern int kdb_parse(const char *cmdstr); | ||
72 | #else /* ! CONFIG_KGDB_KDB */ | 74 | #else /* ! CONFIG_KGDB_KDB */ |
73 | static inline int kdb_stub(struct kgdb_state *ks) | 75 | static inline int kdb_stub(struct kgdb_state *ks) |
74 | { | 76 | { |
diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index 3c000490a7dd..4b17b3269525 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c | |||
@@ -201,6 +201,9 @@ void gdbstub_msg_write(const char *s, int len) | |||
201 | int wcount; | 201 | int wcount; |
202 | int i; | 202 | int i; |
203 | 203 | ||
204 | if (len == 0) | ||
205 | len = strlen(s); | ||
206 | |||
204 | /* 'O'utput */ | 207 | /* 'O'utput */ |
205 | gdbmsgbuf[0] = 'O'; | 208 | gdbmsgbuf[0] = 'O'; |
206 | 209 | ||
@@ -685,6 +688,25 @@ static void gdb_cmd_query(struct kgdb_state *ks) | |||
685 | kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); | 688 | kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); |
686 | } | 689 | } |
687 | break; | 690 | break; |
691 | #ifdef CONFIG_KGDB_KDB | ||
692 | case 'R': | ||
693 | if (strncmp(remcom_in_buffer, "qRcmd,", 6) == 0) { | ||
694 | int len = strlen(remcom_in_buffer + 6); | ||
695 | |||
696 | if ((len % 2) != 0) { | ||
697 | strcpy(remcom_out_buffer, "E01"); | ||
698 | break; | ||
699 | } | ||
700 | kgdb_hex2mem(remcom_in_buffer + 6, | ||
701 | remcom_out_buffer, len); | ||
702 | len = len / 2; | ||
703 | remcom_out_buffer[len++] = 0; | ||
704 | |||
705 | kdb_parse(remcom_out_buffer); | ||
706 | strcpy(remcom_out_buffer, "OK"); | ||
707 | } | ||
708 | break; | ||
709 | #endif | ||
688 | } | 710 | } |
689 | } | 711 | } |
690 | 712 | ||
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 9e3cec7a925c..8339b291e8bc 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/nmi.h> | 22 | #include <linux/nmi.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/kgdb.h> | ||
24 | #include <linux/kdb.h> | 25 | #include <linux/kdb.h> |
25 | #include <linux/kallsyms.h> | 26 | #include <linux/kallsyms.h> |
26 | #include "kdb_private.h" | 27 | #include "kdb_private.h" |
@@ -669,10 +670,14 @@ kdb_printit: | |||
669 | * Write to all consoles. | 670 | * Write to all consoles. |
670 | */ | 671 | */ |
671 | retlen = strlen(kdb_buffer); | 672 | retlen = strlen(kdb_buffer); |
672 | while (c) { | 673 | if (!dbg_kdb_mode && kgdb_connected) { |
673 | c->write(c, kdb_buffer, retlen); | 674 | gdbstub_msg_write(kdb_buffer, retlen); |
674 | touch_nmi_watchdog(); | 675 | } else { |
675 | c = c->next; | 676 | while (c) { |
677 | c->write(c, kdb_buffer, retlen); | ||
678 | touch_nmi_watchdog(); | ||
679 | c = c->next; | ||
680 | } | ||
676 | } | 681 | } |
677 | if (logging) { | 682 | if (logging) { |
678 | saved_loglevel = console_loglevel; | 683 | saved_loglevel = console_loglevel; |
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 69ed2eff3fea..97d3ba69775d 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h | |||
@@ -254,7 +254,6 @@ extern unsigned long kdb_task_state(const struct task_struct *p, | |||
254 | unsigned long mask); | 254 | unsigned long mask); |
255 | extern void kdb_ps_suppressed(void); | 255 | extern void kdb_ps_suppressed(void); |
256 | extern void kdb_ps1(const struct task_struct *p); | 256 | extern void kdb_ps1(const struct task_struct *p); |
257 | extern int kdb_parse(const char *cmdstr); | ||
258 | extern void kdb_print_nameval(const char *name, unsigned long val); | 257 | extern void kdb_print_nameval(const char *name, unsigned long val); |
259 | extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info); | 258 | extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info); |
260 | extern void kdb_meminfo_proc_show(void); | 259 | extern void kdb_meminfo_proc_show(void); |