allthingsida/idasql-skills/decompiler

Claude Code and agent skill by allthingsida/idasql-skills

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Decompile and analyze IDA functions. Use when asked for pseudocode, ctree AST analysis, local variables, labels, split expressions, or decompiler-driven cleanup.

Install

npx vskill@latest install allthingsida/idasql-skills/decompiler

SKILL.md

Links: when an answer names functions, addresses, strings or types, make them clickable on IDA 9.4 builds: [name](uri) from the deep_links table, outside code blocks (skill deep-links).

Trigger Intents

Use this skill when user asks for:

  • "decompile this function"
  • pseudocode understanding or AST-level analysis
  • local variable semantics in decompiled form
  • decompiler-centric pattern mining (returns/calls/conditions)
  • "split expression": a merged *(_QWORD *)&x = 0x...LL store printed field by field

Route to:

  • annotations for persistent comments/renames after interpretation
  • types for struct/enum/type construction and application
  • disassembly when decompiler is unavailable or insufficient

Do This First (Warm-Start Sequence)

sql
-- 1) Capability/profile probe
SELECT * FROM pragma_table_list WHERE name IN ('pseudocode', 'ctree', 'ctree_lvars');
-- 2) Pick one concrete function target
SELECT name, printf('0x%X', addr) AS addr, size
FROM funcs
ORDER BY size DESC
LIMIT 10;
-- 3) View decompiled text via primary read surface
SELECT decompile(0x401000);

Interpretation guidance:

  • decompile(addr) is primary display surface.
  • pseudocode/ctree* are structured query/edit surfaces.

Global Constraint Reminder (Critical)

Always constrain decompiler tables by function:

sql
WHERE func_addr = 0x...

Without this, decompiler tables may decompile every function and become extremely slow.


Failure and Recovery

  • No Hex-Rays/decompiler tables unavailable:
  • Fall back to disassembly + xrefs workflows.
  • Empty/partial rows:
  • Confirm target func_addr exists and refresh decompile cache (decompile(addr, 1) where supported).
  • Mutation did not appear:
  • Run mandatory mutation loop (read -> edit -> refresh -> verify).
  • A decompiler_splits write failed:
  • "piece_size must be 1, 2, 4 or 8": give bytes, not IDA's internal size code.
  • "is not the start of an instruction" / "is not in the function at": take addr from the

merged assignment (ctree.addr of the cot_asg), and func_addr from funcs.

  • "is already split": UPDATE decompiler_splits SET piece_size = ... or DELETE it.
  • "unrecognised split state version" / "verified on IDA 9.0-9.4 only": this IDA stores split

data in a form idasql does not know; use the pseudocode window's Split expression instead.

  • A split row exists but the pseudocode did not change: nothing at that addr was merged (or

it already prints in pieces that size); delete the row.


Handoff Patterns

  1. decompiler -> types for local type seeding and richer declarations.
  2. decompiler -> annotations for persistent narrative and naming.
  3. decompiler -> disassembly for opcode-level validation.

Decompiler Tables (Hex-Rays Required)

CRITICAL: Always filter by func_addr. Without constraint, these tables will decompile EVERY function - extremely slow!

func_addr is a function's entry address on every decompiler table: an address inside a function matches no row (as on the disassembly tables), and every row reports the entry. Rowids are stable per (function, item), so OR across functions and self-joins never drop or merge rows.

pseudocode

The pseudocode table is a structured line-by-line pseudocode with writable comments. Use `decompile(addr)` to view pseudocode; use this table only for surgical edits (comments) or structured queries.

ColumnTypeWritableDescription
func_addrINTNoFunction address
line_numINTNoLine number
lineTEXTNoPseudocode text
addrINTNoCorresponding assembly address (from COLOR_ADDR anchor); NULL for a line with no address (signature, blank or comment-only line)
commentTEXTYesDecompiler comment at this addr
comment_placementTEXTYesComment placement: semi (inline, default), block1 (above line)

Filter behavior:

  • WHERE func_addr = X: best performance; iterates pseudocode for one function only.
  • WHERE addr = X: decompiles only the containing function and returns matching lines for that EA (a line in a tail shared by several functions is listed under each owner).
  • WHERE line_num = N: scans functions and returns rows at that line index; use only when you need cross-function line alignment.

Comment placements: semi (after ;), block1 (own line above), block2, curly1, curly2, brace1, brace2, colon, case, else, do, asm, try. An unrecognized placement string is silently coerced to semi.

sql
-- VIEWING: Use decompile() function, NOT the pseudocode table
SELECT decompile(0x401000);
-- COMMENTING: Use pseudocode table to add/edit/delete comments
UPDATE pseudocode SET comment_placement = 'semi',
comment = 'buffer overflow here'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Add block comment (appears on own line above the statement)
UPDATE pseudocode SET comment_placement = 'block1', comment = 'vulnerable call'
WHERE func_addr = 0x401000 AND addr = 0x401020;
-- Delete comments at a resolved unique anchor
UPDATE pseudocode SET comment = NULL
WHERE func_addr = 0x401000 AND addr = 0x401020;

True function comments are not part of pseudocode:

  • use UPDATE funcs SET comment = ... WHERE addr = ... for the regular function comment
  • use UPDATE funcs SET rpt_comment = ... WHERE addr = ... for the repeatable function comment
pseudocode_orphan_comments

Persisted Hex-Rays comments that no longer attach to the current decompiled output of a live function. Use it to inspect or delete stale comments.

