Add an example host to demonstrate gdbstub

This commit is contained in:
Hamid Rostami 2026-04-15 22:41:54 +01:00
parent 1f7132e1e8
commit faecd6bbef
4 changed files with 2000 additions and 0 deletions

View file

@ -0,0 +1,7 @@
TOPDIR=../..
all:
gcc -Wall -Werror -Wno-error=unused-function -pedantic -std=c99 -O2 -DUVM32_ERROR_STRINGS -DUVM32_MEMORY_SIZE=65536 -DGDBSTUB_ARCH_UVM32 -DGDBSTUB_IMPLEMENTATION -I${TOPDIR}/uvm32 -I${TOPDIR}/common -o host-gdbstub ${TOPDIR}/uvm32/uvm32.c host-gdbstub.c
clean:
rm -f host-gdbstub

View file

@ -0,0 +1,29 @@
# Why?
To debug your guest application. GDB can attach to the host over TCP socket, stdio,
serial connection, etc. In the provided example, it communicate over stdio, however
using `socat` it can be redirected to a TCP socket.
# How to use it
1. Compile a guest application, for example from [apps](../../apps/) directory.
To have a better debugging experience, use `-O0` and `-g3`.
2. Run the host prividing the app binary file. Use the following command to
redirect stdio to a TCP socket:
```
socat -v -x
TCP-LISTEN:1234,reuseaddr \
EXEC:"./host-gdbstub ../../apps/maze/maze.bin"
```
`-v` and `-x` are used to see the traffic in hex.
3. Fire up a `riscv32-elf-gdb` (might be different name on your OS) and give
it the generated elf file from step 1:
`riscv32-elf-gdb -ex 'target remote :1234' -ex 'layout src' maze.elf`
4. Happy debugging. `s`, `si`, `n`, breakpoint, etc should be working :)

1887
hosts/host-gdbstub/gdbstub.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,77 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "uvm32.h"
#include "gdbstub.h"
static uint8_t *read_file(const char* filename, int *len) {
FILE* f = fopen(filename, "rb");
uint8_t *buf = NULL;
if (f == NULL) {
fprintf(stderr, "error: can't open file '%s'.\n", filename);
return NULL;
}
fseek(f, 0, SEEK_END);
size_t file_size = ftell(f);
rewind(f);
if (NULL == (buf = malloc(file_size))) {
fclose(f);
return NULL;
}
size_t result = fread(buf, sizeof(uint8_t), file_size, f);
if (result != file_size) {
fprintf(stderr, "error: while reading file '%s'\n", filename);
free(buf);
fclose(f);
return NULL;
}
fclose(f);
*len = file_size;
return buf;
}
void usage(const char *name) {
fprintf(stderr, "%s filename.bin\n", name);
exit(1);
}
int main(int argc, char *argv[]) {
uvm32_state_t vmst;
const char *rom_filename = NULL;
int romlen = 0;
if (2 == argc) {
rom_filename = argv[1];
} else {
usage(argv[0]);
}
uint8_t *rom = read_file(rom_filename, &romlen);
if (NULL == rom) {
fprintf(stderr,"file read failed!\n");
return 1;
}
uvm32_init(&vmst);
if (!uvm32_load(&vmst, rom, romlen)) {
fprintf(stderr, "load failed!\n");
return 1;
}
/* Attach gdbstub to vmst */
struct gdb_state state;
gdb_sys_init_state(&state, &vmst, NULL);
while(1) {
gdb_main(&state);
}
free(rom);
return 0;
}