Skip to content
Open
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- **Imported programs are now durably analyzed** — the one-shot project
bootstrap (`analyzeHeadless -import`) no longer passes `-noanalysis`. The
import previously skipped analysis at launch and relied on the bridge's
best-effort `program.save()` after a TCP `analyze`; that save silently
swallows failures, so a fresh session saw the imported program as
un-analyzed (`analyzed:false`, `function_count:0`) even though import
reported "Analysis complete", and `function list`/`decompile` returned
nothing. Analyzing inside the one-shot import is persisted by
`analyzeHeadless` on exit, so query sessions see the functions.

## [0.2.2]

### Added
Expand Down
16 changes: 12 additions & 4 deletions src/ghidra/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,18 @@ fn apply_java_home(cmd: &mut Command, ghidra_install_dir: &Path) {
/// the persistent bridge with `-import` (which holds the imported program inside
/// HeadlessAnalyzer's transaction for the bridge's whole life and only commits
/// it during teardown — a commit we then race by killing the JVM), this run
/// imports, saves, commits the project, and exits on its own. The persistent
/// bridge can then open the already-committed program in `-process` mode, where
/// saves are durable and no teardown commit is required.
/// imports, ANALYZES, saves, commits the project, and exits on its own. The
/// persistent bridge can then open the already-committed, already-analyzed
/// program in `-process` mode, where saves are durable and no teardown commit
/// is required.
///
/// Analysis happens HERE — in the one-shot run — not over TCP after the bridge
/// starts. Previously the run passed `-noanalysis` and relied on the bridge's
/// `program.save()` after a TCP `analyze`; that save is best-effort and
/// silently swallows failures, so a fresh session saw an un-analyzed program
/// (0 functions) even though import reported "Analysis complete". Analyzing in
/// the one-shot import is persisted by `analyzeHeadless` on exit and is immune
/// to that failure mode.
pub fn import_oneshot(
project_path: &Path,
binary_path: &Path,
Expand Down Expand Up @@ -340,7 +349,6 @@ pub fn import_oneshot(
.arg(&ghidra_project_name)
.arg("-import")
.arg(binary_path)
.arg("-noanalysis")
.arg("-overwrite");

apply_java_home(&mut cmd, ghidra_install_dir);
Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,9 @@ fn run_with_bridge(cli: Cli) -> anyhow::Result<()> {
// hang-proof cases (see docs/plans/prescript-fix.md §3.3):
// 1. Bridge already running -> TCP import into the live project.
// 2. Project exists, no bridge -> fast launch (Project mode), TCP import.
// 3. Brand-new project -> bootstrap via `-import -noanalysis`
// (only `-import` can create a project; analysis is skipped at
// launch and driven over TCP below).
// 3. Brand-new project -> bootstrap via `-import`
// (only `-import` can create a project; it analyzes and persists
// the program durably, so query sessions see the functions).
// The launch is bounded (the bridge binds its socket before analysis);
// analysis afterwards runs as an unbounded TCP operation.
let (client, program_name) =
Expand Down