# Ghidra reverse-engineering (Bosch TriCore)

Use Ghidra to PROVE what a byte/region does (find the instruction that reads it), rather
than trusting a forum offset. Ghidra 12.1+ ships a built-in TriCore processor module.

## Environment

- Ghidra (e.g. `/opt/homebrew/Cellar/ghidra/12.1`), TriCore built in.
- JDK 21 (e.g. `/opt/homebrew/opt/openjdk@21/...`). Export `JAVA_HOME` to it.

## Headless import + analyze

```bash
export JAVA_HOME=/opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home
analyzeHeadless /tmp/ghidra_proj MyProj \
  -import ~/path/firmware.bin \
  -processor "tricore:LE:32:default" \
  -loader BinaryLoader -loader-baseAddr 0x80000000
```
The base address `0x80000000` matters: Bosch maps file offset 0 → 0x80000000, so a file
offset `X` is address `0x80000000 + X`. (Calibration at file 0x20000 → addr 0x80020000.)

## Running analysis scripts

Bundled scripts live in `tools/ghidra/` (FindCruise, MapPointerTable, MasterGateTrigger,
FindWriterOfE49, DecompileWriter, etc. — written for the Cerato cruise hunt but good
templates for "find what reads/writes address X" and "find the only instruction with
immediate N"). Run and grep:
```bash
analyzeHeadless /tmp/ghidra_proj MyProj -process firmware.bin -noanalysis \
  -postScript FindCruise.java
# parse the script's println output:
... | grep GhidraScript
```

## Patterns that worked

- **"Only instruction with immediate N"**: the cruise speed-threshold was found as the unique
  `ld.h [a15]#0x1e` in 768KB of code → that's the compare against the feature byte. If a value
  is referenced exactly once, that reference is almost certainly its consumer.
- **Master-gate**: a RAM flag (`if (FLAG & bit == 0) skip routine`) gated by a hardcoded
  threshold (immediates 70/81 on a scaled speed var). Hardcoded ⇒ it's CODE, identical across
  same-App-SW firmwares ⇒ don't need to touch it for a calibration-only feature flip.
- **Follow writers**: to learn what sets a RAM flag, find the function that writes it, then
  decompile that function to see the condition.

## When to reach for Ghidra vs donor-diff

Donor-diff first (faster) to locate candidate bytes; Ghidra to CONFIRM a candidate is the
real gate (kills false positives like the Rio `800E`), and to find CODE-side gates that no
calibration diff can reveal (thresholds baked into instructions).
