]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/ukdebug: Add continue and single step packets to gdb stub
authorMarc Rittinghaus <marc.rittinghaus@unikraft.io>
Mon, 19 Aug 2024 08:58:03 +0000 (10:58 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Fri, 13 Sep 2024 20:51:57 +0000 (20:51 +0000)
These packets implement the "single step" and "continue" operations
in gdb.

Checkpatch-Ignore: UNNECESSARY_PARENTHESES
Signed-off-by: Marc Rittinghaus <marc.rittinghaus@unikraft.io>
Reviewed-by: Michalis Pappas <michalis@unikraft.io>
Reviewed-by: Simon Kuenzer <simon@unikraft.io>
Approved-by: Simon Kuenzer <simon@unikraft.io>
GitHub-Closes: #1479

lib/ukdebug/Makefile.uk
lib/ukdebug/arch/arm64/gdbsup.c
lib/ukdebug/gdbstub.c

index fcaf988b248f988e4f733ef43099e2b473f7b46b..b15ffbf3c54f622f45c397b2a2dd52c1c5684d32 100644 (file)
@@ -3,9 +3,6 @@ $(eval $(call addlib_s,libukdebug,$(CONFIG_LIBUKDEBUG)))
 CINCLUDES-$(CONFIG_LIBUKDEBUG)   += -I$(LIBUKDEBUG_BASE)/include
 CXXINCLUDES-$(CONFIG_LIBUKDEBUG) += -I$(LIBUKDEBUG_BASE)/include
 
-LIBUKDEBUG_ASINCLUDES-y += -I$(LIBUKDEBUG_BASE)/arch/$(CONFIG_UK_ARCH)
-LIBUKDEBUG_CINCLUDES-y  += -I$(LIBUKDEBUG_BASE)/arch/$(CONFIG_UK_ARCH)
-
 LIBUKDEBUG_CFLAGS-y   += -D__IN_LIBUKDEBUG__
 LIBUKDEBUG_CXXFLAGS-y += -D__IN_LIBUKDEBUG__
 
index e9f3fb92669b66952e2bed85994dcc6be86b0cab..8d339deba2a652f174bfa5531b98e83f651074ff 100644 (file)
@@ -5,7 +5,6 @@
  * You may not use this file except in compliance with the License.
  */
 
-#include "gdbsup.h"
 #include "../../gdbstub.h"
 
 #include <uk/arch/traps.h>
index 0c4e4204ac08bd32747a45b2ccf2aecc30783950..653083758873f6b964fb36275a0628928f953be8 100644 (file)
@@ -110,6 +110,43 @@ static int gdb_hex2int(char hex)
        return -EINVAL;
 }
 
+static unsigned long gdb_hex2ulong(const char *buf, __sz buf_len, char **endptr)
+{
+       unsigned long val = 0;
+       int i;
+
+       /* Skip any whitespace */
+       while ((buf_len > 0) && (*buf == ' ')) {
+               buf++;
+               buf_len--;
+       }
+
+       /* Skip hex prefix if present */
+       if ((buf_len >= 2) && (*buf == '0') &&
+           ((*(buf + 1) == 'x') || (*(buf + 1) == 'X'))) {
+               buf += 2;
+               buf_len -= 2;
+       }
+
+       /* Parse hexadecimal integer */
+       while ((buf_len > 0) && (val < __UL_MAX)) {
+               i = gdb_hex2int(*buf);
+               if (i < 0)
+                       break;
+
+               val <<= 4;
+               val |= i;
+
+               buf++;
+               buf_len--;
+       }
+
+       if (endptr)
+               *endptr = DECONST(char *, buf);
+
+       return val;
+}
+
 static __ssz gdb_hex2mem(char *mem, __sz mem_len, const char *hex, __sz hex_len)
 {
        __sz l = hex_len;
@@ -309,8 +346,102 @@ static int gdb_handle_stop_reason(char *buf __unused, __sz buf_len __unused,
        return 0;
 }
 
+/* c/s [addr] */
+static int gdb_handle_step_cont(char *buf, __sz buf_len,
+                               struct gdb_excpt_ctx *g)
+{
+       unsigned long addr;
+       char *buf_end = buf + buf_len;
+
+       if (buf != buf_end) {
+               addr = gdb_hex2ulong(buf, buf_len, &buf);
+               if (buf != buf_end) {
+                       /* Send E22. EINVAL */
+                       GDB_CHECK(gdb_send_error_packet(EINVAL));
+                       return 0;
+               }
+
+               ukarch_regs_set_pc(addr, g->regs);
+       }
+
+       return 1;
+}
+
+/* C/S sig[;addr] */
+static int gdb_handle_step_cont_sig(char *buf, __sz buf_len,
+                                   struct gdb_excpt_ctx *g)
+{
+       unsigned long addr;
+       char *buf_end = buf + buf_len;
+
+       /* Just ignore the signal */
+       gdb_hex2ulong(buf, buf_end - buf, &buf);
+       if (buf != buf_end) {
+               if (unlikely(*buf++ != ';')) {
+                       /* Send E22. EINVAL */
+                       GDB_CHECK(gdb_send_error_packet(EINVAL));
+                       return 0;
+               }
+
+               addr = gdb_hex2ulong(buf, buf_len, &buf);
+               if (unlikely(buf != buf_end)) {
+                       /* Send E22. EINVAL */
+                       GDB_CHECK(gdb_send_error_packet(EINVAL));
+                       return 0;
+               }
+
+               ukarch_regs_set_pc(addr, g->regs);
+       }
+
+       return 1;
+}
+
+/* c[addr] */
+static int gdb_handle_continue(char *buf, __sz buf_len,
+                              struct gdb_excpt_ctx *g)
+{
+       int r;
+
+       return (((r = gdb_handle_step_cont(buf, buf_len, g)) <= 0) ?
+                       r : GDB_DBG_CONT);
+}
+
+/* C sig[;addr] */
+static int gdb_handle_continue_sig(char *buf, __sz buf_len,
+                                  struct gdb_excpt_ctx *g)
+{
+       int r;
+
+       return (((r = gdb_handle_step_cont_sig(buf, buf_len, g)) <= 0) ?
+                       r : GDB_DBG_CONT);
+}
+
+/* s[addr] */
+static int gdb_handle_step(char *buf, __sz buf_len,
+                          struct gdb_excpt_ctx *g)
+{
+       int r;
+
+       return (((r = gdb_handle_step_cont(buf, buf_len, g)) <= 0) ?
+                       r : GDB_DBG_STEP);
+}
+
+/* S sig[;addr] */
+static int gdb_handle_step_sig(char *buf, __sz buf_len,
+                              struct gdb_excpt_ctx *g)
+{
+       int r;
+
+       return (((r = gdb_handle_step_cont_sig(buf, buf_len, g)) <= 0) ?
+                       r : GDB_DBG_STEP);
+}
+
 static struct gdb_cmd_table_entry gdb_cmd_table[] = {
-       { gdb_handle_stop_reason, GDB_STR_A_LEN("?") }
+       { gdb_handle_stop_reason, GDB_STR_A_LEN("?") },
+       { gdb_handle_continue, GDB_STR_A_LEN("c") },
+       { gdb_handle_continue_sig, GDB_STR_A_LEN("C") },
+       { gdb_handle_step, GDB_STR_A_LEN("s") },
+       { gdb_handle_step_sig, GDB_STR_A_LEN("S") }
 };
 
 #define NUM_GDB_CMDS (sizeof(gdb_cmd_table) / \