Skip to content

Commit ace1b8a

Browse files
committed
Add debug mode using mini-gdbstub submodules
1 parent 304f0af commit ace1b8a

File tree

7 files changed

+147
-1
lines changed

7 files changed

+147
-1
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "riscv-arch-test"]
22
path = tests/riscv-arch-test
33
url = https://github.com/riscv-non-isa/riscv-arch-test
4+
[submodule "mini-gdbstub"]
5+
path = mini-gdbstub
6+
url = https://github.com/RinHizakura/mini-gdbstub.git

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ $(OUT)/emulate.o: CFLAGS += -fno-gcse -fno-crossjumping
5555
endif
5656
endif
5757

58+
GDBSTUB :=
59+
ENABLE_GDBRSP ?= 1
60+
ifeq ("$(ENABLE_GDBRSP)", "1")
61+
CFLAGS += -D ENABLE_GDBRSP
62+
LDFLAGS += -Wl,-rpath="$(CURDIR)/mini-gdbstub" -L./mini-gdbstub -lgdbstub
63+
GDBSTUB += ./mini-gdbstub/libgdbstub.so
64+
$(GDBSTUB):
65+
git submodule update --init mini-gdbstub
66+
$(MAKE) -C mini-gdbstub
67+
$(OUT)/emulate.o: $(GDBSTUB)
68+
endif
69+
70+
# Clear the .DEFAULT_GOAL special variable, so that the following turns
71+
# to the first target after .DEFAULT_GOAL is not set.
72+
.DEFAULT_GOAL :=
73+
5874
all: $(BIN)
5975

6076
OBJS := \

emulate.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,92 @@ static inline bool op_unimp(struct riscv_t *rv, uint32_t insn UNUSED)
16721672
return false;
16731673
}
16741674

1675+
#ifdef ENABLE_GDBRSP
1676+
size_t rv_read_reg(void *args, int regno)
1677+
{
1678+
struct riscv_t *rv = (struct riscv_t *) args;
1679+
1680+
if (regno < 32) {
1681+
return rv_get_reg(rv, regno);
1682+
} else if (regno == 32) {
1683+
return rv_get_pc(rv);
1684+
}
1685+
1686+
return -1;
1687+
}
1688+
1689+
void rv_read_mem(void *args, size_t addr, size_t len, void *val)
1690+
{
1691+
struct riscv_t *rv = (struct riscv_t *) args;
1692+
1693+
for (size_t i = 0; i < len; i++)
1694+
*((uint8_t *) val + i) = rv->io.mem_read_b(rv, addr + i);
1695+
}
1696+
1697+
gdb_action_t rv_cont(void *args)
1698+
{
1699+
struct riscv_t *rv = (struct riscv_t *) args;
1700+
const uint32_t cycles_per_step = 1;
1701+
for (; !rv_has_halted(rv) &&
1702+
rv->PC != rv->bp_addr;) { /* run until the flag is done */
1703+
/* step instructions */
1704+
rv_step(rv, cycles_per_step);
1705+
}
1706+
1707+
return ACT_RESUME;
1708+
}
1709+
1710+
bool rv_set_bp(void *args, size_t addr, bp_type_t type)
1711+
{
1712+
struct riscv_t *rv = (struct riscv_t *) args;
1713+
if (type != BP_SOFTWARE || rv->bp_is_set)
1714+
return false;
1715+
1716+
rv->bp_is_set = true;
1717+
rv->bp_addr = addr;
1718+
return true;
1719+
}
1720+
1721+
bool rv_rm_bp(void *args, size_t addr, bp_type_t type)
1722+
{
1723+
struct riscv_t *rv = (struct riscv_t *) args;
1724+
// It's fine when there's no matching breakpoint, just doing nothing
1725+
if (type != BP_SOFTWARE || !rv->bp_is_set || rv->bp_addr != addr)
1726+
return true;
1727+
1728+
rv->bp_is_set = false;
1729+
rv->bp_addr = 0;
1730+
return true;
1731+
}
1732+
1733+
struct target_ops rv_ops = {
1734+
.read_reg = rv_read_reg,
1735+
.read_mem = rv_read_mem,
1736+
.cont = rv_cont,
1737+
.stepi = NULL,
1738+
.set_bp = rv_set_bp,
1739+
.rm_bp = rv_rm_bp,
1740+
};
1741+
1742+
void rv_debug(struct riscv_t *rv)
1743+
{
1744+
if (!gdbstub_init(&rv->gdbstub, &rv_ops,
1745+
(arch_info_t){
1746+
.reg_num = 33,
1747+
.reg_byte = 4,
1748+
.target_desc = TARGET_RV32,
1749+
},
1750+
"127.0.0.1:1234")) {
1751+
return;
1752+
}
1753+
1754+
if (!gdbstub_run(&rv->gdbstub, (void *) rv)) {
1755+
return;
1756+
}
1757+
gdbstub_close(&rv->gdbstub);
1758+
}
1759+
#endif /* ENABLE_GDBRSP */
1760+
16751761
void rv_step(struct riscv_t *rv, int32_t cycles)
16761762
{
16771763
assert(rv);

main.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
/* enable program trace mode */
99
static bool opt_trace = false;
10+
#ifdef ENABLE_GDBRSP
11+
/* enable program debug mode */
12+
static bool opt_debug = false;
13+
#endif
1014

1115
/* RISCV arch-test */
1216
static bool opt_arch_test = false;
@@ -60,6 +64,13 @@ static void run_and_trace(struct riscv_t *rv, elf_t *elf)
6064
}
6165
}
6266

