summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 08:36:35 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 08:36:35 -0400
commitba58dcdc5ad6ca021c723d279f33e3f14e1184df (patch)
tree47e43a2dad9a2d4bb40da46243654bff8b1302de /debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md
parentfe485080e159c983242d699f4a584659df159818 (diff)
downloadopen-iov-ba58dcdc5ad6ca021c723d279f33e3f14e1184df.tar.gz
open-iov-ba58dcdc5ad6ca021c723d279f33e3f14e1184df.zip
debug: add green-eye GSP/uproc RISC-V VM runtime analysis tooling
Adds open-iov/debug/risc-v-gsp-rm-vm: a GDB-free instrumentation stack that boots uproc/GSP firmware in qemu-system-riscv64 and provides Frida-like hooks, breakpoints, watchpoints, memory dumps, structure decoding, snapshot diffs, recorded sessions, declarative probes, a plugin API and a Ghidra symbol/hit bridge. Verified: 25 tests green (including a live QEMU smoke test); the demo uproc boots with correct hook/leave/watch/schema/snapshot/fault evidence; the optional TCG trace plugin builds and recorded 15M trace lines in 3 s; the TU104 570.144 fwimage probe reports its first exception (load access fault at firmware vaddr 0x4009014 reading 0x2000000000000A00). Documentation: lean tool docs under debug/risc-v-gsp-rm-vm/docs/00-10, a new docs/05-operations/03-risc-v-gsp-rm-vm.md debugging document, and '# TOOL IN DEVELOPMENT - NOT READY YET!' markers in docs/README.md, the onboarding tooling table and the debugging workflows doc. Vendors qemu-plugin.h from QEMU v8.2.2 (GPL-2.0-or-later), with its license header intact, so the optional TCG plugin builds without a QEMU source tree.
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md')
-rw-r--r--debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md105
1 files changed, 105 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md b/debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md
new file mode 100644
index 0000000..857102e
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md
@@ -0,0 +1,105 @@
+# 05 — Ghidra bridge
+
+> **# TOOL IN DEVELOPMENT - NOT READY YET!** See 00 for status.
+
+Ghidra answers *what is the code*; green-eye answers *what did it do*. The
+bridge joins them in both directions: Ghidra symbols into the runtime session,
+runtime hit addresses back into the Ghidra project.
+
+## 1. Address conventions (read this first)
+
+| Space | Meaning | Transformation |
+|---|---|---|
+| file vaddr | offset in the binary (`libcuda+0x…`) | base |
+| Ghidra program addr | what the decompiler shows | file vaddr + image base (`0x100000` for libcuda) |
+| runtime addr | live process / emulator address | file vaddr + load bias |
+
+* Firmware linked at its load address: bias 0 (the demo, and a
+ relocated-to-RAM GSP image when using the probe bias).
+* CUDA `libcuda` in the host oracle: runtime base from `/proc/<pid>/maps`;
+ `--bias` normalises it if you want runtime addresses in the DB.
+* The project's `decompiled_index.tsv`/bucket TSVs carry **both** program and
+ file addresses; green-eye parses both and stores the program address in
+ `symbol.extras["program_addr"]`.
+
+## 2. Build a symbol DB from Ghidra exports
+
+```bash
+./greeneye.sh symbols export \
+ --names ../../userspace/cuda/570.144/annotations/names.tsv \
+ --index ../../userspace/cuda/570.144/run/analysis/decompiled/decompiled_index.tsv \
+ --exports ../../userspace/cuda/570.144/run/analysis/elf-index/exports.tsv \
+ --callgraph ../../userspace/cuda/570.144/run/analysis/elf-index/callgraph.tsv \
+ --bias 0 -o symbols-cuda.json
+```
+
+For the GSP firmware project (`tools/ghidra/gsp-fwimage-570.144/`), first run
+the existing export scripts (`ExportFunctionIndex.java`,
+`DecompileFunctions.java`, …) to produce TSVs, then:
+
+```bash
+./greeneye.sh symbols export --index <export.tsv> --bias 0 -o symbols-gsp.json
+```
+
+`load_index_tsv` is column-aware: it accepts
+`<program>\t<file>\t<size>\t<name>\t<bucket>\t<line>\t<status>`, the 4-column
+exports form, or a plain `<addr>\t<name>` two-column form.
+
+## 3. Runtime addresses in the session
+
+```python
+db = SymbolDB()
+db.load_json("symbols-cuda.json")
+db.load_names_tsv("names.tsv", bias=runtime_base - file_base)
+s.symbols = db # or pass symbols= to attach()/launch()
+```
+
+`resolve()` then annotates every hit with the Ghidra name, and
+`greeneye.ghidra.corpus_location(symbol, corpus_root)` returns
+`<bucket>:<line>` when the index carried that information — the pointer from a
+live hit to the decompiled body.
+
+## 4. Annotate hits back into Ghidra
+
+```bash
+./greeneye.sh analyze dumps/<run> --symbols symbols-gsp.json --out run.md
+python3 - <<'PY'
+from greeneye.ghidra import export_hits
+from greeneye.symbols import SymbolDB
+db = SymbolDB(); db.load_json("symbols-gsp.json")
+print(export_hits("dumps/<run>", "greeneye_hits.tsv", symbols=db))
+PY
+```
+
+`greeneye_hits.tsv` is `addr<TAB>hits<TAB>symbol<TAB>annotation`. Then run the
+bundled Java script in Ghidra headless:
+
+```bash
+$GHIDRA/support/analyzeHeadless <proj_dir> <project> -process <program> -noanalysis \
+ -scriptPath debug/risc-v-gsp-rm-vm/ghidra \
+ -postScript MarkGreenEyeHits.java /abs/path/greeneye_hits.tsv
+```
+
+`ExportForGreenEye.java` is the reverse helper: it walks the current program
+and writes a green-eye-compatible `addr<TAB>name<TAB>size` TSV.
+
+## 5. Breakpoints from Ghidra
+
+Two practical routes today:
+
+1. `greeneye decompose/decompile` → note the file vaddr → script
+ `s.hook("0x…")` (green-eye translates to runtime via the bias you loaded).
+2. Use `symbols export` from the Ghidra index, then `s.hook("<name>")` by
+ name — the most robust route across recompilations.
+
+A future Ghidra-side green-eye console (roadmap item) can call
+`greeneye` through its CLI to set breakpoints directly from the tool.
+
+## 6. Limits
+
+* Wrapper-generated functions are re-laid-out between driver patch versions;
+ transfer names, never raw wrapper addresses (the CUDA playbook's lesson).
+* The decompiler does not recover struct types; structure schemas for
+ green-eye decoding must be written or exported separately.
+* `decompiled_index.tsv` buckets are large and gitignored; keep symbol JSONs
+ small (name/size/subsystem only) if they must be tracked.