Commit 916a7596 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'kgdb-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux

Pull kgdb updates from Daniel Thompson:
 "Exclusively tidy ups this cycle. Most of them are thanks to Sumit Garg
  and, as it happens, the clean ups do result in a slight increase in
  the line count. This is due to registering kdb commands using data
  structures rather than function calls which, in turn, simplifies the
  memory management during command registration.

  In addition to changes to command registration we also have some dead
  code removal, a clearer implementation of environment variable
  handling and a typo fix"

* tag 'kgdb-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux:
  kdb: Refactor env variables get/set code
  kernel: debug: Ordinary typo fixes in the file gdbstub.c
  kdb: Simplify kdb commands registration
  kdb: Remove redundant function definitions/prototypes
parents 6daa755f 83fa2d13
...@@ -321,7 +321,7 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val) ...@@ -321,7 +321,7 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val)
/* /*
* Copy the binary array pointed to by buf into mem. Fix $, #, and * Copy the binary array pointed to by buf into mem. Fix $, #, and
* 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success. * 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
* The input buf is overwitten with the result to write to mem. * The input buf is overwritten with the result to write to mem.
*/ */
static int kgdb_ebin2mem(char *buf, char *mem, int count) static int kgdb_ebin2mem(char *buf, char *mem, int count)
{ {
...@@ -952,7 +952,7 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks) ...@@ -952,7 +952,7 @@ static int gdb_cmd_exception_pass(struct kgdb_state *ks)
} }
/* /*
* This function performs all gdbserial command procesing * This function performs all gdbserial command processing
*/ */
int gdb_serial_stub(struct kgdb_state *ks) int gdb_serial_stub(struct kgdb_state *ks)
{ {
......
...@@ -522,6 +522,54 @@ static int kdb_ss(int argc, const char **argv) ...@@ -522,6 +522,54 @@ static int kdb_ss(int argc, const char **argv)
return KDB_CMD_SS; return KDB_CMD_SS;
} }
static kdbtab_t bptab[] = {
{ .cmd_name = "bp",
.cmd_func = kdb_bp,
.cmd_usage = "[<vaddr>]",
.cmd_help = "Set/Display breakpoints",
.cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "bl",
.cmd_func = kdb_bp,
.cmd_usage = "[<vaddr>]",
.cmd_help = "Display breakpoints",
.cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "bc",
.cmd_func = kdb_bc,
.cmd_usage = "<bpnum>",
.cmd_help = "Clear Breakpoint",
.cmd_flags = KDB_ENABLE_FLOW_CTRL,
},
{ .cmd_name = "be",
.cmd_func = kdb_bc,
.cmd_usage = "<bpnum>",
.cmd_help = "Enable Breakpoint",
.cmd_flags = KDB_ENABLE_FLOW_CTRL,
},
{ .cmd_name = "bd",
.cmd_func = kdb_bc,
.cmd_usage = "<bpnum>",
.cmd_help = "Disable Breakpoint",
.cmd_flags = KDB_ENABLE_FLOW_CTRL,
},
{ .cmd_name = "ss",
.cmd_func = kdb_ss,
.cmd_usage = "",
.cmd_help = "Single Step",
.cmd_minlen = 1,
.cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
},
};
static kdbtab_t bphcmd = {
.cmd_name = "bph",
.cmd_func = kdb_bp,
.cmd_usage = "[<vaddr>]",
.cmd_help = "[datar [length]|dataw [length]] Set hw brk",
.cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS,
};
/* Initialize the breakpoint table and register breakpoint commands. */ /* Initialize the breakpoint table and register breakpoint commands. */
void __init kdb_initbptab(void) void __init kdb_initbptab(void)
...@@ -537,30 +585,7 @@ void __init kdb_initbptab(void) ...@@ -537,30 +585,7 @@ void __init kdb_initbptab(void)
for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++)
bp->bp_free = 1; bp->bp_free = 1;
kdb_register_flags("bp", kdb_bp, "[<vaddr>]", kdb_register_table(bptab, ARRAY_SIZE(bptab));
"Set/Display breakpoints", 0,
KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS);
kdb_register_flags("bl", kdb_bp, "[<vaddr>]",
"Display breakpoints", 0,
KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS);
if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT)
kdb_register_flags("bph", kdb_bp, "[<vaddr>]", kdb_register_table(&bphcmd, 1);
"[datar [length]|dataw [length]] Set hw brk", 0,
KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS);
kdb_register_flags("bc", kdb_bc, "<bpnum>",
"Clear Breakpoint", 0,
KDB_ENABLE_FLOW_CTRL);
kdb_register_flags("be", kdb_bc, "<bpnum>",
"Enable Breakpoint", 0,
KDB_ENABLE_FLOW_CTRL);
kdb_register_flags("bd", kdb_bc, "<bpnum>",
"Disable Breakpoint", 0,
KDB_ENABLE_FLOW_CTRL);
kdb_register_flags("ss", kdb_ss, "",
"Single Step", 1,
KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS);
/*
* Architecture dependent initialization.
*/
} }
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/kgdb.h> #include <linux/kgdb.h>
#include <linux/kdb.h> #include <linux/kdb.h>
#include <linux/list.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic = ...@@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic =
static unsigned int kdb_continue_catastrophic; static unsigned int kdb_continue_catastrophic;
#endif #endif
/* kdb_commands describes the available commands. */ /* kdb_cmds_head describes the available commands. */
static kdbtab_t *kdb_commands; static LIST_HEAD(kdb_cmds_head);
#define KDB_BASE_CMD_MAX 50
static int kdb_max_commands = KDB_BASE_CMD_MAX;
static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];
#define for_each_kdbcmd(cmd, num) \
for ((cmd) = kdb_base_commands, (num) = 0; \
num < kdb_max_commands; \
num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)
typedef struct _kdbmsg { typedef struct _kdbmsg {
int km_diag; /* kdb diagnostic */ int km_diag; /* kdb diagnostic */
...@@ -146,7 +140,7 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs); ...@@ -146,7 +140,7 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
* KDB_ENVBUFSIZE if required). * KDB_ENVBUFSIZE if required).
*/ */
static char *__env[] = { static char *__env[31] = {
#if defined(CONFIG_SMP) #if defined(CONFIG_SMP)
"PROMPT=[%d]kdb> ", "PROMPT=[%d]kdb> ",
#else #else
...@@ -158,30 +152,6 @@ static char *__env[] = { ...@@ -158,30 +152,6 @@ static char *__env[] = {
KDB_PLATFORM_ENV, KDB_PLATFORM_ENV,
"DTABCOUNT=30", "DTABCOUNT=30",
"NOSECT=1", "NOSECT=1",
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
(char *)0,
}; };
static const int __nenv = ARRAY_SIZE(__env); static const int __nenv = ARRAY_SIZE(__env);
...@@ -323,6 +293,63 @@ int kdbgetintenv(const char *match, int *value) ...@@ -323,6 +293,63 @@ int kdbgetintenv(const char *match, int *value)
return diag; return diag;
} }
/*
* kdb_setenv() - Alter an existing environment variable or create a new one.
* @var: Name of the variable
* @val: Value of the variable
*
* Return: Zero on success, a kdb diagnostic on failure.
*/
static int kdb_setenv(const char *var, const char *val)
{
int i;
char *ep;
size_t varlen, vallen;
varlen = strlen(var);
vallen = strlen(val);
ep = kdballocenv(varlen + vallen + 2);
if (ep == (char *)0)
return KDB_ENVBUFFULL;
sprintf(ep, "%s=%s", var, val);
for (i = 0; i < __nenv; i++) {
if (__env[i]
&& ((strncmp(__env[i], var, varlen) == 0)
&& ((__env[i][varlen] == '\0')
|| (__env[i][varlen] == '=')))) {
__env[i] = ep;
return 0;
}
}
/*
* Wasn't existing variable. Fit into slot.
*/
for (i = 0; i < __nenv-1; i++) {
if (__env[i] == (char *)0) {
__env[i] = ep;
return 0;
}
}
return KDB_ENVFULL;
}
/*
* kdb_printenv() - Display the current environment variables.
*/
static void kdb_printenv(void)
{
int i;
for (i = 0; i < __nenv; i++) {
if (__env[i])
kdb_printf("%s\n", __env[i]);
}
}
/* /*
* kdbgetularg - This function will convert a numeric string into an * kdbgetularg - This function will convert a numeric string into an
* unsigned long value. * unsigned long value.
...@@ -380,10 +407,6 @@ int kdbgetu64arg(const char *arg, u64 *value) ...@@ -380,10 +407,6 @@ int kdbgetu64arg(const char *arg, u64 *value)
*/ */
int kdb_set(int argc, const char **argv) int kdb_set(int argc, const char **argv)
{ {
int i;
char *ep;
size_t varlen, vallen;
/* /*
* we can be invoked two ways: * we can be invoked two ways:
* set var=value argv[1]="var", argv[2]="value" * set var=value argv[1]="var", argv[2]="value"
...@@ -428,37 +451,7 @@ int kdb_set(int argc, const char **argv) ...@@ -428,37 +451,7 @@ int kdb_set(int argc, const char **argv)
* Tokenizer squashed the '=' sign. argv[1] is variable * Tokenizer squashed the '=' sign. argv[1] is variable
* name, argv[2] = value. * name, argv[2] = value.
*/ */
varlen = strlen(argv[1]); return kdb_setenv(argv[1], argv[2]);
vallen = strlen(argv[2]);
ep = kdballocenv(varlen + vallen + 2);
if (ep == (char *)0)
return KDB_ENVBUFFULL;
sprintf(ep, "%s=%s", argv[1], argv[2]);
ep[varlen+vallen+1] = '\0';
for (i = 0; i < __nenv; i++) {
if (__env[i]
&& ((strncmp(__env[i], argv[1], varlen) == 0)
&& ((__env[i][varlen] == '\0')
|| (__env[i][varlen] == '=')))) {
__env[i] = ep;
return 0;
}
}
/*
* Wasn't existing variable. Fit into slot.
*/
for (i = 0; i < __nenv-1; i++) {
if (__env[i] == (char *)0) {
__env[i] = ep;
return 0;
}
}
return KDB_ENVFULL;
} }
static int kdb_check_regs(void) static int kdb_check_regs(void)
...@@ -921,7 +914,7 @@ int kdb_parse(const char *cmdstr) ...@@ -921,7 +914,7 @@ int kdb_parse(const char *cmdstr)
char *cp; char *cp;
char *cpp, quoted; char *cpp, quoted;
kdbtab_t *tp; kdbtab_t *tp;
int i, escaped, ignore_errors = 0, check_grep = 0; int escaped, ignore_errors = 0, check_grep = 0;
/* /*
* First tokenize the command string. * First tokenize the command string.
...@@ -1011,45 +1004,33 @@ int kdb_parse(const char *cmdstr) ...@@ -1011,45 +1004,33 @@ int kdb_parse(const char *cmdstr)
++argv[0]; ++argv[0];
} }
for_each_kdbcmd(tp, i) { list_for_each_entry(tp, &kdb_cmds_head, list_node) {
if (tp->cmd_name) {
/* /*
* If this command is allowed to be abbreviated, * If this command is allowed to be abbreviated,
* check to see if this is it. * check to see if this is it.
*/ */
if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) &&
if (tp->cmd_minlen (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0))
&& (strlen(argv[0]) <= tp->cmd_minlen)) {
if (strncmp(argv[0],
tp->cmd_name,
tp->cmd_minlen) == 0) {
break; break;
}
}
if (strcmp(argv[0], tp->cmd_name) == 0) if (strcmp(argv[0], tp->cmd_name) == 0)
break; break;
} }
}
/* /*
* If we don't find a command by this name, see if the first * If we don't find a command by this name, see if the first
* few characters of this match any of the known commands. * few characters of this match any of the known commands.
* e.g., md1c20 should match md. * e.g., md1c20 should match md.
*/ */
if (i == kdb_max_commands) { if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
for_each_kdbcmd(tp, i) { list_for_each_entry(tp, &kdb_cmds_head, list_node) {
if (tp->cmd_name) { if (strncmp(argv[0], tp->cmd_name,
if (strncmp(argv[0], strlen(tp->cmd_name)) == 0)
tp->cmd_name,
strlen(tp->cmd_name)) == 0) {
break; break;
} }
} }
}
}
if (i < kdb_max_commands) { if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
int result; int result;
if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1)) if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
...@@ -2073,12 +2054,7 @@ static int kdb_lsmod(int argc, const char **argv) ...@@ -2073,12 +2054,7 @@ static int kdb_lsmod(int argc, const char **argv)
static int kdb_env(int argc, const char **argv) static int kdb_env(int argc, const char **argv)
{ {
int i; kdb_printenv();
for (i = 0; i < __nenv; i++) {
if (__env[i])
kdb_printf("%s\n", __env[i]);
}
if (KDB_DEBUG(MASK)) if (KDB_DEBUG(MASK))
kdb_printf("KDBDEBUG=0x%x\n", kdb_printf("KDBDEBUG=0x%x\n",
...@@ -2428,17 +2404,14 @@ static int kdb_kgdb(int argc, const char **argv) ...@@ -2428,17 +2404,14 @@ static int kdb_kgdb(int argc, const char **argv)
static int kdb_help(int argc, const char **argv) static int kdb_help(int argc, const char **argv)
{ {
kdbtab_t *kt; kdbtab_t *kt;
int i;
kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description"); kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
kdb_printf("-----------------------------" kdb_printf("-----------------------------"
"-----------------------------\n"); "-----------------------------\n");
for_each_kdbcmd(kt, i) { list_for_each_entry(kt, &kdb_cmds_head, list_node) {
char *space = ""; char *space = "";
if (KDB_FLAG(CMD_INTERRUPT)) if (KDB_FLAG(CMD_INTERRUPT))
return 0; return 0;
if (!kt->cmd_name)
continue;
if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true)) if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
continue; continue;
if (strlen(kt->cmd_usage) > 20) if (strlen(kt->cmd_usage) > 20)
...@@ -2659,7 +2632,6 @@ static int kdb_grep_help(int argc, const char **argv) ...@@ -2659,7 +2632,6 @@ static int kdb_grep_help(int argc, const char **argv)
* Returns: * Returns:
* zero for success, one if a duplicate command. * zero for success, one if a duplicate command.
*/ */
#define kdb_command_extend 50 /* arbitrary */
int kdb_register_flags(char *cmd, int kdb_register_flags(char *cmd,
kdb_func_t func, kdb_func_t func,
char *usage, char *usage,
...@@ -2667,50 +2639,21 @@ int kdb_register_flags(char *cmd, ...@@ -2667,50 +2639,21 @@ int kdb_register_flags(char *cmd,
short minlen, short minlen,
kdb_cmdflags_t flags) kdb_cmdflags_t flags)
{ {
int i;
kdbtab_t *kp; kdbtab_t *kp;
/* list_for_each_entry(kp, &kdb_cmds_head, list_node) {
* Brute force method to determine duplicates if (strcmp(kp->cmd_name, cmd) == 0) {
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
kdb_printf("Duplicate kdb command registered: " kdb_printf("Duplicate kdb command registered: "
"%s, func %px help %s\n", cmd, func, help); "%s, func %px help %s\n", cmd, func, help);
return 1; return 1;
} }
} }
/* kp = kmalloc(sizeof(*kp), GFP_KDB);
* Insert command into first available location in table if (!kp) {
*/ kdb_printf("Could not allocate new kdb_command table\n");
for_each_kdbcmd(kp, i) {
if (kp->cmd_name == NULL)
break;
}
if (i >= kdb_max_commands) {
kdbtab_t *new = kmalloc_array(kdb_max_commands -
KDB_BASE_CMD_MAX +
kdb_command_extend,
sizeof(*new),
GFP_KDB);
if (!new) {
kdb_printf("Could not allocate new kdb_command "
"table\n");
return 1; return 1;
} }
if (kdb_commands) {
memcpy(new, kdb_commands,
(kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
kfree(kdb_commands);
}
memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,
kdb_command_extend * sizeof(*new));
kdb_commands = new;
kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
kdb_max_commands += kdb_command_extend;
}
kp->cmd_name = cmd; kp->cmd_name = cmd;
kp->cmd_func = func; kp->cmd_func = func;
...@@ -2718,11 +2661,27 @@ int kdb_register_flags(char *cmd, ...@@ -2718,11 +2661,27 @@ int kdb_register_flags(char *cmd,
kp->cmd_help = help; kp->cmd_help = help;
kp->cmd_minlen = minlen; kp->cmd_minlen = minlen;
kp->cmd_flags = flags; kp->cmd_flags = flags;
kp->is_dynamic = true;
list_add_tail(&kp->list_node, &kdb_cmds_head);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(kdb_register_flags); EXPORT_SYMBOL_GPL(kdb_register_flags);
/*
* kdb_register_table() - This function is used to register a kdb command
* table.
* @kp: pointer to kdb command table
* @len: length of kdb command table
*/
void kdb_register_table(kdbtab_t *kp, size_t len)
{
while (len--) {
list_add_tail(&kp->list_node, &kdb_cmds_head);
kp++;
}
}
/* /*
* kdb_register - Compatibility register function for commands that do * kdb_register - Compatibility register function for commands that do
...@@ -2757,15 +2716,16 @@ EXPORT_SYMBOL_GPL(kdb_register); ...@@ -2757,15 +2716,16 @@ EXPORT_SYMBOL_GPL(kdb_register);
*/ */
int kdb_unregister(char *cmd) int kdb_unregister(char *cmd)
{ {
int i;
kdbtab_t *kp; kdbtab_t *kp;
/* /*
* find the command. * find the command.
*/ */
for_each_kdbcmd(kp, i) { list_for_each_entry(kp, &kdb_cmds_head, list_node) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) { if (strcmp(kp->cmd_name, cmd) == 0) {
kp->cmd_name = NULL; list_del(&kp->list_node);
if (kp->is_dynamic)
kfree(kp);
return 0; return 0;
} }
} }
...@@ -2775,118 +2735,222 @@ int kdb_unregister(char *cmd) ...@@ -2775,118 +2735,222 @@ int kdb_unregister(char *cmd)
} }
EXPORT_SYMBOL_GPL(kdb_unregister); EXPORT_SYMBOL_GPL(kdb_unregister);
/* Initialize the kdb command table. */ static kdbtab_t maintab[] = {
static void __init kdb_inittab(void) { .cmd_name = "md",
{ .cmd_func = kdb_md,
int i; .cmd_usage = "<vaddr>",
kdbtab_t *kp; .cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1",
.cmd_minlen = 1,
for_each_kdbcmd(kp, i) .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
kp->cmd_name = NULL; },
{ .cmd_name = "mdr",
kdb_register_flags("md", kdb_md, "<vaddr>", .cmd_func = kdb_md,
"Display Memory Contents, also mdWcN, e.g. md8c1", 1, .cmd_usage = "<vaddr> <bytes>",
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); .cmd_help = "Display Raw Memory",
kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>", .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
"Display Raw Memory", 0, },
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); { .cmd_name = "mdp",
kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>", .cmd_func = kdb_md,
"Display Physical Memory", 0, .cmd_usage = "<paddr> <bytes>",
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); .cmd_help = "Display Physical Memory",
kdb_register_flags("mds", kdb_md, "<vaddr>", .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
"Display Memory Symbolically", 0, },
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS); { .cmd_name = "mds",
kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>", .cmd_func = kdb_md,
"Modify Memory Contents", 0, .cmd_usage = "<vaddr>",
KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS); .cmd_help = "Display Memory Symbolically",
kdb_register_flags("go", kdb_go, "[<vaddr>]", .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
"Continue Execution", 1, },
KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); { .cmd_name = "mm",
kdb_register_flags("rd", kdb_rd, "", .cmd_func = kdb_mm,
"Display Registers", 0, .cmd_usage = "<vaddr> <contents>",
KDB_ENABLE_REG_READ); .cmd_help = "Modify Memory Contents",
kdb_register_flags("rm", kdb_rm, "<reg> <contents>", .cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
"Modify Registers", 0, },
KDB_ENABLE_REG_WRITE); { .cmd_name = "go",
kdb_register_flags("ef", kdb_ef, "<vaddr>", .cmd_func = kdb_go,
"Display exception frame", 0, .cmd_usage = "[<vaddr>]",
KDB_ENABLE_MEM_READ); .cmd_help = "Continue Execution",
kdb_register_flags("bt", kdb_bt, "[<vaddr>]", .cmd_minlen = 1,
"Stack traceback", 1, .cmd_flags = KDB_ENABLE_REG_WRITE |
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
kdb_register_flags("btp", kdb_bt, "<pid>", },
"Display stack for process <pid>", 0, { .cmd_name = "rd",
KDB_ENABLE_INSPECT); .cmd_func = kdb_rd,
kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]", .cmd_usage = "",
"Backtrace all processes matching state flag", 0, .cmd_help = "Display Registers",
KDB_ENABLE_INSPECT); .cmd_flags = KDB_ENABLE_REG_READ,
kdb_register_flags("btc", kdb_bt, "", },
"Backtrace current process on each cpu", 0, { .cmd_name = "rm",
KDB_ENABLE_INSPECT); .cmd_func = kdb_rm,
kdb_register_flags("btt", kdb_bt, "<vaddr>", .cmd_usage = "<reg> <contents>",
"Backtrace process given its struct task address", 0, .cmd_help = "Modify Registers",
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS); .cmd_flags = KDB_ENABLE_REG_WRITE,
kdb_register_flags("env", kdb_env, "", },
"Show environment variables", 0, { .cmd_name = "ef",
KDB_ENABLE_ALWAYS_SAFE); .cmd_func = kdb_ef,
kdb_register_flags("set", kdb_set, "", .cmd_usage = "<vaddr>",
"Set environment variables", 0, .cmd_help = "Display exception frame",
KDB_ENABLE_ALWAYS_SAFE); .cmd_flags = KDB_ENABLE_MEM_READ,
kdb_register_flags("help", kdb_help, "", },
"Display Help Message", 1, { .cmd_name = "bt",
KDB_ENABLE_ALWAYS_SAFE); .cmd_func = kdb_bt,
kdb_register_flags("?", kdb_help, "", .cmd_usage = "[<vaddr>]",
"Display Help Message", 0, .cmd_help = "Stack traceback",
KDB_ENABLE_ALWAYS_SAFE); .cmd_minlen = 1,
kdb_register_flags("cpu", kdb_cpu, "<cpunum>", .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
"Switch to new cpu", 0, },
KDB_ENABLE_ALWAYS_SAFE_NO_ARGS); { .cmd_name = "btp",
kdb_register_flags("kgdb", kdb_kgdb, "", .cmd_func = kdb_bt,
"Enter kgdb mode", 0, 0); .cmd_usage = "<pid>",
kdb_register_flags("ps", kdb_ps, "[<flags>|A]", .cmd_help = "Display stack for process <pid>",
"Display active task list", 0, .cmd_flags = KDB_ENABLE_INSPECT,
KDB_ENABLE_INSPECT); },
kdb_register_flags("pid", kdb_pid, "<pidnum>", { .cmd_name = "bta",
"Switch to another task", 0, .cmd_func = kdb_bt,
KDB_ENABLE_INSPECT); .cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]",
kdb_register_flags("reboot", kdb_reboot, "", .cmd_help = "Backtrace all processes matching state flag",
"Reboot the machine immediately", 0, .cmd_flags = KDB_ENABLE_INSPECT,
KDB_ENABLE_REBOOT); },
{ .cmd_name = "btc",
.cmd_func = kdb_bt,
.cmd_usage = "",
.cmd_help = "Backtrace current process on each cpu",
.cmd_flags = KDB_ENABLE_INSPECT,
},
{ .cmd_name = "btt",
.cmd_func = kdb_bt,
.cmd_usage = "<vaddr>",
.cmd_help = "Backtrace process given its struct task address",
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
},
{ .cmd_name = "env",
.cmd_func = kdb_env,
.cmd_usage = "",
.cmd_help = "Show environment variables",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
{ .cmd_name = "set",
.cmd_func = kdb_set,
.cmd_usage = "",
.cmd_help = "Set environment variables",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
{ .cmd_name = "help",
.cmd_func = kdb_help,
.cmd_usage = "",
.cmd_help = "Display Help Message",
.cmd_minlen = 1,
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
{ .cmd_name = "?",
.cmd_func = kdb_help,
.cmd_usage = "",
.cmd_help = "Display Help Message",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
{ .cmd_name = "cpu",
.cmd_func = kdb_cpu,
.cmd_usage = "<cpunum>",
.cmd_help = "Switch to new cpu",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
},
{ .cmd_name = "kgdb",
.cmd_func = kdb_kgdb,
.cmd_usage = "",
.cmd_help = "Enter kgdb mode",
.cmd_flags = 0,
},
{ .cmd_name = "ps",
.cmd_func = kdb_ps,
.cmd_usage = "[<flags>|A]",
.cmd_help = "Display active task list",
.cmd_flags = KDB_ENABLE_INSPECT,
},
{ .cmd_name = "pid",
.cmd_func = kdb_pid,
.cmd_usage = "<pidnum>",
.cmd_help = "Switch to another task",
.cmd_flags = KDB_ENABLE_INSPECT,
},
{ .cmd_name = "reboot",
.cmd_func = kdb_reboot,
.cmd_usage = "",
.cmd_help = "Reboot the machine immediately",
.cmd_flags = KDB_ENABLE_REBOOT,
},
#if defined(CONFIG_MODULES) #if defined(CONFIG_MODULES)
kdb_register_flags("lsmod", kdb_lsmod, "", { .cmd_name = "lsmod",
"List loaded kernel modules", 0, .cmd_func = kdb_lsmod,
KDB_ENABLE_INSPECT); .cmd_usage = "",
.cmd_help = "List loaded kernel modules",
.cmd_flags = KDB_ENABLE_INSPECT,
},
#endif #endif
#if defined(CONFIG_MAGIC_SYSRQ) #if defined(CONFIG_MAGIC_SYSRQ)
kdb_register_flags("sr", kdb_sr, "<key>", { .cmd_name = "sr",
"Magic SysRq key", 0, .cmd_func = kdb_sr,
KDB_ENABLE_ALWAYS_SAFE); .cmd_usage = "<key>",
.cmd_help = "Magic SysRq key",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif #endif
#if defined(CONFIG_PRINTK) #if defined(CONFIG_PRINTK)
kdb_register_flags("dmesg", kdb_dmesg, "[lines]", { .cmd_name = "dmesg",
"Display syslog buffer", 0, .cmd_func = kdb_dmesg,
KDB_ENABLE_ALWAYS_SAFE); .cmd_usage = "[lines]",
.cmd_help = "Display syslog buffer",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif #endif
if (arch_kgdb_ops.enable_nmi) { { .cmd_name = "defcmd",
kdb_register_flags("disable_nmi", kdb_disable_nmi, "", .cmd_func = kdb_defcmd,
"Disable NMI entry to KDB", 0, .cmd_usage = "name \"usage\" \"help\"",
KDB_ENABLE_ALWAYS_SAFE); .cmd_help = "Define a set of commands, down to endefcmd",
} .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"", },
"Define a set of commands, down to endefcmd", 0, { .cmd_name = "kill",
KDB_ENABLE_ALWAYS_SAFE); .cmd_func = kdb_kill,
kdb_register_flags("kill", kdb_kill, "<-signal> <pid>", .cmd_usage = "<-signal> <pid>",
"Send a signal to a process", 0, .cmd_help = "Send a signal to a process",
KDB_ENABLE_SIGNAL); .cmd_flags = KDB_ENABLE_SIGNAL,
kdb_register_flags("summary", kdb_summary, "", },
"Summarize the system", 4, { .cmd_name = "summary",
KDB_ENABLE_ALWAYS_SAFE); .cmd_func = kdb_summary,
kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]", .cmd_usage = "",
"Display per_cpu variables", 3, .cmd_help = "Summarize the system",
KDB_ENABLE_MEM_READ); .cmd_minlen = 4,
kdb_register_flags("grephelp", kdb_grep_help, "", .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
"Display help on | grep", 0, },
KDB_ENABLE_ALWAYS_SAFE); { .cmd_name = "per_cpu",
.cmd_func = kdb_per_cpu,
.cmd_usage = "<sym> [<bytes>] [<cpu>]",
.cmd_help = "Display per_cpu variables",
.cmd_minlen = 3,
.cmd_flags = KDB_ENABLE_MEM_READ,
},
{ .cmd_name = "grephelp",
.cmd_func = kdb_grep_help,
.cmd_usage = "",
.cmd_help = "Display help on | grep",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
};
static kdbtab_t nmicmd = {
.cmd_name = "disable_nmi",
.cmd_func = kdb_disable_nmi,
.cmd_usage = "",
.cmd_help = "Disable NMI entry to KDB",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
};
/* Initialize the kdb command table. */
static void __init kdb_inittab(void)
{
kdb_register_table(maintab, ARRAY_SIZE(maintab));
if (arch_kgdb_ops.enable_nmi)
kdb_register_table(&nmicmd, 1);
} }
/* Execute any commands defined in kdb_cmds. */ /* Execute any commands defined in kdb_cmds. */
......
...@@ -174,8 +174,11 @@ typedef struct _kdbtab { ...@@ -174,8 +174,11 @@ typedef struct _kdbtab {
short cmd_minlen; /* Minimum legal # command short cmd_minlen; /* Minimum legal # command
* chars required */ * chars required */
kdb_cmdflags_t cmd_flags; /* Command behaviour flags */ kdb_cmdflags_t cmd_flags; /* Command behaviour flags */
struct list_head list_node; /* Command list */
bool is_dynamic; /* Command table allocation type */
} kdbtab_t; } kdbtab_t;
extern void kdb_register_table(kdbtab_t *kp, size_t len);
extern int kdb_bt(int, const char **); /* KDB display back trace */ extern int kdb_bt(int, const char **); /* KDB display back trace */
/* KDB breakpoint management functions */ /* KDB breakpoint management functions */
...@@ -207,9 +210,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p, ...@@ -207,9 +210,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p,
unsigned long mask); unsigned long mask);
extern void kdb_ps_suppressed(void); extern void kdb_ps_suppressed(void);
extern void kdb_ps1(const struct task_struct *p); extern void kdb_ps1(const struct task_struct *p);
extern void kdb_print_nameval(const char *name, unsigned long val);
extern void kdb_send_sig(struct task_struct *p, int sig); extern void kdb_send_sig(struct task_struct *p, int sig);
extern void kdb_meminfo_proc_show(void);
extern char kdb_getchar(void); extern char kdb_getchar(void);
extern char *kdb_getstr(char *, size_t, const char *); extern char *kdb_getstr(char *, size_t, const char *);
extern void kdb_gdb_state_pass(char *buf); extern void kdb_gdb_state_pass(char *buf);
......
...@@ -654,24 +654,6 @@ unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask) ...@@ -654,24 +654,6 @@ unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask)
return (mask & kdb_task_state_string(state)) != 0; return (mask & kdb_task_state_string(state)) != 0;
} }
/*
* kdb_print_nameval - Print a name and its value, converting the
* value to a symbol lookup if possible.
* Inputs:
* name field name to print
* val value of field
*/
void kdb_print_nameval(const char *name, unsigned long val)
{
kdb_symtab_t symtab;
kdb_printf(" %-11.11s ", name);
if (kdbnearsym(val, &symtab))
kdb_symbol_print(val, &symtab,
KDB_SP_VALUE|KDB_SP_SYMSIZE|KDB_SP_NEWLINE);
else
kdb_printf("0x%lx\n", val);
}
/* Last ditch allocator for debugging, so we can still debug even when /* Last ditch allocator for debugging, so we can still debug even when
* the GFP_ATOMIC pool has been exhausted. The algorithms are tuned * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
* for space usage, not for speed. One smallish memory pool, the free * for space usage, not for speed. One smallish memory pool, the free
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment