kgdb patches for 5.13

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.
 
 Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEELzVBU1D3lWq6cKzwfOMlXTn3iKEFAmCIEcIACgkQfOMlXTn3
 iKHaWRAApW5fVDvM4ACAYYzqnq+ID2wW5h9XHpbyFqeaErQQEwjIcQHKMnHGMQ7J
 2Smb8r9hmk93HgetUAYUe1xoU1/UgiVUlLxZDmtWw8Kf/e9unRcFAa6nUUxeFDn9
 J3s1ZLAGOyjxThRKqOhgoQLE0c+tby7QaiEFF1O/iHTxWIn/euSTRbENoF40xDXU
 oheEfysWF9TpRo/96ZO14tbBHj6THrjyKkHFzYyjRs29wc/j/ofLg9OJj4tzuMne
 XecT7npDJ1JFoyZfkvxxK8TW/a2MLaH1EVO3EpiBM6tMSlHW3NRCehXXlJ6JyGY0
 wAYwd5hgldXcVL8kmDXIC8qhuhGf7mCaU/8AmWyISj+lQcmcNfZYivJmZjdEW3qT
 yFkZ3k/r18N7/tRPbvOarlhxNHx+eCaFGm5ffz9VmMHMp1nrTk1lGhK63gTel3B0
 ndIbvpN4ujWpes5lDg2knvZpaRIClSvisn/UyuuzZyWmeTT/kdUVHruSmopUFw9m
 BEWvAh0HwlR9dRhB8UKUyFF7w5fMXXw0+9j5HOw7gOR78QoNUZymBsxsISWp9fOO
 +Pzz3B9+TQdt9aZP1frMgDvNf6HDebxDZnmgCh5uMoLiKXAqJtJYdmLCOiTjtg35
 FG44QhZFFlyDQdmPFf3hY+hGf2YxNdk+zdlyYq/amFjm5N3jGUM=
 =2I9J
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2021-04-27 18:07:19 -07:00
commit 916a75965e
5 changed files with 384 additions and 312 deletions

View File

@ -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
* 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)
{
@ -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)
{

View File

@ -522,6 +522,54 @@ static int kdb_ss(int argc, const char **argv)
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. */
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++)
bp->bp_free = 1;
kdb_register_flags("bp", kdb_bp, "[<vaddr>]",
"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);
kdb_register_table(bptab, ARRAY_SIZE(bptab));
if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT)
kdb_register_flags("bph", kdb_bp, "[<vaddr>]",
"[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.
*/
kdb_register_table(&bphcmd, 1);
}

View File

