Skip to content

Auto save Ghidra project - #23

Open
Thaelz wants to merge 2 commits into
akiselev:masterfrom
Thaelz:auto-save-after-mutations
Open

Auto save Ghidra project#23
Thaelz wants to merge 2 commits into
akiselev:masterfrom
Thaelz:auto-save-after-mutations

Conversation

@Thaelz

@Thaelz Thaelz commented Sep 7, 2026

Copy link
Copy Markdown

After an AI RE session, I wanted to check for myself the function it was refering to and.. there was no function! No disassembly! I realized that all the create function, symbol renames, comments were not saved to the Ghidra project. I think it is a nice feature, to capitalize better on the token consummed and ease coworking with AI.

So I tasked Claude to create a patch for that, tested on my target and it worked fine.
Looks minimal enough to me. The CreateFunctionCmd is a fallback needed for raw binary. Tested on ARM raw binary & x64 ELF.
Note that it is enabled per default, you might prefer to gate it under a parameter (I do not!).

Thaelz and others added 2 commits September 7, 2026 11:20
Mutating bridge commands (create_function, rename_function, symbol/type
edits, tag edits, comments, patches, script/batch runs) only ended their
Ghidra transaction, which commits into the bridge JVM's in-memory program.
Nothing flushed to the .rep store until analyze/program switch/import, and
`stop` SIGKILLs the JVM without a teardown save, so those edits were lost on
teardown and never appeared when the project was opened in the Ghidra GUI.

Add isMutatingCommand() and, in executeProgramRequest, call
currentProgram.save() after any successful mutating command. Read-only
queries (decompile, disasm, list/xref/find/graph/diff/tag list/exports) are
excluded, as are import/analyze/open_program which already persist on their
own paths. Save failures are logged via printerr and do not fail the command.

Verified end-to-end on a freshly imported binary: `comment set` + `tag add`,
then `stop` (kills the JVM, no teardown save), then restart — both the plate
comment and the tag read back; without the save they were gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The strict FunctionManager.createFunction() API rejects entries in raw/flat
firmware images that Ghidra's auto-analysis never reached, failing with
"Function body must contain the entrypoint" even when valid instructions exist
at the address. This blocked defining the many computed/indirect-call targets
that are the whole point of annotating STM32/nRF/bootloader images.

On strict failure, fall back to ghidra.app.cmd.function.CreateFunctionCmd (what
the GUI's "Create Function" uses): it disassembles at the entry if needed and
computes the body by following flow, then we apply the requested name. Callers
must pass EVEN (non-Thumb-bit) addresses; an odd address is treated as a literal
mid-instruction location and rejected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant