Switch to use a linked list instead of dynamic array which makes
allocation of kdb macro and traversing the kdb macro commands list
simpler.

Also, rename defcmd_set struct to kdb_macro_t struct as it sounds more
appropriate given its purpose. Along with this directly embed kdbtab_t
struct instead of custom command fields in kdb_macro_t struct as its now
possible to register pre-allocated kdb commands via kdb_register_table().

Suggested-by: Daniel Thompson <daniel.thomp...@linaro.org>
Signed-off-by: Sumit Garg <sumit.g...@linaro.org>
---

Changes in v2:
- Define new structs: kdb_macro_t and kdb_macro_cmd_t instead of
  modifying existing kdb command struct and struct kdb_subcmd.
- Reword commit message.

 kernel/debug/kdb/kdb_main.c | 158 +++++++++++++++++++-----------------
 1 file changed, 83 insertions(+), 75 deletions(-)

diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 9d69169582c6..2f2c0e3b39a9 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -678,16 +678,17 @@ 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;
+struct kdb_macro_t {
+       kdbtab_t cmd;                   /* Macro command name */
+       struct list_head commands;      /* Associated command list */
 };
-static struct defcmd_set *defcmd_set;
-static int defcmd_set_count;
+
+struct kdb_macro_cmd_t {
+       char *cmd;                      /* Command name */
+       struct list_head list_node;     /* Command list node */
+};
+
+static struct kdb_macro_t *kdb_macro;
 static bool defcmd_in_progress;
 
 /* Forward references */
@@ -695,53 +696,56 @@ 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_macro_cmd_t *kmc;
+
+       if (!kdb_macro)
+               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(&kdb_macro->commands))
+                       kdb_register_table(&kdb_macro->cmd, 1);
                return 0;
        }
-       if (!s->usable)
-               return KDB_NOTIMP;
-       s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB);
-       if (!s->command) {
-               kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
+
+       kmc = kmalloc(sizeof(*kmc), GFP_KDB);
+       if (!kmc) {
+               kdb_printf("Could not allocate new kdb macro command: %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);
+
+       kmc->cmd = kdb_strdup(cmdstr, GFP_KDB);
+       list_add_tail(&kmc->list_node, &kdb_macro->commands);
+
        return 0;
 }
 
 static int kdb_defcmd(int argc, const char **argv)
 {
-       struct defcmd_set *save_defcmd_set = defcmd_set, *s;
+       kdbtab_t *mp;
+
        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_macro_t *kmp;
+               struct kdb_macro_cmd_t *kmc;
+
+               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);
+                               kmp = container_of(kp, struct kdb_macro_t, cmd);
+                               list_for_each_entry(kmc, &kmp->commands,
+                                                   list_node)
+                                       kdb_printf("%s", kmc->cmd);
+                               kdb_printf("endefcmd\n");
+                       }
                }
                return 0;
        }
@@ -751,45 +755,43 @@ 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);
-       if (!defcmd_set)
+       kdb_macro = kzalloc(sizeof(*kdb_macro), GFP_KDB);
+       if (!kdb_macro)
                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)
+       mp = &kdb_macro->cmd;
+
+       mp->cmd_func = kdb_exec_defcmd;
+       mp->cmd_minlen = 0;
+       mp->cmd_flags = KDB_ENABLE_ALWAYS_SAFE;
+       mp->cmd_name = kdb_strdup(argv[1], GFP_KDB);
+       if (!mp->cmd_name)
                goto fail_name;
-       s->usage = kdb_strdup(argv[2], GFP_KDB);
-       if (!s->usage)
+       mp->cmd_usage = kdb_strdup(argv[2], GFP_KDB);
+       if (!mp->cmd_usage)
                goto fail_usage;
-       s->help = kdb_strdup(argv[3], GFP_KDB);
-       if (!s->help)
+       mp->cmd_help = kdb_strdup(argv[3], GFP_KDB);
+       if (!mp->cmd_help)
                goto fail_help;
-       if (s->usage[0] == '"') {
-               strcpy(s->usage, argv[2]+1);
-               s->usage[strlen(s->usage)-1] = '\0';
+       if (mp->cmd_usage[0] == '"') {
+               strcpy(mp->cmd_usage, argv[2]+1);
+               mp->cmd_usage[strlen(mp->cmd_usage)-1] = '\0';
        }
-       if (s->help[0] == '"') {
-               strcpy(s->help, argv[3]+1);
-               s->help[strlen(s->help)-1] = '\0';
+       if (mp->cmd_help[0] == '"') {
+               strcpy(mp->cmd_help, argv[3]+1);
+               mp->cmd_help[strlen(mp->cmd_help)-1] = '\0';
        }
-       ++defcmd_set_count;
+
+       INIT_LIST_HEAD(&kdb_macro->commands);
        defcmd_in_progress = true;
-       kfree(save_defcmd_set);
        return 0;
 fail_help:
-       kfree(s->usage);
+       kfree(mp->cmd_usage);
 fail_usage:
-       kfree(s->name);
+       kfree(mp->cmd_name);
 fail_name:
-       kfree(defcmd_set);
+       kfree(kdb_macro);
 fail_defcmd:
-       kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
-       defcmd_set = save_defcmd_set;
+       kdb_printf("Could not allocate new kdb_macro entry for %s\n", argv[1]);
        return KDB_NOTIMP;
 }
 
@@ -804,25 +806,31 @@ 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_macro_t *kmp;
+       struct kdb_macro_cmd_t *kmc;
+
        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 */
+       kmp = container_of(kp, struct kdb_macro_t, cmd);
+       list_for_each_entry(kmc, &kmp->commands, 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", kmp->cmd.cmd_name, kmc->cmd);
+               ret = kdb_parse(kmc->cmd);
                if (ret)
                        return ret;
        }
-- 
2.25.1



_______________________________________________
Kgdb-bugreport mailing list
Kgdb-bugreport@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport

Reply via email to