linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] kdb: Refactor kdb_defcmd implementation
@ 2021-03-09 12:17 Sumit Garg
  2021-03-19 17:17 ` Daniel Thompson
  0 siblings, 1 reply; 3+ messages in thread
From: Sumit Garg @ 2021-03-09 12:17 UTC (permalink / raw)
  To: kgdb-bugreport
  Cc: daniel.thompson, jason.wessel, dianders, linux-kernel, Sumit Garg

Switch to use kdbtab_t instead of separate struct defcmd_set since
now we have kdb_register_table() to register pre-allocated kdb commands.

Also, switch to use a linked list for sub-commands instead of dynamic
array which makes traversing the sub-commands list simpler.

Suggested-by: Daniel Thompson <daniel.thompson@linaro.org>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
---
 kernel/debug/kdb/kdb_main.c    | 136 +++++++++++++++------------------
 kernel/debug/kdb/kdb_private.h |   7 ++
 2 files changed, 70 insertions(+), 73 deletions(-)

diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 9d69169582c6..2f54e81fd9f7 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -33,7 +33,6 @@
 #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>
@@ -678,16 +677,7 @@ static void kdb_cmderror(int diag)
  * Returns:
  *	zero for success, a kdb diagnostic if error
  */
-struct defcmd_set {
-	int count;
-	bool usable;
-	char *name;
-	char *usage;
-	char *help;
-	char **command;
-};
-static struct defcmd_set *defcmd_set;
-static int defcmd_set_count;
+static kdbtab_t *defcmd_set;
 static bool defcmd_in_progress;
 
 /* Forward references */
@@ -695,53 +685,52 @@ static int kdb_exec_defcmd(int argc, const char **argv);
 
 static int kdb_defcmd2(const char *cmdstr, const char *argv0)
 {
-	struct defcmd_set *s = defcmd_set + defcmd_set_count - 1;
-	char **save_command = s->command;
+	struct kdb_subcmd *ks;
+
+	if (!defcmd_set)
+		return KDB_NOTIMP;
+
 	if (strcmp(argv0, "endefcmd") == 0) {
 		defcmd_in_progress = false;
-		if (!s->count)
-			s->usable = false;
-		if (s->usable)
-			/* macros are always safe because when executed each
-			 * internal command re-enters kdb_parse() and is
-			 * safety checked individually.
-			 */
-			kdb_register_flags(s->name, kdb_exec_defcmd, s->usage,
-					   s->help, 0,
-					   KDB_ENABLE_ALWAYS_SAFE);
+		if (!list_empty(&defcmd_set->kdb_scmds_head))
+			kdb_register_table(defcmd_set, 1);
 		return 0;
 	}
-	if (!s->usable)
-		return KDB_NOTIMP;
-	s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB);
-	if (!s->command) {
+
+	ks = kmalloc(sizeof(*ks), GFP_KDB);
+	if (!ks) {
 		kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
 			   cmdstr);
-		s->usable = false;
 		return KDB_NOTIMP;
 	}
-	memcpy(s->command, save_command, s->count * sizeof(*(s->command)));
-	s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB);
-	kfree(save_command);
+
+	ks->scmd_name = kdb_strdup(cmdstr, GFP_KDB);
+	list_add_tail(&ks->list_node, &defcmd_set->kdb_scmds_head);
+
 	return 0;
 }
 
 static int kdb_defcmd(int argc, const char **argv)
 {
-	struct defcmd_set *save_defcmd_set = defcmd_set, *s;
 	if (defcmd_in_progress) {
 		kdb_printf("kdb: nested defcmd detected, assuming missing "
 			   "endefcmd\n");
 		kdb_defcmd2("endefcmd", "endefcmd");
 	}
 	if (argc == 0) {
-		int i;
-		for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) {
-			kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name,
-				   s->usage, s->help);
-			for (i = 0; i < s->count; ++i)
-				kdb_printf("%s", s->command[i]);
-			kdb_printf("endefcmd\n");
+		kdbtab_t *kp;
+		struct kdb_subcmd *ks;
+
+		list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+			if (kp->cmd_func == kdb_exec_defcmd) {
+				kdb_printf("defcmd %s \"%s\" \"%s\"\n",
+					   kp->cmd_name, kp->cmd_usage,
+					   kp->cmd_help);
+				list_for_each_entry(ks, &kp->kdb_scmds_head,
+						    list_node)
+					kdb_printf("%s", ks->scmd_name);
+				kdb_printf("endefcmd\n");
+			}
 		}
 		return 0;
 	}
@@ -751,45 +740,42 @@ static int kdb_defcmd(int argc, const char **argv)
 		kdb_printf("Command only available during kdb_init()\n");
 		return KDB_NOTIMP;
 	}
-	defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set),
-				   GFP_KDB);
+	defcmd_set = kzalloc(sizeof(*defcmd_set), GFP_KDB);
 	if (!defcmd_set)
 		goto fail_defcmd;
-	memcpy(defcmd_set, save_defcmd_set,
-	       defcmd_set_count * sizeof(*defcmd_set));
-	s = defcmd_set + defcmd_set_count;
-	memset(s, 0, sizeof(*s));
-	s->usable = true;
-	s->name = kdb_strdup(argv[1], GFP_KDB);
-	if (!s->name)
+
+	defcmd_set->cmd_func = kdb_exec_defcmd;
+	defcmd_set->cmd_minlen = 0;
+	defcmd_set->cmd_flags = KDB_ENABLE_ALWAYS_SAFE;
+	defcmd_set->cmd_name = kdb_strdup(argv[1], GFP_KDB);
+	if (!defcmd_set->cmd_name)
 		goto fail_name;
-	s->usage = kdb_strdup(argv[2], GFP_KDB);
-	if (!s->usage)
+	defcmd_set->cmd_usage = kdb_strdup(argv[2], GFP_KDB);
+	if (!defcmd_set->cmd_usage)
 		goto fail_usage;
-	s->help = kdb_strdup(argv[3], GFP_KDB);
-	if (!s->help)
+	defcmd_set->cmd_help = kdb_strdup(argv[3], GFP_KDB);
+	if (!defcmd_set->cmd_help)
 		goto fail_help;
-	if (s->usage[0] == '"') {
-		strcpy(s->usage, argv[2]+1);
-		s->usage[strlen(s->usage)-1] = '\0';
+	if (defcmd_set->cmd_usage[0] == '"') {
+		strcpy(defcmd_set->cmd_usage, argv[2]+1);
+		defcmd_set->cmd_usage[strlen(defcmd_set->cmd_usage)-1] = '\0';
 	}
-	if (s->help[0] == '"') {
-		strcpy(s->help, argv[3]+1);
-		s->help[strlen(s->help)-1] = '\0';
+	if (defcmd_set->cmd_help[0] == '"') {
+		strcpy(defcmd_set->cmd_help, argv[3]+1);
+		defcmd_set->cmd_help[strlen(defcmd_set->cmd_help)-1] = '\0';
 	}
-	++defcmd_set_count;
+
+	INIT_LIST_HEAD(&defcmd_set->kdb_scmds_head);
 	defcmd_in_progress = true;
-	kfree(save_defcmd_set);
 	return 0;
 fail_help:
-	kfree(s->usage);
+	kfree(defcmd_set->cmd_usage);
 fail_usage:
-	kfree(s->name);
+	kfree(defcmd_set->cmd_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;
 }
 
@@ -804,25 +790,29 @@ static int kdb_defcmd(int argc, const char **argv)
  */
 static int kdb_exec_defcmd(int argc, const char **argv)
 {
-	int i, ret;
-	struct defcmd_set *s;
+	int ret;
+	kdbtab_t *kp;
+	struct kdb_subcmd *ks;
+
 	if (argc != 0)
 		return KDB_ARGCOUNT;
-	for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) {
-		if (strcmp(s->name, argv[0]) == 0)
+
+	list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+		if (strcmp(kp->cmd_name, argv[0]) == 0)
 			break;
 	}
-	if (i == defcmd_set_count) {
+	if (list_entry_is_head(kp, &kdb_cmds_head, list_node)) {
 		kdb_printf("kdb_exec_defcmd: could not find commands for %s\n",
 			   argv[0]);
 		return KDB_NOTIMP;
 	}
-	for (i = 0; i < s->count; ++i) {
-		/* Recursive use of kdb_parse, do not use argv after
-		 * this point */
+	list_for_each_entry(ks, &kp->kdb_scmds_head, list_node) {
+		/*
+		 * Recursive use of kdb_parse, do not use argv after this point.
+		 */
 		argv = NULL;
-		kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]);
-		ret = kdb_parse(s->command[i]);
+		kdb_printf("[%s]kdb> %s\n", kp->cmd_name, ks->scmd_name);
+		ret = kdb_parse(ks->scmd_name);
 		if (ret)
 			return ret;
 	}
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index ec91d7e02334..a8bda278c9c1 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -13,6 +13,7 @@
  */
 
 #include <linux/kgdb.h>
+#include <linux/list.h>
 #include "../debug_core.h"
 
 /* Kernel Debugger Command codes.  Must not overlap with error codes. */
@@ -164,6 +165,11 @@ typedef struct _kdb_bp {
 #ifdef CONFIG_KGDB_KDB
 extern kdb_bp_t kdb_breakpoints[/* KDB_MAXBPT */];
 
+struct kdb_subcmd {
+	char    *scmd_name;		/* Sub-command name */
+	struct  list_head list_node;	/* Sub-command node */
+};
+
 /* The KDB shell command table */
 typedef struct _kdbtab {
 	char    *cmd_name;		/* Command name */
@@ -175,6 +181,7 @@ typedef struct _kdbtab {
 	kdb_cmdflags_t cmd_flags;	/* Command behaviour flags */
 	struct list_head list_node;	/* Command list */
 	bool    is_dynamic;		/* Command table allocation type */
+	struct list_head kdb_scmds_head; /* Sub-commands list */
 } kdbtab_t;
 
 extern void kdb_register_table(kdbtab_t *kp, size_t len);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-03-23  6:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-09 12:17 [PATCH] kdb: Refactor kdb_defcmd implementation Sumit Garg
2021-03-19 17:17 ` Daniel Thompson
2021-03-23  6:13   ` Sumit Garg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).