ColumnTypeWritableDescription
func_addrINTNoFunction address
func_nameTEXTNoCurrent function name for triage
addrINTNoStored orphan comment EA
comment_placementTEXTNoStored treeloc_t.itp placement
orphan_commentTEXTDelete-onlyStored orphan comment text

Rules:

  • UPDATE ... SET orphan_comment = NULL or '' deletes that orphan comment.
  • Any non-empty write is rejected.
pseudocode_v_orphan_comment_groups

Grouped, read-only orphan triage surface. One row per function with orphan comments.

Columns: func_addr, func_name, orphan_count, orphan_comments_json

Comment Anchor Resolution (Critical)

Use this recipe before writing heading-style decompiler notes.

Rules:

  • Do not assume addr == func_addr.
  • The first displayed pseudocode row (the signature) has addr NULL and is not a write target.
  • One addr can map to multiple rows ({, statement, }); prefer a unique non-brace anchor.
  • For true function comments, update funcs.comment / funcs.rpt_comment instead of pseudocode.
sql
-- Resolve the first attachable non-brace row near function start
SELECT line_num, addr, line
FROM pseudocode
WHERE func_addr = 0x401000
AND addr IS NOT NULL
AND TRIM(line) NOT IN ('{', '}')
AND addr IN (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000 AND addr IS NOT NULL
GROUP BY addr
HAVING COUNT(*) = 1
)
ORDER BY line_num
LIMIT 1;
-- Write a heading-style summary using the resolved addr
UPDATE pseudocode
SET comment_placement = 'block1',
comment = 'One-paragraph summary of the function.'
WHERE func_addr = 0x401000
AND addr = (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000
AND addr IS NOT NULL
AND TRIM(line) NOT IN ('{', '}')
AND addr IN (
SELECT addr
FROM pseudocode
WHERE func_addr = 0x401000 AND addr IS NOT NULL
GROUP BY addr
HAVING COUNT(*) = 1
)
ORDER BY line_num
LIMIT 1
);
ctree

Full Abstract Syntax Tree of decompiled code.

ColumnTypeDescription
func_addrINTFunction address
item_idINTUnique node ID
is_exprINT1=expression, 0=statement
opINTRaw numeric op code
op_nameTEXTNode type (cot_call, cit_if, etc.)
addrINTAddress in binary
parent_idINTParent node ID
depthINTTree depth
x_id, y_id, z_idINTChild node IDs
cond_idINTCondition child ID (if/while/for)
then_idINTThen-branch child ID (if)
else_idINTElse-branch child ID (if)
body_idINTBody child ID (loops)
init_idINTInit child ID (for)
step_idINTStep child ID (for)
var_idxINTLocal variable index
obj_addrINTTarget address
num_valueINTNumeric literal
str_valueTEXTString literal
helper_nameTEXTHelper function name (cot_helper)
member_offsetINTMember offset (cot_memptr/cot_memref)
var_nameTEXTVariable name
var_is_stkINT1=variable is a stack variable
var_is_regINT1=variable is a register variable
var_is_argINT1=variable is a function argument
obj_nameTEXTSymbol name
label_numINTLabel number when node defines a label
goto_label_numINTTarget label number for cit_goto nodes
ctree_lvars

Local variables from decompilation.

ColumnTypeDescription
func_addrINTFunction address
idxINTVariable index
nameTEXTVariable name
typeTEXTType string
commentTEXTLocal-variable comment shown next to declaration
sizeINTSize in bytes
is_argINT1=function argument
is_resultINT1=holds the function result
is_stk_varINT1=stack variable
is_reg_varINT1=register variable
stkoffINTStack offset
mregINTMicrocode register number (register variables)

Mutation guidance:

  • Prefer idx-based updates for deterministic writes.
  • type accepts scalars, pointers, and array types — e.g. SET type = 'WCHAR[6]' or '_BYTE[392]' for wide stack strings / fixed buffers (the type must fit the local's stack slot).
  • comment updates map to Hex-Rays local-variable comments (lv.cmt) and appear in decompile(...) output.
  • A type UPDATE is read back: when Hex-Rays keeps the old type the UPDATE fails ("Hex-Rays kept ...") and nothing is left changed. The result variable (is_result = 1, often unnamed) usually follows the function prototype that way, so change the return type with UPDATE funcs SET prototype = .... Its comment is writable.
  • A rename can re-order the function's locals (IDA 9.2 does this for register arguments), so the next edit should re-select its idx (or address the variable by mreg / stkoff) rather than reuse an idx read before the rename.
ctree_labels

Decompiler control-flow labels. Supports UPDATE (name) and mirrors label facilities on cfunc_t.

ColumnTypeRWDescription
func_addrINTRFunction address
label_numINTRLabel number (LABEL_<n>)
nameTEXTRWCurrent label name
item_idINTRBacking ctree item id for this label
item_addrINTRAddress of label-bearing ctree item (NULL when the item has none)
is_user_definedINTR1 if name differs from default LABEL_<n>
decompiler_splits

Hex-Rays "Split expression" without a pseudocode window (the window's Split/Unsplit expression; vdui_t::split_item in hexrays.hpp). A row keeps the decompiler from merging narrower operations into one wider one at addr, so a struct initialised by one 8-byte store prints field by field.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
12
Repository forks
4
7-day trend score
13

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 22 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/allthingsida/idasql-skills/decompiler/badge)](https://verified-skill.com/skills/allthingsida/idasql-skills/decompiler)

Something wrong with this skill or its page? Tell us.