All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 01/20] gdbstub: Add infrastructure to parse cmd packets
@ 2019-04-24 18:45 Jon Doron
  2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 02/20] gdbstub: Implement deatch (D pkt) with new infra Jon Doron
                   ` (18 more replies)
  0 siblings, 19 replies; 20+ messages in thread
From: Jon Doron @ 2019-04-24 18:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jon Doron

Signed-off-by: Jon Doron <arilou@gmail.com>
---
 gdbstub.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 209 insertions(+)

diff --git a/gdbstub.c b/gdbstub.c
index d54abd17cc..64680722fc 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1268,6 +1268,215 @@ out:
     return res;
 }
 
+typedef union GdbCmdVariant {
+    const char *data;
+    uint8_t opcode;
+    unsigned long val_ul;
+    unsigned long long val_ull;
+    struct {
+        GDBThreadIdKind kind;
+        uint32_t pid;
+        uint32_t tid;
+    } thread_id;
+} GdbCmdVariant;
+
+static const char *cmd_next_param(const char *param, const char delimiter)
+{
+    const char *delim;
+    static char all_delimiters[] = ",;:=";
+    static char no_delimiter[] = "\0";
+    char curr_delimiters[2] = {0};
+    const char *delimiters;
+
+    if (delimiter == '?') {
+        delimiters = all_delimiters;
+    } else if (delimiter == '0') {
+        delimiters = no_delimiter;
+    } else if (delimiter == '.' && *param) {
+        return param + 1;
+    } else {
+        curr_delimiters[0] = delimiter;
+        delimiters = curr_delimiters;
+    }
+
+    while (*param) {
+        delim = delimiters;
+        while (*delim) {
+            if (*param == *delim) {
+                return param + 1;
+            }
+            delim++;
+        }
+        param++;
+    }
+
+    return param;
+}
+
+static int cmd_parse_params(const char *data, const char *schema,
+                            GdbCmdVariant *params, int *num_params)
+{
+    int curr_param;
+    const char *curr_schema, *curr_data;
+
+    *num_params = 0;
+
+    if (!schema) {
+        return 0;
+    }
+
+    curr_schema = schema;
+    curr_param = 0;
+    curr_data = data;
+    while (curr_schema[0] && curr_schema[1] && *curr_data) {
+        switch (curr_schema[0]) {
+        case 'l':
+            if (qemu_strtoul(curr_data, &curr_data, 16,
+                             &params[curr_param].val_ul)) {
+                return -EINVAL;
+            }
+            curr_param++;
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        case 'L':
+            if (qemu_strtou64(curr_data, &curr_data, 16,
+                              (uint64_t *)&params[curr_param].val_ull)) {
+                return -EINVAL;
+            }
+            curr_param++;
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        case 's':
+            params[curr_param].data = curr_data;
+            curr_param++;
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        case 'o':
+            params[curr_param].opcode = *(uint8_t *)curr_data;
+            curr_param++;
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        case 't':
+            params[curr_param].thread_id.kind =
+                read_thread_id(curr_data, &curr_data,
+                               &params[curr_param].thread_id.pid,
+                               &params[curr_param].thread_id.tid);
+            curr_param++;
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        case '?':
+            curr_data = cmd_next_param(curr_data, curr_schema[1]);
+            break;
+        default:
+            return -EINVAL;
+        }
+        curr_schema += 2;
+    }
+
+    *num_params = curr_param;
+    return 0;
+}
+
+typedef struct GdbCmdContext {
+    GDBState *s;
+    GdbCmdVariant *params;
+    int num_params;
+    uint8_t mem_buf[MAX_PACKET_LENGTH];
+    char str_buf[MAX_PACKET_LENGTH + 1];
+} GdbCmdContext;
+
+typedef void (*GdbCmdHandler)(GdbCmdContext *gdb_ctx, void *user_ctx);
+
+/*
+ * cmd_startswith -> cmd is compared using startswith
+ * cmd_full_match -> cmd is compared using strcmp
+ *
+ *
+ * schema definitions:
+ * Each schema parameter entry consists of 2 chars,
+ * the first char represents the parameter type handling
+ * the second char represents the delimiter for the next parameter
+ *
+ * Currently supported schema types:
+ * 'l' -> unsigned long (stored in .val_ul)
+ * 'L' -> unsigned long long (stored in .val_ull)
+ * 's' -> string (stored in .data)
+ * 'o' -> single char (stored in .opcode)
+ * 't' -> thread id (stored in .thread_id)
+ * '?' -> skip according to delimiter
+ *
+ * Currently supported delimiters:
+ * '?' -> Stop at any delimiter (",;:=\0")
+ * '0' -> Stop at "\0"
+ * '.' -> Skip 1 char unless reached "\0"
+ * Any other value is treated as the delimiter value itself
+ */
+typedef struct GdbCmdParseEntry {
+    GdbCmdHandler handler;
+    const char *cmd;
+    union {
+        int flags;
+        struct {
+            int cmd_startswith:1;
+            int cmd_full_match:1;
+        };
+    };
+    const char *schema;
+} GdbCmdParseEntry;
+
+static inline int startswith(const char *string, const char *pattern)
+{
+  return !strncmp(string, pattern, strlen(pattern));
+}
+
+__attribute__((unused)) static int process_string_cmd(
+        GDBState *s, void *user_ctx, const char *data,
+        GdbCmdParseEntry *cmds, int num_cmds);
+
+static int process_string_cmd(GDBState *s, void *user_ctx, const char *data,
+                              GdbCmdParseEntry *cmds, int num_cmds)
+{
+    int i, schema_len, max_num_params;
+    GdbCmdContext gdb_ctx;
+
+    if (!cmds) {
+        return -1;
+    }
+
+    for (i = 0; i < num_cmds; i++) {
+        if (!cmds[i].handler || !cmds[i].cmd ||
+            (cmds[i].cmd_startswith && !startswith(data, cmds[i].cmd)) ||
+            (cmds[i].cmd_full_match && strcmp(data, cmds[i].cmd))) {
+            continue;
+        }
+
+        max_num_params = 0;
+        if (cmds[i].schema) {
+            schema_len = strlen(cmds[i].schema);
+            if (schema_len % 2) {
+                return -2;
+            }
+
+            max_num_params = schema_len / 2;
+        }
+
+        gdb_ctx.params =
+            (GdbCmdVariant *)alloca(sizeof(*gdb_ctx.params) * max_num_params);
+        memset(gdb_ctx.params, 0, sizeof(*gdb_ctx.params) * max_num_params);
+
+        if (cmd_parse_params(&data[strlen(cmds[i].cmd)], cmds[i].schema,
+                             gdb_ctx.params, &gdb_ctx.num_params)) {
+            return -1;
+        }
+
+        gdb_ctx.s = s;
+        cmds[i].handler(&gdb_ctx, user_ctx);
+        return 0;
+    }
+
+    return -1;
+}
+
 static int gdb_handle_packet(GDBState *s, const char *line_buf)
 {
     CPUState *cpu;
-- 
2.20.1

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

end of thread, other threads:[~2019-04-24 18:58 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-24 18:45 [Qemu-devel] [PATCH v4 01/20] gdbstub: Add infrastructure to parse cmd packets Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 02/20] gdbstub: Implement deatch (D pkt) with new infra Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 03/20] gdbstub: Implement thread_alive (T " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 04/20] gdbstub: Implement continue (c " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 05/20] gdbstub: Implement continue with signal (C " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 06/20] gdbstub: Implement set_thread (H " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 07/20] gdbstub: Implement insert breakpoint (Z " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 08/20] gdbstub: Implement remove breakpoint (z " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 09/20] gdbstub: Implement set register (P " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 10/20] gdbstub: Implement get register (p " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 11/20] gdbstub: Implement write memory (M " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 12/20] gdbstub: Implement read memory (m " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 13/20] gdbstub: Implement write all registers (G " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 14/20] gdbstub: Implement read all registers (g " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 15/20] gdbstub: Implement file io (F " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 16/20] gdbstub: Implement step (s " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 17/20] gdbstub: Implement v commands " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 18/20] gdbstub: Implement generic query (q pkt) " Jon Doron
2019-04-24 18:45 ` [Qemu-devel] [PATCH v4 19/20] gdbstub: Implement generic set (Q " Jon Doron
2019-04-24 18:46 ` [Qemu-devel] [PATCH v4 20/20] gdbstub: Refactor parse handle packet to work with a static array Jon Doron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.