@ -33,6 +33,7 @@
#include <linux/kallsyms.h>
#include <linux/kgdb.h>
#include <linux/kdb.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic =
static unsigned int kdb_continue_catastrophic;
#endif
/* kdb_commands describes the available commands. */
static kdbtab_t *kdb_commands;
#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++)
/* kdb_cmds_head describes the available commands. */
static LIST_HEAD(kdb_cmds_head);
typedef struct _kdbmsg {
int km_diag; /* kdb diagnostic */
@ -146,42 +140,18 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
* KDB_ENVBUFSIZE if required).
*/
static char *__env[] = {
static char *__env[31] = {
#if defined(CONFIG_SMP)
"PROMPT=[%d]kdb> ",
"PROMPT=[%d]kdb> ",
#else
"PROMPT=kdb> ",
"PROMPT=kdb> ",
#endif
"MOREPROMPT=more> ",
"RADIX=16",
"MDCOUNT=8", /* lines of md output */
KDB_PLATFORM_ENV,
"DTABCOUNT=30",
"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,
"MOREPROMPT=more> ",
"RADIX=16",
"MDCOUNT=8", /* lines of md output */
KDB_PLATFORM_ENV,
"DTABCOUNT=30",
"NOSECT=1",
};
static const int __nenv = ARRAY_SIZE(__env);
@ -323,6 +293,63 @@ int kdbgetintenv(const char *match, int *value)
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
* unsigned long value.
@ -380,10 +407,6 @@ int kdbgetu64arg(const char *arg, u64 *value)
*/
int kdb_set(int argc, const char **argv)
{
int i;
char *ep;
size_t varlen, vallen;
/*
* we can be invoked two ways:
* set var=value argv[1]="var", argv[2]="value"
@ -428,37 +451,7 @@ int kdb_set(int argc, const char **argv)
* Tokenizer squashed the '=' sign. argv[1] is variable
* name, argv[2] = value.
*/
varlen = strlen(argv[1]);
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;
return kdb_setenv(argv[1], argv[2]);
}
static int kdb_check_regs(void)
@ -921,7 +914,7 @@ int kdb_parse(const char *cmdstr)
char *cp;
char *cpp, quoted;
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.
@ -1011,25 +1004,17 @@ int kdb_parse(const char *cmdstr)
++argv[0];
}
for_each_kdbcmd(tp, i) {
if (tp->cmd_name) {
/*
* If this command is allowed to be abbreviated,
* check to see if this is it.
*/
list_for_each_entry(tp, &kdb_cmds_head, list_node) {
/*
* If this command is allowed to be abbreviated,
* check to see if this is it.
*/
if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) &&
(strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0))
break;
if (tp->cmd_minlen
&& (strlen(argv[0]) <= tp->cmd_minlen)) {
if (strncmp(argv[0],
tp->cmd_name,
tp->cmd_minlen) == 0) {
break;
}
}
if (strcmp(argv[0], tp->cmd_name) == 0)
break;
}
if (strcmp(argv[0], tp->cmd_name) == 0)
break;
}
/*
@ -1037,19 +1022,15 @@ int kdb_parse(const char *cmdstr)
* few characters of this match any of the known commands.
* e.g., md1c20 should match md.
*/
if (i == kdb_max_commands) {
for_each_kdbcmd(tp, i) {
if (tp->cmd_name) {
if (strncmp(argv[0],
tp->cmd_name,
strlen(tp->cmd_name)) == 0) {
break;
}
}
if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
list_for_each_entry(tp, &kdb_cmds_head, list_node) {
if (strncmp(argv[0], tp->cmd_name,
strlen(tp->cmd_name)) == 0)
break;
}
}
if (i < kdb_max_commands) {
if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
int result;
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)
static int kdb_env(int argc, const char **argv)
{
int i;
for (i = 0; i < __nenv; i++) {
if (__env[i])
kdb_printf("%s\n", __env[i]);
}
kdb_printenv();
if (KDB_DEBUG(MASK))
kdb_printf("KDBDEBUG=0x%x\n",
@ -2428,17 +2404,14 @@ static int kdb_kgdb(int argc, const char **argv)
static int kdb_help(int argc, const char **argv)
{
kdbtab_t *kt;
int i;
kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
kdb_printf("-----------------------------"
"-----------------------------\n");
for_each_kdbcmd(kt, i) {
list_for_each_entry(kt, &kdb_cmds_head, list_node) {
char *space = "";
if (KDB_FLAG(CMD_INTERRUPT))
return 0;
if (!kt->cmd_name)
continue;
if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
continue;
if (strlen(kt->cmd_usage) > 20)
@ -2659,7 +2632,6 @@ static int kdb_grep_help(int argc, const char **argv)
* Returns:
* zero for success, one if a duplicate command.
*/
#define kdb_command_extend 50 /* arbitrary */
int kdb_register_flags(char *cmd,
kdb_func_t func,
char *usage,
@ -2667,49 +2639,20 @@ int kdb_register_flags(char *cmd,
short minlen,
kdb_cmdflags_t flags)
{
int i;
kdbtab_t *kp;
/*
* Brute force method to determine duplicates
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
list_for_each_entry(kp, &kdb_cmds_head, list_node) {
if (strcmp(kp->cmd_name, cmd) == 0) {
kdb_printf("Duplicate kdb command registered: "
"%s, func %px help %s\n", cmd, func, help);
return 1;
}
}
/*
* Insert command into first available location in table
*/
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;
}
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 = kmalloc(sizeof(*kp), GFP_KDB);
if (!kp) {
kdb_printf("Could not allocate new kdb_command table\n");
return 1;
}
kp->cmd_name = cmd;
@ -2718,11 +2661,27 @@ int kdb_register_flags(char *cmd,
kp->cmd_help = help;
kp->cmd_minlen = minlen;
kp->cmd_flags = flags;
kp->is_dynamic = true;
list_add_tail(&kp->list_node, &kdb_cmds_head);
return 0;
}
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
@ -2757,15 +2716,16 @@ EXPORT_SYMBOL_GPL(kdb_register);
*/
int kdb_unregister(char *cmd)
{
int i;
kdbtab_t *kp;
/*
* find the command.
*/
for_each_kdbcmd(kp, i) {
if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
kp->cmd_name = NULL;
list_for_each_entry(kp, &kdb_cmds_head, list_node) {
if (strcmp(kp->cmd_name, cmd) == 0) {
list_del(&kp->list_node);
if (kp->is_dynamic)
kfree(kp);
return 0;
}
}
@ -2775,118 +2735,222 @@ int kdb_unregister(char *cmd)
}
EXPORT_SYMBOL_GPL(kdb_unregister);
static kdbtab_t maintab[] = {
{ .cmd_name = "md",
.cmd_func = kdb_md,
.cmd_usage = "<vaddr>",
.cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1",
.cmd_minlen = 1,
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "mdr",
.cmd_func = kdb_md,
.cmd_usage = "<vaddr> <bytes>",
.cmd_help = "Display Raw Memory",
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "mdp",
.cmd_func = kdb_md,
.cmd_usage = "<paddr> <bytes>",
.cmd_help = "Display Physical Memory",
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "mds",
.cmd_func = kdb_md,
.cmd_usage = "<vaddr>",
.cmd_help = "Display Memory Symbolically",
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "mm",
.cmd_func = kdb_mm,
.cmd_usage = "<vaddr> <contents>",
.cmd_help = "Modify Memory Contents",
.cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
},
{ .cmd_name = "go",
.cmd_func = kdb_go,
.cmd_usage = "[<vaddr>]",
.cmd_help = "Continue Execution",
.cmd_minlen = 1,
.cmd_flags = KDB_ENABLE_REG_WRITE |
KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
},
{ .cmd_name = "rd",
.cmd_func = kdb_rd,
.cmd_usage = "",
.cmd_help = "Display Registers",
.cmd_flags = KDB_ENABLE_REG_READ,
},
{ .cmd_name = "rm",
.cmd_func = kdb_rm,
.cmd_usage = "<reg> <contents>",
.cmd_help = "Modify Registers",
.cmd_flags = KDB_ENABLE_REG_WRITE,
},
{ .cmd_name = "ef",
.cmd_func = kdb_ef,
.cmd_usage = "<vaddr>",
.cmd_help = "Display exception frame",
.cmd_flags = KDB_ENABLE_MEM_READ,
},
{ .cmd_name = "bt",
.cmd_func = kdb_bt,
.cmd_usage = "[<vaddr>]",
.cmd_help = "Stack traceback",
.cmd_minlen = 1,
.cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
},
{ .cmd_name = "btp",
.cmd_func = kdb_bt,
.cmd_usage = "<pid>",
.cmd_help = "Display stack for process <pid>",
.cmd_flags = KDB_ENABLE_INSPECT,
},
{ .cmd_name = "bta",
.cmd_func = kdb_bt,
.cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]",
.cmd_help = "Backtrace all processes matching state flag",
.cmd_flags = KDB_ENABLE_INSPECT,
},
{ .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)
{ .cmd_name = "lsmod",
.cmd_func = kdb_lsmod,
.cmd_usage = "",
.cmd_help = "List loaded kernel modules",
.cmd_flags = KDB_ENABLE_INSPECT,
},
#endif
#if defined(CONFIG_MAGIC_SYSRQ)
{ .cmd_name = "sr",
.cmd_func = kdb_sr,
.cmd_usage = "<key>",
.cmd_help = "Magic SysRq key",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif
#if defined(CONFIG_PRINTK)
{ .cmd_name = "dmesg",
.cmd_func = kdb_dmesg,
.cmd_usage = "[lines]",
.cmd_help = "Display syslog buffer",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
#endif
{ .cmd_name = "defcmd",
.cmd_func = kdb_defcmd,
.cmd_usage = "name \"usage\" \"help\"",
.cmd_help = "Define a set of commands, down to endefcmd",
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
},
{ .cmd_name = "kill",
.cmd_func = kdb_kill,
.cmd_usage = "<-signal> <pid>",
.cmd_help = "Send a signal to a process",
.cmd_flags = KDB_ENABLE_SIGNAL,
},
{ .cmd_name = "summary",
.cmd_func = kdb_summary,
.cmd_usage = "",
.cmd_help = "Summarize the system",
.cmd_minlen = 4,
.cmd_flags = 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)
{
int i;
kdbtab_t *kp;
for_each_kdbcmd(kp, i)
kp->cmd_name = NULL;
kdb_register_flags("md", kdb_md, "<vaddr>",
"Display Memory Contents, also mdWcN, e.g. md8c1", 1,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>",
"Display Raw Memory", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>",
"Display Physical Memory", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mds", kdb_md, "<vaddr>",
"Display Memory Symbolically", 0,
KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>",
"Modify Memory Contents", 0,
KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS);
kdb_register_flags("go", kdb_go, "[<vaddr>]",
"Continue Execution", 1,
KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
kdb_register_flags("rd", kdb_rd, "",
"Display Registers", 0,
KDB_ENABLE_REG_READ);
kdb_register_flags("rm", kdb_rm, "<reg> <contents>",
"Modify Registers", 0,
KDB_ENABLE_REG_WRITE);
kdb_register_flags("ef", kdb_ef, "<vaddr>",
"Display exception frame", 0,
KDB_ENABLE_MEM_READ);
kdb_register_flags("bt", kdb_bt, "[<vaddr>]",
"Stack traceback", 1,
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
kdb_register_flags("btp", kdb_bt, "<pid>",
"Display stack for process <pid>", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
"Backtrace all processes matching state flag", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("btc", kdb_bt, "",
"Backtrace current process on each cpu", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("btt", kdb_bt, "<vaddr>",
"Backtrace process given its struct task address", 0,
KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
kdb_register_flags("env", kdb_env, "",
"Show environment variables", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("set", kdb_set, "",
"Set environment variables", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("help", kdb_help, "",
"Display Help Message", 1,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("?", kdb_help, "",
"Display Help Message", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("cpu", kdb_cpu, "<cpunum>",
"Switch to new cpu", 0,
KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
kdb_register_flags("kgdb", kdb_kgdb, "",
"Enter kgdb mode", 0, 0);
kdb_register_flags("ps", kdb_ps, "[<flags>|A]",
"Display active task list", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("pid", kdb_pid, "<pidnum>",
"Switch to another task", 0,
KDB_ENABLE_INSPECT);
kdb_register_flags("reboot", kdb_reboot, "",
"Reboot the machine immediately", 0,
KDB_ENABLE_REBOOT);
#if defined(CONFIG_MODULES)
kdb_register_flags("lsmod", kdb_lsmod, "",
"List loaded kernel modules", 0,
KDB_ENABLE_INSPECT);
#endif
#if defined(CONFIG_MAGIC_SYSRQ)
kdb_register_flags("sr", kdb_sr, "<key>",
"Magic SysRq key", 0,
KDB_ENABLE_ALWAYS_SAFE);
#endif
#if defined(CONFIG_PRINTK)
kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
"Display syslog buffer", 0,
KDB_ENABLE_ALWAYS_SAFE);
#endif
if (arch_kgdb_ops.enable_nmi) {
kdb_register_flags("disable_nmi", kdb_disable_nmi, "",
"Disable NMI entry to KDB", 0,
KDB_ENABLE_ALWAYS_SAFE);
}
kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
"Define a set of commands, down to endefcmd", 0,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("kill", kdb_kill, "<-signal> <pid>",
"Send a signal to a process", 0,
KDB_ENABLE_SIGNAL);
kdb_register_flags("summary", kdb_summary, "",
"Summarize the system", 4,
KDB_ENABLE_ALWAYS_SAFE);
kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
"Display per_cpu variables", 3,
KDB_ENABLE_MEM_READ);
kdb_register_flags("grephelp", kdb_grep_help, "",
"Display help on | grep", 0,
KDB_ENABLE_ALWAYS_SAFE);
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. */

View File

@ -174,8 +174,11 @@ typedef struct _kdbtab {
short cmd_minlen; /* Minimum legal # command
* chars required */
kdb_cmdflags_t cmd_flags; /* Command behaviour flags */
struct list_head list_node; /* Command list */
bool is_dynamic; /* Command table allocation type */
} kdbtab_t;
extern void kdb_register_table(kdbtab_t *kp, size_t len);
extern int kdb_bt(int, const char **); /* KDB display back trace */
/* KDB breakpoint management functions */
@ -207,9 +210,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p,
unsigned long mask);
extern void kdb_ps_suppressed(void);
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_meminfo_proc_show(void);
extern char kdb_getchar(void);
extern char *kdb_getstr(char *, size_t, const char *);
extern void kdb_gdb_state_pass(char *buf);

View File

@ -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;
}
/*
* 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
* the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
* for space usage, not for speed. One smallish memory pool, the free