From: Marc Rittinghaus Date: Mon, 19 Aug 2024 08:58:03 +0000 (+0200) Subject: lib/ukdebug: Add continue and single step packets to gdb stub X-Git-Tag: RELEASE-0.18.0~95 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=6adc4a91843fbe2869348153bec460c4ddce1996;p=unikraft%2Funikraft.git lib/ukdebug: Add continue and single step packets to gdb stub These packets implement the "single step" and "continue" operations in gdb. Checkpatch-Ignore: UNNECESSARY_PARENTHESES Signed-off-by: Marc Rittinghaus Reviewed-by: Michalis Pappas Reviewed-by: Simon Kuenzer Approved-by: Simon Kuenzer GitHub-Closes: #1479 --- diff --git a/lib/ukdebug/Makefile.uk b/lib/ukdebug/Makefile.uk index fcaf988b2..b15ffbf3c 100644 --- a/lib/ukdebug/Makefile.uk +++ b/lib/ukdebug/Makefile.uk @@ -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__ diff --git a/lib/ukdebug/arch/arm64/gdbsup.c b/lib/ukdebug/arch/arm64/gdbsup.c index e9f3fb926..8d339deba 100644 --- a/lib/ukdebug/arch/arm64/gdbsup.c +++ b/lib/ukdebug/arch/arm64/gdbsup.c @@ -5,7 +5,6 @@ * You may not use this file except in compliance with the License. */ -#include "gdbsup.h" #include "../../gdbstub.h" #include diff --git a/lib/ukdebug/gdbstub.c b/lib/ukdebug/gdbstub.c index 0c4e4204a..653083758 100644 --- a/lib/ukdebug/gdbstub.c +++ b/lib/ukdebug/gdbstub.c @@ -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) / \