67+
#ifdef ENABLE_GDBRSP
68+
static void run_debug(struct riscv_t *rv)
69+
{
70+
rv_debug(rv);
71+
}
72+
#endif
73+
6374
static void run(struct riscv_t *rv)
6475
{
6576
const uint32_t cycles_per_step = 100;
@@ -94,6 +105,12 @@ static bool parse_args(int argc, char **args)
94105
opt_trace = true;
95106
continue;
96107
}
108+
#ifdef ENABLE_GDBRSP
109+
if (!strcmp(arg, "--debug")) {
110+
opt_debug = true;
111+
continue;
112+
}
113+
#endif
97114
if (!strcmp(arg, "--arch-test")) {
98115
opt_arch_test = true;
99116
if (i + 1 >= argc) {
@@ -199,7 +216,13 @@ int main(int argc, char **args)
199216
/* run based on the specified mode */
200217
if (opt_trace) {
201218
run_and_trace(rv, elf);
202-
} else {
219+
}
220+
#ifdef ENABLE_GDBRSP
221+
else if (opt_debug) {
222+
run_debug(rv);
223+
}
224+
#endif
225+
else {
203226
run(rv);
204227
}
205228

mini-gdbstub

Submodule mini-gdbstub added at dd39ca8

riscv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ void rv_delete(struct riscv_t *);
9999
/* reset the RISC-V processor */
100100
void rv_reset(struct riscv_t *, riscv_word_t pc);
101101

102+
#ifdef ENABLE_GDBRSP
103+
/* Run the RISCV-emulator in debug mode */
104+
void rv_debug(struct riscv_t *rv);
105+
#endif
106+
102107
/* step the RISC-V emulator */
103108
void rv_step(struct riscv_t *, int32_t cycles);
104109

riscv_private.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#pragma once
22
#include <stdbool.h>
33

4+
#ifdef ENABLE_GDBRSP
5+
#include "mini-gdbstub/include/gdbstub.h"
6+
#endif
47
#include "riscv.h"
58

69
#define RV_NUM_REGS 32
@@ -138,6 +141,15 @@ struct riscv_t {
138141
/* user provided data */
139142
riscv_user_t userdata;
140143

144+
#ifdef ENABLE_GDBRSP
145+
/* gdbstub instance */
146+
gdbstub_t gdbstub;
147+
148+
/* GDB instruction breakpoint */
149+
bool bp_is_set;
150+
size_t bp_addr;
151+
#endif
152+
141153
#ifdef ENABLE_RV32F
142154
/* float registers */
143155
union {

0 commit comments

Comments
 (0)