mcpField
D
decompiler

decompiler

github.com/allthingsidaDevelopment4970 installsUpdated 3w ago
Repository

About decompiler

A skill for analyzing decompiled functions in Hex-Rays, using pseudocode, AST data, local variables, and pattern views. It guides function-scoped queries and routes follow-up work to related analysis skills.

Key features

  1. 01Inspect decompiled pseudocode
  2. 02Query AST and local variables
  3. 03Search calls, branches, and loops
  4. 04Edit pseudocode comments
  5. 05Recover with disassembly workflows

Use cases

  1. 01Understand a function's behavior
  2. 02Find call or condition patterns
  3. 03Inspect local variable semantics
  4. 04Validate decompiler output at assembly level

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/allthingsida/idasql-skills --skill decompiler

After installing, type/decompilerin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

agents/
openai.yaml
references/
ctree-manipulation.md
decompiler-views.md
decompiler-workflows.md

Details

From the project README

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)

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)

-- 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:

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).

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!

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)
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.
  • 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.

-- 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 often has addr = 0 and is not the right 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.
-- Resolve the first attachable non-brace row near function start
SELECT line_num, addr, line
FROM pseudocode
WHERE func_addr = 0x401000
  AND addr != 0
  AND TRIM(line) NOT IN ('{', '}')
  AND addr IN (
    SELECT addr
    FROM pseudocode
    WHERE func_addr = 0x401000 AND addr != 0
    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 != 0
      AND TRIM(line) NOT IN ('{', '}')
      AND addr IN (
        SELECT addr
        FROM pseudocode
        WHERE func_addr = 0x401000 AND addr != 0
        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.
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
is_user_definedINTR1 if name differs from default LABEL_<n>
ctree_call_args

Flattened call arguments for easy querying.

ColumnTypeDescription
func_addrINTFunction address
call_item_idINTCall node ID
call_addrINTCall-site EA
call_obj_nameTEXTCallee object name
call_helper_nameTEXTCallee helper name
arg_idxINTArgument index (0-based)
arg_item_idINTArgument expression item ID
arg_opTEXTArgument type
arg_var_idxINTLocal variable index when the argument is a variable
arg_var_nameTEXTVariable name if applicable
arg_var_is_stkINT1=argument variable is a stack variable
arg_var_is_argINT1=argument variable is itself a function argument
arg_obj_addrINTObject address when the argument is a global object
arg_obj_nameTEXTObject name when the argument is a global object
arg_num_valueINTNumeric value
arg_str_valueTEXTString value

Decompiler Views

Pre-built views for common patterns (always filter by func_addr):

ViewPurpose
ctree_v_callsFunction calls with callee info
ctree_v_indirect_callsIndirect/dynamic call sites for call-site typing
ctree_v_loopsfor/while/do loops
ctree_v_ifsif statements
ctree_v_comparisonsComparisons with operands
ctree_v_signed_opsSigned comparison/arithmetic operations
ctree_v_assignmentsAssignments with operands
ctree_v_derefsPointer dereferences
ctree_v_returnsReturn statements with value details
ctree_v_calls_in_loopsCalls inside loops (recursive)
ctree_v_calls_in_ifsCalls inside if branches (recursive)
ctree_v_leaf_funcsFunctions with no outgoing calls
ctree_v_call_chainsCall chain paths up to depth 10

Type Tables and Views

For types, types_members, types_enum_values, types_func_args schemas, type views, and type CRUD examples, see types skill.


SQL Functions — Decompilation

When to use decompile() vs pseudocode table:

  • Read/show pseudocode -> always start with SELECT decompile(addr). Returns full function as one text block with per-line prefixes.
  • Local declaration hints -> declaration lines include compact local-variable index hints ([lv:N]) so rename operations can target UPDATE ctree_lvars ... WHERE func_addr = ... AND idx = N safely.
  • Need fresh output after edits -> use SELECT decompile(addr, 1) to force re-decompilation.
  • Need structured line access or comment CRUD -> query/update the pseudocode table.
FunctionDescription
decompile(addr)PREFERRED -- Full pseudocode with line prefixes
decompile(addr, 1)Same output but forces re-decompilation
call_arg_addrs(call_addr)Read persisted argument-loader addresses as JSON
set_union_selection(func_addr, addr, path)Set/clear union selection path at EA
set_union_selection_item(func_addr, item_id, path)Set/clear union selection path by ctree.item_id
set_union_selection_addr_arg(func_addr, addr, arg_idx, path[, callee])PREFERRED call-arg targeting helper
call_arg_item(func_addr, addr, arg_idx[, callee])Resolve call-arg coordinate to explicit arg_item_id
ctree_item_at(func_addr, addr[, op_name[, nth]])Resolve generic expression coordinate to explicit ctree.item_id
set_union_selection_addr_expr(func_addr, addr, path[, op_name[, nth]])Set/clear union selection via generic expression coordinate
get_union_selection(func_addr, addr)Read union selection path JSON at EA
get_union_selection_item(func_addr, item_id)Read union selection path JSON by ctree.item_id
get_union_selection_addr_arg(func_addr, addr, arg_idx[, callee])Read union selection JSON via call-arg coordinate
get_union_selection_addr_expr(func_addr, addr[, op_name[, nth]])Read union selection JSON via generic expression coordinate
set_numform(func_addr, addr, opnum, spec)Set/clear numform directly by EA + operand index
get_numform(func_addr, addr, opnum)Read numform JSON directly by EA + operand index
set_numform_item(func_addr, item_id, opnum, spec)Set/clear numform by explicit ctree item id
get_numform_item(func_addr, item_id, opnum)Read numform JSON by explicit ctree item id
set_numform_addr_arg(func_addr, addr, arg_idx, opnum, spec[, callee])Set/clear numform via call-arg coordinate
get_numform_addr_arg(func_addr, addr, arg_idx, opnum[, callee])Read numform JSON via call-arg coordinate
set_numform_addr_expr(func_addr, addr, opnum, spec[, op_name[, nth]])Set/clear numform via generic expression coordinate
get_numform_addr_expr(func_addr, addr, opnum[, op_name[, nth]])Read numform JSON via generic expression coordinate

Targeting guidance:

  • Use *_addr_arg helpers for repeated callees and call-site arguments.
  • Use ctree_item_at(..., op_name, nth) plus *_addr_expr helpers for non-call expressions and assignment-side struct/union population stores.

SQL Functions — Modification

For applied_types, parse_decls(), and name writes via names/funcs, see types skill.

Preferred SQL write surface for function metadata:

  • UPDATE funcs SET name = '...', prototype = '...', comment = '...', rpt_comment = '...' WHERE addr = ...
  • prototype maps to applied_types behavior and invalidates decompiler cache.
  • comment / rpt_comment map to get_func_cmt() / set_func_cmt().

Performance Rules

TableArchitectureKey ConstraintNotes
pseudocodeCachedfunc_addrLazy per-function cache, freed after query
pseudocode_orphan_commentsCachedfunc_addrQuery-scoped orphan rows; writable delete-only
pseudocode_v_orphan_comment_groupsCachedfunc_addrQuery-scoped grouped orphan triage; start broad with LIMIT
ctreeGeneratorfunc_addrLazy streaming, never materializes full result, respects LIMIT
ctree_lvarsCachedfunc_addrLazy per-function cache, freed after query
ctree_call_argsGeneratorfunc_addrLazy streaming, respects LIMIT

Critical rules:

  • ALL decompiler tables require func_addr constraint. Without it, every function is decompiled.
  • Generator tables (ctree, ctree_call_args) stream rows lazily and stop at LIMIT.
  • Decompiler views (ctree_v_calls, ctree_v_indirect_calls, ctree_v_loops, etc.) inherit the func_addr constraint -- always filter.
  • Hex-Rays cfunc cache: decompile(addr) is internally cached. decompile(addr, 1) forces a full re-decompilation -- only use when you need to see effects of a mutation.

Cost model:

decompile(addr)          -> ~50-200ms first call, ~0ms cached
decompile(addr, 1)       -> ~50-200ms always (forces re-decompile)
ctree WHERE func_addr=X  -> one decompilation + streaming rows
ctree (no constraint)    -> one decompilation per row in funcs

Additional Resources


See Also

  • data — raw bytes and string content referenced by decompiled code (the bytes table for per-byte reads and bounded-window reads via WHERE start_addr = X AND n = N; hex(blob_concat(value)) for hex output).
  • disassembly — instruction-level ground truth for the same function (disasm_func, instructions, disasm_calls).
  • xrefs — callers and callees of a decompiled function; pivot from pseudocode to call graph.
  • types — applied prototypes drive ctree shape; retype via applied_types / funcs.prototype to clean up casts and indirect calls.

Comments

Markdown supported