mirror of
https://github.com/encounter/ghidra-cli.git
synced 2026-07-10 03:18:56 -07:00
3.5 KiB
3.5 KiB
Refactoring Notes
Architecture Reference: debugger-cli
The debugger-cli project at ~/git/debugger-cli provides a good pattern for daemon-based CLIs:
Key Patterns Used
-
IPC via Local Sockets (
src/ipc/)- Uses
interprocesscrate for cross-platform Unix sockets / Windows named pipes - Length-prefixed JSON messages (4-byte little-endian length + payload)
- Separate
protocol.rs,transport.rs, andclient.rsmodules
- Uses
-
Daemon Architecture (
src/daemon/)server.rs- Main event loop with IPC listenerhandler.rs- Command routing and executionsession.rs- State management for debug sessions
-
Clean Separation
- IPC protocol defines its own
Commandenum (not reusing CLI args) - Handler translates protocol commands to domain operations
- Session holds the actual debug adapter connection
- IPC protocol defines its own
Implementation Progress
Phase 1: Bridge Script ✅
- Created
src/ghidra/scripts/bridge.py- persistent TCP server inside Ghidra - Implements handlers:
ping,program_info,list_functions,decompile,list_strings,list_imports,list_exports,memory_map,xrefs_to,xrefs_from - Uses
---GHIDRA_CLI_START---/---GHIDRA_CLI_END---markers for ready signal
Phase 2: Output Markers ✅
- Updated all 8 Python scripts in
scripts.rswith delimiters - Updated
headless.rsto use marker-based extraction instead of fragile brace-counting
Phase 3: IPC Layer ✅
- Added
interprocesscrate toCargo.toml - Created
src/ipc/mod.rswith:protocol.rs- TypedCommandenum,Request,Responsestructurestransport.rs- Cross-platform socket wrapper with length-prefixed framingclient.rs-DaemonClientfor CLI-to-daemon communication
Phase 4: Bridge Manager ✅
- Created
src/ghidra/bridge.rswithGhidraBridgestruct - Manages Ghidra process lifecycle (spawn, monitor, shutdown)
- TCP connection to Python bridge script
BridgeResponse<T>typed response handling- Embeds bridge.py via
include_str!macro
Phase 5: Daemon Update 🚧
- Status: Not yet wired up
- Remaining: Refactor daemon to use new IPC layer and bridge
Phase 6: Typed Responses ⚙️
BridgeResponse<T>created inbridge.rs- Remaining: Update all response handling
Phase 7: GUI Integration (Optional)
- Status: Not started
- Future work
Files Created/Modified
New Files
src/ghidra/scripts/bridge.py- Persistent Python bridge serversrc/ghidra/bridge.rs- Rust bridge managersrc/ipc/mod.rs- IPC module rootsrc/ipc/protocol.rs- Typed protocol definitionssrc/ipc/transport.rs- Socket transport layersrc/ipc/client.rs- Daemon client
Modified Files
Cargo.toml- Addedinterprocesscratesrc/main.rs- Addedmod ipcsrc/ghidra/mod.rs- Addedmod bridge,#[derive(Debug)]onGhidraClientsrc/ghidra/scripts.rs- All scripts now have output markerssrc/ghidra/headless.rs- Marker-based JSON extraction
Remaining Work
To complete the refactoring:
- Wire up bridge to daemon - Modify
daemon/mod.rsto holdGhidraBridge - Route commands through bridge - Update
daemon/queue.rsto use bridge instead of spawning headless - Switch to IPC layer - Replace TCP RPC with local socket IPC
- Remove one-shot execution - Clean up legacy headless spawning code
- Manual testing - Test with actual Ghidra installation
Build Status
✅ cargo check - PASSED
✅ cargo test - 30 passed, 1 pre-existing failure (test_parse_hex)