Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions apps/starry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,24 @@ Stress configs are available through explicit QEMU config variants; see
## GDB Smoke

The `gdb-smoke` case is a RISC-V QEMU app workflow that prepares a temporary
rootfs overlay with GDB, GDBServer, and two tiny target programs.
rootfs overlay with GDB, GDBServer, and tiny debugger smoke targets.

```bash
cargo xtask starry app run -t gdb-smoke --arch riscv64
cargo xtask starry app run -t gdb-smoke --arch riscv64 \
cargo xtask starry app qemu -t gdb-smoke --arch riscv64
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver.toml
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-threads.toml
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-stress.toml
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver-manual.toml
```

When using the long-lived Docker container for a `*-manual.toml` entry, run the
same command through `docker exec -it tgoskits-dev ...` so the QEMU serial
console stays interactive.

## MariaDB

The `mariadb` case is a QEMU app workflow that installs MariaDB in the guest,
Expand Down
207 changes: 207 additions & 0 deletions apps/starry/gdb-smoke/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
# StarryOS GDB Smoke

This app prepares a RISC-V Alpine rootfs overlay with guest `gdb`, `gdbserver`,
and tiny target programs for StarryOS user-space debugger smoke testing.

## Batch Native GDB Smoke

Use this command for the automated native GDB batch smoke:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64
```

The batch script runs:

```gdb
break native_marker
run
bt
info proc mappings
info files
info auxv
shell pid="$(pidof gdb-native-smoke-target)" && cat "/proc/$pid/status"
info registers
x/4gx $sp
stepi
continue
```

Success requires all `GDB_NATIVE_*` markers from
`native/gdb-native-smoke.gdb`.

## Manual Native GDB Demo

Use this entry when you want an interactive StarryOS shell:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-manual.toml
```

When running through the long-lived Docker container, keep stdin and a TTY
attached:

```bash
docker exec -it tgoskits-dev cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-manual.toml
```

This keeps QEMU's serial console interactive inside Docker. Use `Ctrl+A`, then
`x`, to leave the QEMU console after the manual demo.

Inside StarryOS:

```bash
gdb /usr/bin/gdb-native-smoke-target
```

This starts the guest-side GDB and loads symbols for the native smoke target.

Inside GDB:

```gdb
break native_marker
run
bt
info registers
stepi
continue
quit
```

These commands set a breakpoint, run to it, print a backtrace and registers,
single-step once, then continue the target to normal exit.

The native target uses a clear call chain:

```text
main -> demo_entry -> demo_worker -> native_marker
```

## Native Thread GDB Smoke

Use this command for the native GDB thread smoke:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-threads.toml
```

The thread script enables GDB's multi-thread scheduling, breaks on
`thread_marker`, runs `info threads`, lists `/proc/<pid>/task`, prints a
backtrace, deletes the breakpoint, and continues the target to normal exit.

## GDBServer Smoke

Use this command for the guest-internal gdbserver smoke:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver.toml
```

The default gdbserver script connects to `127.0.0.1:1234`, breaks on
`compute_value`, prints a backtrace, deletes the breakpoint, and continues the
remote target.

Remote pthread gdbserver coverage is opt-in because it is slower and exercises
the heavier clone/thread event path:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver-debug.toml
```

Set `GDBSERVER_SMOKE_SERVER_DEBUG=1` in the QEMU config when gdbserver's own
debug trace is needed for a focused investigation.

## GDB Stress

Use this opt-in entry for the heavier ptrace/GDB stress path:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-stress.toml
```

This stress target exercises a multi-threaded tracee with clone events, a
software breakpoint written through `/proc/<pid>/mem`, register access,
single-step, and delayed tracer scheduling. It is intentionally kept out of the
default batch smoke and remote CI paths.

## Host-To-Guest Remote GDB Demo

