Merge tag 'for_linux-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb
Pull KGDB/KDB fixes and cleanups from Jason Wessel:
"For a change we removed more code than we added. If people aren't
using it we shouldn't be carrying it. :-)
Cleanups:
- Remove kdb ssb command - there is no in kernel disassembler to
support it
- Remove kdb ll command - Always caused a kernel oops and there were
no bug reports so no one was using this command
- Use kernel ARRAY_SIZE macro instead of array computations
Fixes:
- Stop oops in kdb if user executes kdb_defcmd with args
- kdb help command truncated text
- ppc64 support for kgdbts
- Add missing kconfig option from original kdb port for dealing with
catastrophic kernel crashes such that you can reboot automatically
on continue from kdb"
* tag 'for_linux-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb:
kdb: Remove unhandled ssb command
kdb: Prevent kernel oops with kdb_defcmd
kdb: Remove the ll command
kdb_main: fix help print
kdb: Fix overlap in buffers with strcpy
Fixed dead ifdef block by adding missing Kconfig option.
kdb: Setup basic kdb state before invoking commands via kgdb
kdb: use ARRAY_SIZE where possible
kgdb/kgdbts: support ppc64
kdb: A fix for kdb command table expansion
This commit is contained in:
@@ -103,6 +103,7 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#define v1printk(a...) do { \
|
#define v1printk(a...) do { \
|
||||||
if (verbose) \
|
if (verbose) \
|
||||||
@@ -222,6 +223,7 @@ static unsigned long lookup_addr(char *arg)
|
|||||||
addr = (unsigned long)do_fork;
|
addr = (unsigned long)do_fork;
|
||||||
else if (!strcmp(arg, "hw_break_val"))
|
else if (!strcmp(arg, "hw_break_val"))
|
||||||
addr = (unsigned long)&hw_break_val;
|
addr = (unsigned long)&hw_break_val;
|
||||||
|
addr = (unsigned long) dereference_function_descriptor((void *)addr);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ extern int dbg_kdb_mode;
|
|||||||
#ifdef CONFIG_KGDB_KDB
|
#ifdef CONFIG_KGDB_KDB
|
||||||
extern int kdb_stub(struct kgdb_state *ks);
|
extern int kdb_stub(struct kgdb_state *ks);
|
||||||
extern int kdb_parse(const char *cmdstr);
|
extern int kdb_parse(const char *cmdstr);
|
||||||
|
extern int kdb_common_init_state(struct kgdb_state *ks);
|
||||||
|
extern int kdb_common_deinit_state(void);
|
||||||
#else /* ! CONFIG_KGDB_KDB */
|
#else /* ! CONFIG_KGDB_KDB */
|
||||||
static inline int kdb_stub(struct kgdb_state *ks)
|
static inline int kdb_stub(struct kgdb_state *ks)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -783,7 +783,10 @@ static void gdb_cmd_query(struct kgdb_state *ks)
|
|||||||
len = len / 2;
|
len = len / 2;
|
||||||
remcom_out_buffer[len++] = 0;
|
remcom_out_buffer[len++] = 0;
|
||||||
|
|
||||||
|
kdb_common_init_state(ks);
|
||||||
kdb_parse(remcom_out_buffer);
|
kdb_parse(remcom_out_buffer);
|
||||||
|
kdb_common_deinit_state();
|
||||||
|
|
||||||
strcpy(remcom_out_buffer, "OK");
|
strcpy(remcom_out_buffer, "OK");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -486,11 +486,9 @@ static int kdb_bc(int argc, const char **argv)
|
|||||||
/*
|
/*
|
||||||
* kdb_ss
|
* kdb_ss
|
||||||
*
|
*
|
||||||
* Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch)
|
* Process the 'ss' (Single Step) command.
|
||||||
* commands.
|
|
||||||
*
|
*
|
||||||
* ss
|
* ss
|
||||||
* ssb
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* argc Argument count
|
* argc Argument count
|
||||||
@@ -498,35 +496,23 @@ static int kdb_bc(int argc, const char **argv)
|
|||||||
* Outputs:
|
* Outputs:
|
||||||
* None.
|
* None.
|
||||||
* Returns:
|
* Returns:
|
||||||
* KDB_CMD_SS[B] for success, a kdb error if failure.
|
* KDB_CMD_SS for success, a kdb error if failure.
|
||||||
* Locking:
|
* Locking:
|
||||||
* None.
|
* None.
|
||||||
* Remarks:
|
* Remarks:
|
||||||
*
|
*
|
||||||
* Set the arch specific option to trigger a debug trap after the next
|
* Set the arch specific option to trigger a debug trap after the next
|
||||||
* instruction.
|
* instruction.
|
||||||
*
|
|
||||||
* For 'ssb', set the trace flag in the debug trap handler
|
|
||||||
* after printing the current insn and return directly without
|
|
||||||
* invoking the kdb command processor, until a branch instruction
|
|
||||||
* is encountered.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int kdb_ss(int argc, const char **argv)
|
static int kdb_ss(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int ssb = 0;
|
|
||||||
|
|
||||||
ssb = (strcmp(argv[0], "ssb") == 0);
|
|
||||||
if (argc != 0)
|
if (argc != 0)
|
||||||
return KDB_ARGCOUNT;
|
return KDB_ARGCOUNT;
|
||||||
/*
|
/*
|
||||||
* Set trace flag and go.
|
* Set trace flag and go.
|
||||||
*/
|
*/
|
||||||
KDB_STATE_SET(DOING_SS);
|
KDB_STATE_SET(DOING_SS);
|
||||||
if (ssb) {
|
|
||||||
KDB_STATE_SET(DOING_SSB);
|
|
||||||
return KDB_CMD_SSB;
|
|
||||||
}
|
|
||||||
return KDB_CMD_SS;
|
return KDB_CMD_SS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,8 +547,6 @@ void __init kdb_initbptab(void)
|
|||||||
|
|
||||||
kdb_register_repeat("ss", kdb_ss, "",
|
kdb_register_repeat("ss", kdb_ss, "",
|
||||||
"Single Step", 1, KDB_REPEAT_NO_ARGS);
|
"Single Step", 1, KDB_REPEAT_NO_ARGS);
|
||||||
kdb_register_repeat("ssb", kdb_ss, "",
|
|
||||||
"Single step to branch/call", 0, KDB_REPEAT_NO_ARGS);
|
|
||||||
/*
|
/*
|
||||||
* Architecture dependent initialization.
|
* Architecture dependent initialization.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,6 +34,22 @@ EXPORT_SYMBOL_GPL(kdb_poll_idx);
|
|||||||
|
|
||||||
static struct kgdb_state *kdb_ks;
|
static struct kgdb_state *kdb_ks;
|
||||||
|
|
||||||
|
int kdb_common_init_state(struct kgdb_state *ks)
|
||||||
|
{
|
||||||
|
kdb_initial_cpu = atomic_read(&kgdb_active);
|
||||||
|
kdb_current_task = kgdb_info[ks->cpu].task;
|
||||||
|
kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kdb_common_deinit_state(void)
|
||||||
|
{
|
||||||
|
kdb_initial_cpu = -1;
|
||||||
|
kdb_current_task = NULL;
|
||||||
|
kdb_current_regs = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int kdb_stub(struct kgdb_state *ks)
|
int kdb_stub(struct kgdb_state *ks)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@@ -94,13 +110,10 @@ int kdb_stub(struct kgdb_state *ks)
|
|||||||
}
|
}
|
||||||
/* Set initial kdb state variables */
|
/* Set initial kdb state variables */
|
||||||
KDB_STATE_CLEAR(KGDB_TRANS);
|
KDB_STATE_CLEAR(KGDB_TRANS);
|
||||||
kdb_initial_cpu = atomic_read(&kgdb_active);
|
kdb_common_init_state(ks);
|
||||||
kdb_current_task = kgdb_info[ks->cpu].task;
|
|
||||||
kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
|
|
||||||
/* Remove any breakpoints as needed by kdb and clear single step */
|
/* Remove any breakpoints as needed by kdb and clear single step */
|
||||||
kdb_bp_remove();
|
kdb_bp_remove();
|
||||||
KDB_STATE_CLEAR(DOING_SS);
|
KDB_STATE_CLEAR(DOING_SS);
|
||||||
KDB_STATE_CLEAR(DOING_SSB);
|
|
||||||
KDB_STATE_SET(PAGER);
|
KDB_STATE_SET(PAGER);
|
||||||
/* zero out any offline cpu data */
|
/* zero out any offline cpu data */
|
||||||
for_each_present_cpu(i) {
|
for_each_present_cpu(i) {
|
||||||
@@ -125,9 +138,7 @@ int kdb_stub(struct kgdb_state *ks)
|
|||||||
* Upon exit from the kdb main loop setup break points and restart
|
* Upon exit from the kdb main loop setup break points and restart
|
||||||
* the system based on the requested continue state
|
* the system based on the requested continue state
|
||||||
*/
|
*/
|
||||||
kdb_initial_cpu = -1;
|
kdb_common_deinit_state();
|
||||||
kdb_current_task = NULL;
|
|
||||||
kdb_current_regs = NULL;
|
|
||||||
KDB_STATE_CLEAR(PAGER);
|
KDB_STATE_CLEAR(PAGER);
|
||||||
kdbnearsym_cleanup();
|
kdbnearsym_cleanup();
|
||||||
if (error == KDB_CMD_KGDB) {
|
if (error == KDB_CMD_KGDB) {
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ static kdbmsg_t kdbmsgs[] = {
|
|||||||
};
|
};
|
||||||
#undef KDBMSG
|
#undef KDBMSG
|
||||||
|
|
||||||
static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t);
|
static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -175,7 +175,7 @@ static char *__env[] = {
|
|||||||
(char *)0,
|
(char *)0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int __nenv = (sizeof(__env) / sizeof(char *));
|
static const int __nenv = ARRAY_SIZE(__env);
|
||||||
|
|
||||||
struct task_struct *kdb_curr_task(int cpu)
|
struct task_struct *kdb_curr_task(int cpu)
|
||||||
{
|
{
|
||||||
@@ -681,34 +681,50 @@ static int kdb_defcmd(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
return KDB_ARGCOUNT;
|
return KDB_ARGCOUNT;
|
||||||
defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set),
|
if (in_dbg_master()) {
|
||||||
GFP_KDB);
|
kdb_printf("Command only available during kdb_init()\n");
|
||||||
if (!defcmd_set) {
|
|
||||||
kdb_printf("Could not allocate new defcmd_set entry for %s\n",
|
|
||||||
argv[1]);
|
|
||||||
defcmd_set = save_defcmd_set;
|
|
||||||
return KDB_NOTIMP;
|
return KDB_NOTIMP;
|
||||||
}
|
}
|
||||||
|
defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set),
|
||||||
|
GFP_KDB);
|
||||||
|
if (!defcmd_set)
|
||||||
|
goto fail_defcmd;
|
||||||
memcpy(defcmd_set, save_defcmd_set,
|
memcpy(defcmd_set, save_defcmd_set,
|
||||||
defcmd_set_count * sizeof(*defcmd_set));
|
defcmd_set_count * sizeof(*defcmd_set));
|
||||||
kfree(save_defcmd_set);
|
|
||||||
s = defcmd_set + defcmd_set_count;
|
s = defcmd_set + defcmd_set_count;
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
s->usable = 1;
|
s->usable = 1;
|
||||||
s->name = kdb_strdup(argv[1], GFP_KDB);
|
s->name = kdb_strdup(argv[1], GFP_KDB);
|
||||||
|
if (!s->name)
|
||||||
|
goto fail_name;
|
||||||
s->usage = kdb_strdup(argv[2], GFP_KDB);
|
s->usage = kdb_strdup(argv[2], GFP_KDB);
|
||||||
|
if (!s->usage)
|
||||||
|
goto fail_usage;
|
||||||
s->help = kdb_strdup(argv[3], GFP_KDB);
|
s->help = kdb_strdup(argv[3], GFP_KDB);
|
||||||
|
if (!s->help)
|
||||||
|
goto fail_help;
|
||||||
if (s->usage[0] == '"') {
|
if (s->usage[0] == '"') {
|
||||||
strcpy(s->usage, s->usage+1);
|
strcpy(s->usage, argv[2]+1);
|
||||||
s->usage[strlen(s->usage)-1] = '\0';
|
s->usage[strlen(s->usage)-1] = '\0';
|
||||||
}
|
}
|
||||||
if (s->help[0] == '"') {
|
if (s->help[0] == '"') {
|
||||||
strcpy(s->help, s->help+1);
|
strcpy(s->help, argv[3]+1);
|
||||||
s->help[strlen(s->help)-1] = '\0';
|
s->help[strlen(s->help)-1] = '\0';
|
||||||
}
|
}
|
||||||
++defcmd_set_count;
|
++defcmd_set_count;
|
||||||
defcmd_in_progress = 1;
|
defcmd_in_progress = 1;
|
||||||
|
kfree(save_defcmd_set);
|
||||||
return 0;
|
return 0;
|
||||||
|
fail_help:
|
||||||
|
kfree(s->usage);
|
||||||
|
fail_usage:
|
||||||
|
kfree(s->name);
|
||||||
|
fail_name:
|
||||||
|
kfree(defcmd_set);
|
||||||
|
fail_defcmd:
|
||||||
|
kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
|
||||||
|
defcmd_set = save_defcmd_set;
|
||||||
|
return KDB_NOTIMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1112,7 +1128,6 @@ void kdb_set_current_task(struct task_struct *p)
|
|||||||
* KDB_CMD_GO User typed 'go'.
|
* KDB_CMD_GO User typed 'go'.
|
||||||
* KDB_CMD_CPU User switched to another cpu.
|
* KDB_CMD_CPU User switched to another cpu.
|
||||||
* KDB_CMD_SS Single step.
|
* KDB_CMD_SS Single step.
|
||||||
* KDB_CMD_SSB Single step until branch.
|
|
||||||
*/
|
*/
|
||||||
static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
||||||
kdb_dbtrap_t db_result)
|
kdb_dbtrap_t db_result)
|
||||||
@@ -1151,14 +1166,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
|
|||||||
kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",
|
kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",
|
||||||
instruction_pointer(regs));
|
instruction_pointer(regs));
|
||||||
break;
|
break;
|
||||||
case KDB_DB_SSB:
|
|
||||||
/*
|
|
||||||
* In the midst of ssb command. Just return.
|
|
||||||
*/
|
|
||||||
KDB_DEBUG_STATE("kdb_local 3", reason);
|
|
||||||
return KDB_CMD_SSB; /* Continue with SSB command */
|
|
||||||
|
|
||||||
break;
|
|
||||||
case KDB_DB_SS:
|
case KDB_DB_SS:
|
||||||
break;
|
break;
|
||||||
case KDB_DB_SSBPT:
|
case KDB_DB_SSBPT:
|
||||||
@@ -1281,7 +1288,6 @@ do_full_getstr:
|
|||||||
if (diag == KDB_CMD_GO
|
if (diag == KDB_CMD_GO
|
||||||
|| diag == KDB_CMD_CPU
|
|| diag == KDB_CMD_CPU
|
||||||
|| diag == KDB_CMD_SS
|
|| diag == KDB_CMD_SS
|
||||||
|| diag == KDB_CMD_SSB
|
|
||||||
|| diag == KDB_CMD_KGDB)
|
|| diag == KDB_CMD_KGDB)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1368,12 +1374,6 @@ int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == KDB_CMD_SSB) {
|
|
||||||
KDB_STATE_SET(DOING_SS);
|
|
||||||
KDB_STATE_SET(DOING_SSB);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == KDB_CMD_KGDB) {
|
if (result == KDB_CMD_KGDB) {
|
||||||
if (!KDB_STATE(DOING_KGDB))
|
if (!KDB_STATE(DOING_KGDB))
|
||||||
kdb_printf("Entering please attach debugger "
|
kdb_printf("Entering please attach debugger "
|
||||||
@@ -2350,69 +2350,6 @@ static int kdb_pid(int argc, const char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* kdb_ll - This function implements the 'll' command which follows a
|
|
||||||
* linked list and executes an arbitrary command for each
|
|
||||||
* element.
|
|
||||||
*/
|
|
||||||
static int kdb_ll(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
int diag = 0;
|
|
||||||
unsigned long addr;
|
|
||||||
long offset = 0;
|
|
||||||
unsigned long va;
|
|
||||||
unsigned long linkoffset;
|
|
||||||
int nextarg;
|
|
||||||
const char *command;
|
|
||||||
|
|
||||||
if (argc != 3)
|
|
||||||
return KDB_ARGCOUNT;
|
|
||||||
|
|
||||||
nextarg = 1;
|
|
||||||
diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
|
|
||||||
if (diag)
|
|
||||||
return diag;
|
|
||||||
|
|
||||||
diag = kdbgetularg(argv[2], &linkoffset);
|
|
||||||
if (diag)
|
|
||||||
return diag;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using the starting address as
|
|
||||||
* the first element in the list, and assuming that
|
|
||||||
* the list ends with a null pointer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
va = addr;
|
|
||||||
command = kdb_strdup(argv[3], GFP_KDB);
|
|
||||||
if (!command) {
|
|
||||||
kdb_printf("%s: cannot duplicate command\n", __func__);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Recursive use of kdb_parse, do not use argv after this point */
|
|
||||||
argv = NULL;
|
|
||||||
|
|
||||||
while (va) {
|
|
||||||
char buf[80];
|
|
||||||
|
|
||||||
if (KDB_FLAG(CMD_INTERRUPT))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va);
|
|
||||||
diag = kdb_parse(buf);
|
|
||||||
if (diag)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
addr = va + linkoffset;
|
|
||||||
if (kdb_getword(&va, addr, sizeof(va)))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(command);
|
|
||||||
return diag;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int kdb_kgdb(int argc, const char **argv)
|
static int kdb_kgdb(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
return KDB_CMD_KGDB;
|
return KDB_CMD_KGDB;
|
||||||
@@ -2430,11 +2367,15 @@ static int kdb_help(int argc, const char **argv)
|
|||||||
kdb_printf("-----------------------------"
|
kdb_printf("-----------------------------"
|
||||||
"-----------------------------\n");
|
"-----------------------------\n");
|
||||||
for_each_kdbcmd(kt, i) {
|
for_each_kdbcmd(kt, i) {
|
||||||
if (kt->cmd_name)
|
char *space = "";
|
||||||
kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name,
|
|
||||||
kt->cmd_usage, kt->cmd_help);
|
|
||||||
if (KDB_FLAG(CMD_INTERRUPT))
|
if (KDB_FLAG(CMD_INTERRUPT))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!kt->cmd_name)
|
||||||
|
continue;
|
||||||
|
if (strlen(kt->cmd_usage) > 20)
|
||||||
|
space = "\n ";
|
||||||
|
kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
|
||||||
|
kt->cmd_usage, space, kt->cmd_help);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2739,7 +2680,7 @@ int kdb_register_repeat(char *cmd,
|
|||||||
(kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
|
(kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
|
||||||
kfree(kdb_commands);
|
kfree(kdb_commands);
|
||||||
}
|
}
|
||||||
memset(new + kdb_max_commands, 0,
|
memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,
|
||||||
kdb_command_extend * sizeof(*new));
|
kdb_command_extend * sizeof(*new));
|
||||||
kdb_commands = new;
|
kdb_commands = new;
|
||||||
kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
|
kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
|
||||||
@@ -2843,15 +2784,13 @@ static void __init kdb_inittab(void)
|
|||||||
"Stack traceback", 1, KDB_REPEAT_NONE);
|
"Stack traceback", 1, KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("btp", kdb_bt, "<pid>",
|
kdb_register_repeat("btp", kdb_bt, "<pid>",
|
||||||
"Display stack for process <pid>", 0, KDB_REPEAT_NONE);
|
"Display stack for process <pid>", 0, KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("bta", kdb_bt, "[DRSTCZEUIMA]",
|
kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
|
||||||
"Display stack all processes", 0, KDB_REPEAT_NONE);
|
"Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("btc", kdb_bt, "",
|
kdb_register_repeat("btc", kdb_bt, "",
|
||||||
"Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
|
"Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("btt", kdb_bt, "<vaddr>",
|
kdb_register_repeat("btt", kdb_bt, "<vaddr>",
|
||||||
"Backtrace process given its struct task address", 0,
|
"Backtrace process given its struct task address", 0,
|
||||||
KDB_REPEAT_NONE);
|
KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("ll", kdb_ll, "<first-element> <linkoffset> <cmd>",
|
|
||||||
"Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE);
|
|
||||||
kdb_register_repeat("env", kdb_env, "",
|
kdb_register_repeat("env", kdb_env, "",
|
||||||
"Show environment variables", 0, KDB_REPEAT_NONE);
|
"Show environment variables", 0, KDB_REPEAT_NONE);
|
||||||
kdb_register_repeat("set", kdb_set, "",
|
kdb_register_repeat("set", kdb_set, "",
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#define KDB_CMD_GO (-1001)
|
#define KDB_CMD_GO (-1001)
|
||||||
#define KDB_CMD_CPU (-1002)
|
#define KDB_CMD_CPU (-1002)
|
||||||
#define KDB_CMD_SS (-1003)
|
#define KDB_CMD_SS (-1003)
|
||||||
#define KDB_CMD_SSB (-1004)
|
|
||||||
#define KDB_CMD_KGDB (-1005)
|
#define KDB_CMD_KGDB (-1005)
|
||||||
|
|
||||||
/* Internal debug flags */
|
/* Internal debug flags */
|
||||||
@@ -125,8 +124,6 @@ extern int kdb_state;
|
|||||||
* kdb control */
|
* kdb control */
|
||||||
#define KDB_STATE_HOLD_CPU 0x00000010 /* Hold this cpu inside kdb */
|
#define KDB_STATE_HOLD_CPU 0x00000010 /* Hold this cpu inside kdb */
|
||||||
#define KDB_STATE_DOING_SS 0x00000020 /* Doing ss command */
|
#define KDB_STATE_DOING_SS 0x00000020 /* Doing ss command */
|
||||||
#define KDB_STATE_DOING_SSB 0x00000040 /* Doing ssb command,
|
|
||||||
* DOING_SS is also set */
|
|
||||||
#define KDB_STATE_SSBPT 0x00000080 /* Install breakpoint
|
#define KDB_STATE_SSBPT 0x00000080 /* Install breakpoint
|
||||||
* after one ss, independent of
|
* after one ss, independent of
|
||||||
* DOING_SS */
|
* DOING_SS */
|
||||||
@@ -191,7 +188,6 @@ extern void kdb_bp_remove(void);
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
KDB_DB_BPT, /* Breakpoint */
|
KDB_DB_BPT, /* Breakpoint */
|
||||||
KDB_DB_SS, /* Single-step trap */
|
KDB_DB_SS, /* Single-step trap */
|
||||||
KDB_DB_SSB, /* Single step to branch */
|
|
||||||
KDB_DB_SSBPT, /* Single step over breakpoint */
|
KDB_DB_SSBPT, /* Single step over breakpoint */
|
||||||
KDB_DB_NOBPT /* Spurious breakpoint */
|
KDB_DB_NOBPT /* Spurious breakpoint */
|
||||||
} kdb_dbtrap_t;
|
} kdb_dbtrap_t;
|
||||||
|
|||||||
@@ -80,4 +80,22 @@ config KDB_KEYBOARD
|
|||||||
help
|
help
|
||||||
KDB can use a PS/2 type keyboard for an input device
|
KDB can use a PS/2 type keyboard for an input device
|
||||||
|
|
||||||
|
config KDB_CONTINUE_CATASTROPHIC
|
||||||
|
int "KDB: continue after catastrophic errors"
|
||||||
|
depends on KGDB_KDB
|
||||||
|
default "0"
|
||||||
|
help
|
||||||
|
This integer controls the behaviour of kdb when the kernel gets a
|
||||||
|
catastrophic error, i.e. for a panic or oops.
|
||||||
|
When KDB is active and a catastrophic error occurs, nothing extra
|
||||||
|
will happen until you type 'go'.
|
||||||
|
CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default). The first time
|
||||||
|
you type 'go', you will be warned by kdb. The secend time you type
|
||||||
|
'go', KDB tries to continue. No guarantees that the
|
||||||
|
kernel is still usable in this situation.
|
||||||
|
CONFIG_KDB_CONTINUE_CATASTROPHIC == 1. KDB tries to continue.
|
||||||
|
No guarantees that the kernel is still usable in this situation.
|
||||||
|
CONFIG_KDB_CONTINUE_CATASTROPHIC == 2. KDB forces a reboot.
|
||||||
|
If you are not sure, say 0.
|
||||||
|
|
||||||
endif # KGDB
|
endif # KGDB
|
||||||
|
|||||||
Reference in New Issue
Block a user