annotations
Apply persistent ghidrasql annotations such as names, comments, signatures, and local-variable edits.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Apply persistent ghidrasql annotations such as names, comments, signatures, and local-variable edits.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Analyze binaries with ghidrasql using safe, high-signal query patterns.
Connect to ghidrasql sources, verify live access, and route to the right analysis skill.
Query strings, bytes, data items, memory blocks, and relocations through ghidrasql.
Manage breakpoints and patch bytes through ghidrasql — the breakpoints table and bytes single-byte UPDATE.
Decompile functions with ghidrasql and work with pseudocode, locals, parameters, and ctree pattern views safely.
Inspect code structure through ghidrasql tables for functions, instructions, blocks, CFG, loops, switches, dominators, and tail calls.
| name | annotations |
| description | Apply persistent ghidrasql annotations such as names, comments, signatures, and local-variable edits. |
| allowed-tools | ["Bash","Read","Glob","Grep"] |
Use this skill when the user asks to:
apply_type_* viewsRoute to:
decompiler to inspect locals and pseudocode before editingtypes when a mutation depends on declarations or type importsre-source when the campaign expands beyond a single functionfunc_addr, local_id, ordinal, addr).SELECT save_database(); once at the end.curl -X POST http://127.0.0.1:8081/shutdown (managed mode applies the launch-time --shutdown save policy; proxy mode leaves the upstream host running).There is no SQL shutdown(...) function.
save_database() returning 1 is not always proof the change persisted — in some configurations the save is silently dropped on reopen. For critical edits, save → shut the host down → reconnect with --readonly --no-analyze → re-query the affected rows and compare against the post-write values. See the connect skill's mutation-loop section for the full recipe.pseudocode/decomp_lvars/decomp_comments on the same host can deadlock on a fair ReentrantReadWriteLock. Serialise decompiler-backed work — do not run two parallel annotation pipelines against one host.| Table | UPDATE columns | INSERT | DELETE |
|---|---|---|---|
funcs | name, prototype | – | – |
names | name | yes | yes |
comments | comment, repeatable, source | yes | yes |
data_items | name, data_type | yes | yes |
bookmarks | type, category, comment | yes | yes |
decomp_lvars | name, type | – | – |
decomp_comments | comment, source | yes | yes |
function_params | param_name, param_type | – | – |
function_tags | comment | yes | yes |
function_tag_mappings | – | yes | yes |
signatures | name (function rows only), prototype | – | – |
breakpoints | enabled, type, size, condition, group | yes | yes |
bytes | value (single-byte patch) | – | – |
segments | start_addr (rebase/move block) | yes | yes |
memory_blocks | start_addr (rebase/move block) | yes | yes |
segments/memory_blocks are the writable memory map (#42): INSERT a region
(start_addr, end_addr [, name, perm]), UPDATE start_addr to rebase/move
it, DELETE to remove it. Both expose the same map — see the data skill.
Type tables (types, type_members, type_enums, type_enum_members, type_unions, type_aliases) support INSERT and DELETE; UPDATE is mostly limited to name (full per-table matrix in the types skill).
INSERT-only views: apply_type_data, apply_type_param, apply_type_local — INSTEAD OF INSERT triggers that wrap the underlying type write.
Function rename and signature:
UPDATE funcs
SET name = 'parseConfig',
prototype = 'bool parseConfig(const char *path, Config *out)'
WHERE addr = 0x4011F0;
Parameter rename or type:
UPDATE function_params
SET param_name = 'path',
param_type = 'const char *'
WHERE func_addr = 0x4011F0 AND ordinal = 0;
Decompiler local rename or type — prefer the SQL helpers (direct RPC, no re-decompilation between statements):
SELECT rename_local(0x4011F0, '<local_id>', 'configFile');
SELECT set_local_type(0x4011F0, '<local_id>', 'FILE *');
Alternative via UPDATE (works for the name; type rewrites can fail on array locals — see Gotchas):
UPDATE decomp_lvars
SET name = 'configFile'
WHERE func_addr = 0x4011F0 AND local_id = '<local_id>';
Apply a type via the dedicated view (compositional — works even when the agent only knows the type name):
INSERT INTO apply_type_data (addr, type_name) VALUES (0x404000, 'IMAGE_DOS_HEADER');
INSERT INTO apply_type_param (func_addr, ordinal, type_name) VALUES (0x4011F0, 0, 'const char *');
INSERT INTO apply_type_local (func_addr, local_id, type_name) VALUES (0x4011F0, 'arg2', 'FILE *');
Comment insertion (the source column controls the comment kind: 'plate', 'pre', 'post', 'eol', 'repeatable'):
INSERT INTO comments (addr, comment, source)
VALUES (0x4011F0, 'Reads and parses the configuration file.', 'plate');
Decompiler-attached comments (anchored at decompiler tokens, not raw addresses):
INSERT INTO decomp_comments (func_addr, addr, comment, source)
VALUES (0x4011F0, 0x4012A0, 'fail path: invalid magic', 'pre');
Bookmark (defaults to type='Analysis' if not specified):
INSERT INTO bookmarks (addr, type, category, comment)
VALUES (0x4011F0, 'Note', 'review', 'check overflow handling');
Function tags (catalog first, then map):
INSERT INTO function_tags (name, comment) VALUES ('reviewed', 'manually reviewed');
INSERT INTO function_tag_mappings (func_addr, tag_name) VALUES (0x4011F0, 'reviewed');
Tag deletion cascades through both tables: DELETE FROM function_tags WHERE name = 'reviewed'; removes every mapping.
signatures is read-mostly. Only name and prototype are writable — UPDATE signatures SET name = ... renames the owning function (function rows only; rejected for other owners), equivalent to UPDATE funcs SET name = .... To change the calling convention, write a full prototype string into either funcs.prototype or signatures.prototype.__cdecl in a prototype string can fail with a vague diagnostic. If set_function_signature at 0xN errors without a parse detail, drop the calling-convention prefix and retry — the signature without __cdecl typically applies cleanly.UPDATE decomp_lvars SET name = ... works. The writable-type resolver handles array declarators, so re-applying an array type (e.g. wchar_t[128]) while the rename commits no longer fails with "unable to resolve writable data type". SELECT rename_local(0x4011F0, '<local_id>', 'configFile'); remains available as a direct, type-agnostic RPC alternative.uint8_t/uint16_t/uint32_t/unsigned/unsigned int) are mis-mapped in older builds of parse_decls(). Current builds resolve them correctly; if you hit a width mismatch, suspect an outdated build.program_id, so the next query refreshes automatically. Inside a -f script or multi-statement REPL input, drop just the table you wrote to before reading it again when you need to force a rebuild:
SELECT cache_invalidate('decomp_lvars');
Cheaper than refresh_database() when only one surface is stale.<type> *fn(...) as a name *fn rather than a return type. Use <type>* fn(...) form when authoring prototypes — char* foo, void** bar, int* baz. Same trap applies to multi-statement parameter lists. Verify the apply landed by re-reading funcs.prototype or function_params.apply_type_local (or a direct UPDATE on decomp_lvars) at one site can change unrelated variables. Mitigation: keep the recovered type on prototypes/parameters, back the local out to a neutral type (char *, int) at the questionable site, and verify each step in pseudocode before continuing.SELECT text FROM pseudocode WHERE func_addr = 0x4011F0;
SELECT local_id, name, type FROM decomp_lvars WHERE func_addr = 0x4011F0;
SELECT func_addr, local_id, name, type FROM decomp_lvars WHERE func_name = 'main';
SELECT ordinal, param_name, param_type FROM function_params WHERE func_addr = 0x4011F0;
SELECT save_database();
Name-scoped decomp_lvars reads are useful for discovery, but writes should still use the resolved func_addr plus the exact local_id returned by the read.
pseudocode, verify you used the canonical local_id / ordinal / addr. If you're inside a batched script and the row is correct in decomp_lvars but pseudocode looks stale, SELECT cache_invalidate('pseudocode'); SELECT text FROM pseudocode WHERE func_addr = 0xX;.save_database() once at the end.