Use this entry when you want the host to connect to guest `gdbserver` through
QEMU user-network port forwarding:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver-manual.toml
```

When running through the long-lived Docker container, keep stdin and a TTY
attached:

```bash
docker exec -it tgoskits-dev cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver-manual.toml
```

This manual config keeps the guest shell open and forwards host TCP port 1234 to
guest TCP port 1234.

Inside StarryOS, start `gdbserver` and leave it waiting for the host GDB:

```bash
gdbserver 0.0.0.0:1234 /usr/bin/gdbserver-smoke-target
```

`0.0.0.0:1234` is required for the QEMU host-forwarded connection. The command
blocks until the host GDB connects.

On the host side, use the copied symbol file produced by `prebuild.sh` and keep
GDB interactive:

```bash
gdb-multiarch -q -x apps/starry/gdb-smoke/gdbserver/host-manual.gdb \
target/gdb-smoke-host/gdbserver-smoke-target
```

`host-manual.gdb` sets the riscv64 remote debugging defaults and connects to
`:1234`, but leaves you at the GDB prompt for manual commands.

Inside host GDB:

```gdb
break compute_value
continue
bt
info registers
detach
quit
```

These commands prove host-to-guest remote debugging: insert a breakpoint in the
guest process, continue to it, inspect stack/registers, then detach cleanly so
the guest target can finish.

For the reproducible host-to-guest batch demo, start the guest-side
`gdbserver` with:

```bash
cargo xtask starry app qemu -t gdb-smoke --arch riscv64 \
--qemu-config qemu-riscv64-gdbserver-host.toml
```

This automatic config starts guest `gdbserver` for you and is intended for
repeatable logs rather than manual interaction.

Then run the batch host script:

```bash
gdb-multiarch -q -batch -x apps/starry/gdb-smoke/gdbserver/host-remote.gdb \
target/gdb-smoke-host/gdbserver-smoke-target
```

`-batch` runs the scripted host GDB flow and exits after the marker output.
8 changes: 8 additions & 0 deletions apps/starry/gdb-smoke/gdbserver/gdbserver-smoke.gdb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ set debuginfod enabled off
set sysroot /
set solib-search-path /lib:/usr/lib
set remotetimeout 10
set remote hostio-open-packet off
set remote hostio-pread-packet off
target remote 127.0.0.1:1234
break compute_value
continue
bt
echo GDBSERVER_BREAKPOINT_DONE\n
delete breakpoints
continue
echo GDBSERVER_CONTINUE_DONE\n
quit
84 changes: 63 additions & 21 deletions apps/starry/gdb-smoke/gdbserver/gdbserver-smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,76 @@
set -eu

log=/tmp/gdbserver-smoke.log
rm -f "$log"
gdb_timeout_seconds=${GDBSERVER_SMOKE_TIMEOUT:-90}

/usr/bin/gdbserver 0.0.0.0:1234 /usr/bin/gdbserver-smoke-target >"$log" 2>&1 &
server_pid=$!
trap 'kill "$server_pid" 2>/dev/null || true' EXIT
run_gdb_batch() {
script=$1
target=$2

listening=0
for _ in 1 2 3 4 5 6 7 8 9 10; do
if grep -q "Listening on port 1234" "$log"; then
listening=1
break
set -- /usr/bin/gdb -q -batch
if [ "${GDBSERVER_SMOKE_GDB_DEBUG:-0}" = 1 ]; then
set -- "$@" -ex "set debug remote 1" -ex "set debug infrun 1"
fi
sleep 1
done
set -- "$@" -x "$script" "$target"

cat "$log"
if [ "$listening" -ne 1 ]; then
echo "FAIL: gdbserver did not start listening"
exit 1
fi
if command -v timeout >/dev/null 2>&1; then
timeout -s KILL "$gdb_timeout_seconds" "$@"
else
"$@"
fi
}

/usr/bin/gdb -q -batch -x /usr/bin/gdbserver-smoke.gdb /usr/bin/gdbserver-smoke-target
run_remote_smoke() {
target=$1
script=$2

echo "GDBSERVER_PHASE_START target=$target script=$script"
rm -f "$log"
set -- /usr/bin/gdbserver
if [ "${GDBSERVER_SMOKE_SERVER_DEBUG:-0}" = 1 ]; then
set -- "$@" --debug
fi
set -- "$@" 0.0.0.0:1234 "$target"
"$@" >"$log" 2>&1 &
server_pid=$!
trap 'kill "$server_pid" 2>/dev/null || true' EXIT

listening=0
for _ in 1 2 3 4 5 6 7 8 9 10; do
if grep -q "Listening on port 1234" "$log"; then
listening=1
break
fi
sleep 1
done

if ! wait "$server_pid"; then
cat "$log"
exit 1
if [ "$listening" -ne 1 ]; then
echo "FAIL: gdbserver did not start listening for $target"
exit 1
fi

if ! run_gdb_batch "$script" "$target"; then
echo "FAIL: gdb batch failed for $target with $script"
cat "$log"
exit 1
fi

if ! wait "$server_pid"; then
cat "$log"
exit 1
fi
trap - EXIT

cat "$log"
echo "GDBSERVER_PHASE_DONE target=$target"
}

run_remote_smoke /usr/bin/gdbserver-smoke-target /usr/bin/gdbserver-smoke.gdb
if [ "${GDBSERVER_SMOKE_THREADS:-0}" = 1 ]; then
run_remote_smoke /usr/bin/gdb-native-thread-target /usr/bin/gdbserver-threads.gdb
else
echo "GDBSERVER_THREADS_SKIPPED"
fi
trap - EXIT

cat "$log"
echo GDBSERVER_SMOKE_DONE
27 changes: 27 additions & 0 deletions apps/starry/gdb-smoke/gdbserver/gdbserver-threads.gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
set pagination off
set confirm off
set debuginfod enabled off
set sysroot /
set solib-search-path /lib:/usr/lib
set remotetimeout 10
set remote hostio-open-packet off
set remote hostio-pread-packet off
target remote 127.0.0.1:1234
echo GDBSERVER_THREADS_CONNECTED\n
break thread_marker
echo GDBSERVER_THREADS_BREAKPOINT_SET\n
info threads
echo GDBSERVER_THREADS_INITIAL_LIST_DONE\n
continue
echo GDBSERVER_THREADS_BREAKPOINT_HIT\n
info threads
echo GDBSERVER_THREADS_LIST_DONE\n
bt
echo GDBSERVER_THREADS_BT_DONE\n
delete breakpoints
echo GDBSERVER_THREADS_BREAKPOINTS_DELETED\n
continue
echo GDBSERVER_THREADS_PENDING_TRAP_CONSUMED\n
continue
echo GDBSERVER_THREADS_CONTINUE_DONE\n
quit
11 changes: 11 additions & 0 deletions apps/starry/gdb-smoke/gdbserver/host-manual.gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set pagination off
set confirm off
set debuginfod enabled off
set architecture riscv:rv64
set sysroot /
set solib-search-path /lib:/usr/lib
set remotetimeout 10
set remote hostio-open-packet off
set remote hostio-pread-packet off
target remote :1234
echo HOST_GDB_REMOTE_MANUAL_CONNECTED\n
Loading