summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/docs/05-GHIDRA-BRIDGE.md
blob: f7f46c39df0b3b59fe11dd116d523dc39d4600fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 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.

`greeneye.ghidra.render_ghidra_command(proj_dir, project, program, hits_tsv)`
renders the `analyzeHeadless … MarkGreenEyeHits.java` command line above for
scripts (the helper is not wired into the CLI).

## 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.