[GH-ISSUE #6404] [Feature] Ghidra: admit comment / inline_comment / set_comment / set_inline_comment at any mapped address #3837

Open
opened 2026-10-31 00:44:30 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 22, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6404

Before submitting

  • I searched the open and closed issues and pull requests for a related proposal.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This request does not include credentials, private samples, or sensitive target data.

Area

Native analysis or decompilation

Current limitation

In a Ghidra session an agent can only write a comment at the exact entry of a function. Examined at REA main e83e3ceadd (source reading):

  • The Ghidra adapter's admitted operations (src/ghidra/GhidraInventoryValues.ts, GHIDRA_INVENTORY_OPERATIONS) include set_address_name and set_addresses_names but none of comment, inline_comment, set_comment or set_inline_comment. Hopper declares all four (src/hopper/HopperProviderCapabilities.ts).
  • Ghidra's only comment write is annotate_native_function, where "Regular comments map to PRE and inline comments to EOL at the exact function entry" (src/ghidra/GhidraProviderCapabilities.ts). docs/ghidra-provider.md describes the edit surface as "atomic function-name/entry-comment edits".
  • The set_comment tool contract tells agents to "use comments to record evidence IDs or reasoning" (src/contracts/officialToolContracts.ts), which a Ghidra user cannot do at a specific instruction, jump-table entry or global.

#1634 admitted the naming operations for Ghidra and explicitly deferred comments.

Use cases

  • Recording an Evidence ID or a decoded constant next to the instruction that uses it, in a function body rather than at its entry.
  • Annotating a global (DAT_...) or a data table with what it holds, so later procedure_pseudo_code readers and other agents see the note.
  • Reading back comments that Ghidra's own analyzers or imported PDB/DWARF data placed at non-entry addresses.

Desired outcome and success criteria

comment, inline_comment, set_comment and set_inline_comment work with the Ghidra provider with the same request and result shapes as Hopper:

  1. A regular comment maps to Ghidra's PRE comment and an inline comment to EOL, consistent with annotate_native_function.
  2. Setting a comment at a non-entry instruction and at a data address returns true, and comment / inline_comment read the same text back.
  3. An empty comment clears the comment. An unmapped address returns false and leaves the session unchanged.
  4. CRLF, Unicode and rejection of NUL / unpaired surrogates behave as annotate_native_function already guarantees.
  5. The write operations follow the existing Ghidra edit rules: executable bytes stay unchanged, analysis snapshots are invalidated, edits are discarded on close, and Windows P0 does not admit them.
  6. The set_comment / set_inline_comment tool descriptions stop being Hopper-specific (today set_comment says it mutates "the Hopper document" and set_inline_comment warns that "Hopper may flatten newlines").

Open check for the implementer: whether Ghidra procedure_assembly output should show these comments, and how that interacts with existing output budgets.

Expected interaction with targets

  • Write or change files/configuration

Target and scope details (optional)

The write is to REA's ephemeral Ghidra session database only, the same authority set_address_name already has; the target file is not modified and no Ghidra project is saved. I selected "Write or change files/configuration" because the session database is a file REA owns; if maintainers classify session metadata edits differently, this selection should follow that classification. Non-goals: PLATE/POST/REPEATABLE comment types, bookmarks, and persisting comments across sessions (#6405).

Verification available so far

I can suggest a sample or manual check

Verification details (optional)

Proposed check on the existing Ghidra verification fixture: set a regular comment at an instruction inside a function body and an inline comment at a data address, read both back, clear one with an empty string, try an unmapped address, then confirm that annotate_native_function's entry comment is unaffected. Not run: no local Ghidra was available for this report.

Real existing-project read control

On macOS arm64 with Ghidra 12.1.4, Node 24.22.1 and REA #8414 head 89bf190, an owned Ghidra project was prepared independently with a headless script: a PRE comment was written and read back at a mapped data address outside any function. In REA's real compact stdio MCP existing-project mode, inspect_address_context at that address correctly reported procedure.found: false and the comment facet as unavailable/unknown. It did not falsely report an absent comment or point to an unrelated function. The selected original project files and executable bytes were unchanged by REA.

This is a read-only, one-address observation, not a test of REA write/clear behavior or every Ghidra comment type. Function-scoped comments have a separate dossier recovery route (#8363); this data comment demonstrates a case where that route cannot answer the analyst's question. Any design should start from the address-level read/write task and preserve existing project read-only authority rather than assume raw API parity.

Fresh-import entry-comment control

On macOS arm64 with Ghidra 12.1.4 and #8581 head e88f450c, real compact and full stdio MCP sessions opened a fresh import of an owned Mach-O. set_comment at a known function entry returned capability_unavailable because Ghidra does not declare that direct operation; annotate_native_function at the same entry successfully wrote and read back a regular comment. The target hash remained unchanged. This confirms the function-entry alternative for this fixture, not arbitrary-address write support or persistence.

Undeclared-operation recovery control

In a temporary conflict-resolved combination of #8567 96ba4225 and #8581 41472c933, a fresh Ghidra 12.1.4 MCP session in each schema profile returned the proposed generic provider-selection recovery for set_comment at a known function entry. In the same session annotate_native_function wrote and read back the regular entry comment. The source binary hash was unchanged and both sessions closed. This is a control of the specific combined resolution, not a claim about either unmerged PR alone or about comments outside function entries.

The generic recovery is valid for choosing another provider, but does not mention this narrower same-provider route. A task-oriented handoff could surface annotate_native_function when the caller explicitly intends a function-entry comment, while keeping arbitrary-address comments unsupported and avoiding a speculative address-to-function conversion. No autonomous-agent study was performed.

PR #8567 head 757f2646 now proposes a conditional handoff for undeclared regular/inline comment writes when the bound provider declares annotate_native_function available. Real Ghidra 12.1.4 compact and full MCP controls followed that handoff for both comment kinds at a known function entry. Read-only existing-project controls did not offer the unavailable edit. This is an unmerged recovery improvement, not arbitrary-address comment support or an automatic conversion of an address into a function.

Alternatives considered

  • annotate_native_function: function entry only, and every call returns a full dossier (#1634 measured about 148k characters for one rename).
  • Opening the target in Hopper for comments: needs a second provider and session, and the comments do not appear in the Ghidra session's pseudocode or names.

Possible direction

Reuse the transaction, readback and snapshot-invalidation path that annotate_native_function and set_address_name already use in bridge/ghidra/ReaGhidraBridge.java. Recent Ghidra releases expose comment types through a CommentType enum; the implementer should check which form the supported Ghidra versions require.

References

  • Related: #1634 (closed; deferred comments), #5339 (open; another Ghidra session edit).
Originally created by @coygeek on GitHub (Oct 22, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6404 ### Before submitting - [X] I searched the open and closed issues and pull requests for a related proposal. - [X] I understand the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope) must be reviewed before integration; open questions are welcome here. - [X] This request does not include credentials, private samples, or sensitive target data. ### Area Native analysis or decompilation ### Current limitation In a Ghidra session an agent can only write a comment at the exact entry of a function. Examined at REA `main` e83e3ceadd97770a50b8afa97f4077916e4d2b81 (source reading): - The Ghidra adapter's admitted operations (`src/ghidra/GhidraInventoryValues.ts`, `GHIDRA_INVENTORY_OPERATIONS`) include `set_address_name` and `set_addresses_names` but none of `comment`, `inline_comment`, `set_comment` or `set_inline_comment`. Hopper declares all four (`src/hopper/HopperProviderCapabilities.ts`). - Ghidra's only comment write is `annotate_native_function`, where "Regular comments map to PRE and inline comments to EOL at the exact function entry" (`src/ghidra/GhidraProviderCapabilities.ts`). `docs/ghidra-provider.md` describes the edit surface as "atomic function-name/entry-comment edits". - The `set_comment` tool contract tells agents to "use comments to record evidence IDs or reasoning" (`src/contracts/officialToolContracts.ts`), which a Ghidra user cannot do at a specific instruction, jump-table entry or global. #1634 admitted the naming operations for Ghidra and explicitly deferred comments. ### Use cases - Recording an Evidence ID or a decoded constant next to the instruction that uses it, in a function body rather than at its entry. - Annotating a global (`DAT_...`) or a data table with what it holds, so later `procedure_pseudo_code` readers and other agents see the note. - Reading back comments that Ghidra's own analyzers or imported PDB/DWARF data placed at non-entry addresses. ### Desired outcome and success criteria `comment`, `inline_comment`, `set_comment` and `set_inline_comment` work with the Ghidra provider with the same request and result shapes as Hopper: 1. A regular comment maps to Ghidra's PRE comment and an inline comment to EOL, consistent with `annotate_native_function`. 2. Setting a comment at a non-entry instruction and at a data address returns `true`, and `comment` / `inline_comment` read the same text back. 3. An empty comment clears the comment. An unmapped address returns `false` and leaves the session unchanged. 4. CRLF, Unicode and rejection of NUL / unpaired surrogates behave as `annotate_native_function` already guarantees. 5. The write operations follow the existing Ghidra edit rules: executable bytes stay unchanged, analysis snapshots are invalidated, edits are discarded on close, and Windows P0 does not admit them. 6. The `set_comment` / `set_inline_comment` tool descriptions stop being Hopper-specific (today `set_comment` says it mutates "the Hopper document" and `set_inline_comment` warns that "Hopper may flatten newlines"). Open check for the implementer: whether Ghidra `procedure_assembly` output should show these comments, and how that interacts with existing output budgets. ### Expected interaction with targets - Write or change files/configuration ### Target and scope details (optional) The write is to REA's ephemeral Ghidra session database only, the same authority `set_address_name` already has; the target file is not modified and no Ghidra project is saved. I selected "Write or change files/configuration" because the session database is a file REA owns; if maintainers classify session metadata edits differently, this selection should follow that classification. Non-goals: PLATE/POST/REPEATABLE comment types, bookmarks, and persisting comments across sessions (#6405). ### Verification available so far I can suggest a sample or manual check ### Verification details (optional) Proposed check on the existing Ghidra verification fixture: set a regular comment at an instruction inside a function body and an inline comment at a data address, read both back, clear one with an empty string, try an unmapped address, then confirm that `annotate_native_function`'s entry comment is unaffected. Not run: no local Ghidra was available for this report. ### Real existing-project read control On macOS arm64 with Ghidra 12.1.4, Node 24.22.1 and REA #8414 head `89bf190`, an owned Ghidra project was prepared independently with a headless script: a PRE comment was written and read back at a mapped data address outside any function. In REA's real compact stdio MCP existing-project mode, `inspect_address_context` at that address correctly reported `procedure.found: false` and the comment facet as unavailable/unknown. It did not falsely report an absent comment or point to an unrelated function. The selected original project files and executable bytes were unchanged by REA. This is a read-only, one-address observation, not a test of REA write/clear behavior or every Ghidra comment type. Function-scoped comments have a separate dossier recovery route (#8363); this data comment demonstrates a case where that route cannot answer the analyst's question. Any design should start from the address-level read/write task and preserve existing project read-only authority rather than assume raw API parity. ### Fresh-import entry-comment control On macOS arm64 with Ghidra 12.1.4 and #8581 head `e88f450c`, real compact and full stdio MCP sessions opened a fresh import of an owned Mach-O. `set_comment` at a known function entry returned `capability_unavailable` because Ghidra does not declare that direct operation; `annotate_native_function` at the same entry successfully wrote and read back a regular comment. The target hash remained unchanged. This confirms the function-entry alternative for this fixture, not arbitrary-address write support or persistence. ### Undeclared-operation recovery control In a temporary conflict-resolved combination of #8567 `96ba4225` and #8581 `41472c933`, a fresh Ghidra 12.1.4 MCP session in each schema profile returned the proposed generic provider-selection recovery for `set_comment` at a known function entry. In the same session `annotate_native_function` wrote and read back the regular entry comment. The source binary hash was unchanged and both sessions closed. This is a control of the specific combined resolution, not a claim about either unmerged PR alone or about comments outside function entries. The generic recovery is valid for choosing another provider, but does not mention this narrower same-provider route. A task-oriented handoff could surface `annotate_native_function` when the caller explicitly intends a function-entry comment, while keeping arbitrary-address comments unsupported and avoiding a speculative address-to-function conversion. No autonomous-agent study was performed. PR #8567 head `757f2646` now proposes a conditional handoff for undeclared regular/inline comment writes when the bound provider declares `annotate_native_function` available. Real Ghidra 12.1.4 compact and full MCP controls followed that handoff for both comment kinds at a known function entry. Read-only existing-project controls did not offer the unavailable edit. This is an unmerged recovery improvement, not arbitrary-address comment support or an automatic conversion of an address into a function. ### Alternatives considered - `annotate_native_function`: function entry only, and every call returns a full dossier (#1634 measured about 148k characters for one rename). - Opening the target in Hopper for comments: needs a second provider and session, and the comments do not appear in the Ghidra session's pseudocode or names. ### Possible direction Reuse the transaction, readback and snapshot-invalidation path that `annotate_native_function` and `set_address_name` already use in `bridge/ghidra/ReaGhidraBridge.java`. Recent Ghidra releases expose comment types through a `CommentType` enum; the implementer should check which form the supported Ghidra versions require. ### References - Related: #1634 (closed; deferred comments), #5339 (open; another Ghidra session edit).
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

A real Ghidra 12.1.4 / REA MCP check now confirms the source-only entry-comment behavior described here: annotate_native_function wrote PRE and EOL comments at an owned raw fixture's function entry, and analyze_function read both back. comment and inline_comment returned unsupported-provider errors. The target stayed unchanged.

I filed #8363 for the distinct context workflow issue: inspect_address_context reports those already-readable entry comments unavailable and recommends those unsupported calls. That issue does not require implementing arbitrary-address writes and is not a substitute for this broader proposal.

<!-- gh-comment-id:6548081021 --> @morluto commented on GitHub (Oct 31, 2026): A real Ghidra 12.1.4 / REA MCP check now confirms the source-only entry-comment behavior described here: `annotate_native_function` wrote PRE and EOL comments at an owned raw fixture's function entry, and `analyze_function` read both back. `comment` and `inline_comment` returned unsupported-provider errors. The target stayed unchanged. I filed #8363 for the distinct context workflow issue: `inspect_address_context` reports those already-readable entry comments unavailable and recommends those unsupported calls. That issue does not require implementing arbitrary-address writes and is not a substitute for this broader proposal.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3837
No description provided.