You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: route the xref family to warm Ghidra in any mode, not just headless (#286)
* fix: route the xref family to warm Ghidra in any mode, not just headless
The cross-reference tools (re_xrefs / re_function_xrefs / re_data_xrefs /
re_call_graph) gated the warm-Ghidra path on `_ghidra_xrefs_active()`, which is
true only for headless settings mode. A user running Ghidra in bridge mode (a
managed resident bridge, or a researcher bridge) has a warm Ghidra project, but
the gate returned false, so these tools fell through to the cold radare2 xrefs
probe. That probe finds no warm *r2* project — only Ghidra was analyzed — and
returns "No warm radare2 analysis for this target yet. Run re_analyze ...",
naming the wrong engine and telling the user to build an analysis they don't
use.
Fix:
- Add `_ghidra_backend_enabled()` (enabled in ANY mode) and gate the xref family
on it. Keep the narrow `_ghidra_xrefs_active()` (headless-only) for re_script,
which genuinely needs the headless probe's warm project / P-Code surface.
- `_ghidra_xrefs` now degrades a registered-but-unreachable managed bridge to the
headless warm slot before giving up, instead of dropping the query to r2.
- When Ghidra is the active backend but its warm index can't answer, surface a
Ghidra-named lead (`_GHIDRA_XREF_LEAD`) — never the r2 "no warm radare2" one.
r2 still runs as a genuine last resort, but its cold-miss lead is rewritten so
the message always matches the active backend.
- `_xrefs` now passes `project_mount` on its r2 path (it previously never
reloaded the warm r2 project) and surfaces the cold-miss lead instead of
formatting a false-empty sink map.
- data_xrefs: a subject that doesn't resolve to an address (most often a string
VALUE mistakenly passed, e.g. a URL/path) now points at the resolve-the-
string's-address workflow (re_list_strings / re_resolve) rather than a bare
"no resolvable references".
Tests: broaden the xref-routing wiring to the new gate; add coverage for the
bridge-mode gate, the string-value data_xrefs hint, and the bridge-mode cold
case returning the Ghidra lead (never radare2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: honest researcher-bridge xref message + review follow-ups
Refines the xref-backend routing from the first commit, addressing the merge
review and extending the fix to a sibling that shared the bug:
- Researcher jfx bridge (features.ghidra.mode=="bridge") is decompile-only and
re_analyze builds no slot in that mode, so routing its xref into a headless
cold-miss produced a "run re_analyze" lead that can't help. `_ghidra_bridge_only`
now short-circuits re_xrefs/re_function_xrefs/re_data_xrefs/re_call_graph with an
honest "switch to headless (the bridge is decompile-only)" message — no futile
attempt, no radare2 cold-miss. Mirrors emulation's early mode-aware refusal.
- _search_code_scan gated its warm path on the headless-only _ghidra_xrefs_active
while _ghidra_search already routes bridge-aware — the exact mis-route this PR
fixes for the xref family, on a sibling. Switched it to _ghidra_backend_enabled.
It does NOT get the bridge-only refusal: its r2 fallback is a RAW byte scan that
needs no warm analysis, so researcher-bridge targets still get real hits.
- _ghidra_xrefs now degrades a dead managed bridge to headless ONLY when the bridge
call RAISED (unreachable). A LIVE bridge returning an error dict no longer triggers
a headless op that would conflict on the project lock the bridge holds — it returns
None (caller surfaces the lead / r2) instead.
Tests: the dead-managed-bridge→headless degrade (a real GhidraBridgeDecompiler that
raises), the re_xrefs path's own cold-miss rewrite, the researcher-bridge refusal
message, and search_code falling back to the r2 raw scan in bridge mode. Renamed the
mis-named "bridge_mode_cold" test (its primary was headless).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: tighten _ghidra_xrefs degrade docstring + bridge-only message
Two LOW wording nits from the #286 re-review: the _ghidra_xrefs docstring said
the headless degrade fires when the bridge 'unreachable/errors', but it now
degrades only on a raise (an error dict returns None); and the bridge-only
message listed 'xrefs or search_code' though search_code never shows it (it
falls back to the r2 raw scan in bridge mode).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments