types について
typesスキルは、idasqlから利用できるIDAの型システムを解説し、ローカル型の作成、確認、調整を行うリバースエンジニア向けです。SQLによる型やメンバーの編集、構造体の固定レイアウト、関連分析ワークフローへの案内を扱います。
主な機能
- 01ローカル型定義の確認
- 02構造体、共用体、列挙型、typedefの作成と編集
- 03構造体メンバーの検索と変更
- 04固定レイアウトによる構造体オフセットの保持
- 05型と型ブックマークの整理
- 06関連スキルへの型分析の引き継ぎ
活用シーン
- 01逆アセンブリの所見から構造体を復元
- 02宣言全体を再構築せずに型を調整
- 03関数引数の型とtypedef解決を確認
- 04復元した型をフォルダーに整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ allthingsida/ idasql-skills --skill typesインストール後、Claude Code で/typesを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlreferences/type-patterns.md
詳細
このスキルは、idasql で公開される IDA の型システムに関する信頼できるリファレンスです。型を使用するアノテーションワークフローについては、annotations を参照してください。デコンパイラー固有の型操作(ctree、lvars、ユニオンの選択、numform)については、decompiler を参照してください。
トリガーとなる意図
ユーザーが次のことを尋ねた場合に、このスキルを使用します。
- 構造体、ユニオン、列挙型、typedef の作成・編集
- 関数プロトタイプの引数型の確認
- 非表示のポインターや typedef の挙動の解決
- 復元したデータモデルの適用または調整
次のスキルにルーティングします。
- 式レベルの型コンテキストについては
decompiler - 型の決定の適用と記録については
annotations - 再帰的な構造体復元ワークフローについては
re-source
最初に行うこと(ウォームスタート手順)
-- 1) Inventory local types
SELECT ordinal, name, kind, size
FROM types
ORDER BY ordinal
LIMIT 30;
-- 2) Large/high-signal structs
SELECT name, size
FROM types
WHERE is_struct = 1
ORDER BY size DESC
LIMIT 20;
-- 3) Prototype introspection sample
SELECT type_name, arg_index, arg_name, arg_type
FROM types_func_args
WHERE arg_index >= 0
LIMIT 40;
解釈のガイダンス:
- まず一覧を取得し、大規模で参照先の多い型を優先します。
- typedef を考慮した推論には、
types_func_argsの解決済みフィールドを使用します。
失敗と復旧
- 型の挿入・更新に失敗した場合:
- 宣言構文と、対象の ordinal/名前が存在するかを確認します。
- 型の情報に矛盾や不足がある場合:
- 変更を確定する前に、
decompiler(ctree_lvars、呼び出し引数)と照合します。
- 変更を確定する前に、
- 予期しない逆アセンブル表示になった場合:
- オペランド形式の設定と適用済みの宣言を再確認します。
- 実際に使用される名前を使ってください。よくある間違い:
- メンバーは
types_membersに格納されます(struct_membersではありません)。列挙定数はtypes_enum_valuesに格納されます(enum_membersではありません)。 - SQL 関数
print_type()/exec_python()はありません。型を表示するにはSELECT definition FROM types WHERE ...を実行し、Python を実行するにはidapythonスキルを使用します。 - IDA 9 には
ida_structがありません。構造体/ユニオンはtypes/types_membersを通じて編集します(「固定レイアウト、ギャップ、復元」を参照)。 - フィールドへの参照を見つけるには、
struct_member_xrefsを使用します。instructions.disasm/instruction_operands.textをLIKE '%field%'で走査する方法は使用しないでください。
- メンバーは
引き継ぎパターン
- 意味的な影響を疑似コードで検証するには、
typesからdecompilerに引き継ぎます。 - 新たに型付けしたフィールドの名前付け/コメント付けには、
typesからannotationsに引き継ぎます。 - 複数の関数にわたる構造体の調整には、
typesからre-sourceに引き継ぎます。
型テーブル
local_types
データベースに保存されているローカル型宣言です。
ローカル型の一覧取得や絞り込みにはこれを使用し、より詳細な編集ワークフローには types* テーブルを使用してください。
| Column | Type | Description |
|---|---|---|
ordinal | INT | 型 ordinal(ローカル型 ID) |
name | TEXT | 型名 |
type | TEXT | 宣言された型テキスト |
is_struct | INT | 1=構造体 |
is_enum | INT | 1=列挙型 |
is_typedef | INT | 1=typedef |
-- Quick local type inventory
SELECT ordinal, name, type FROM local_types ORDER BY ordinal LIMIT 50;
正規のスキーマと所有者の対応については、../connect/references/schema-catalog.md(local_types)を参照してください。
types
すべてのローカル型定義です。INSERT(構造体/ユニオン/列挙型の作成)、UPDATE、DELETE、および folder_path によるローカル型フォルダーの整理に対応しています。
| Column | Type | Description |
|---|---|---|
ordinal | INT | 型 ordinal(一意の識別子) |
name | TEXT | 型名 |
folder_path | TEXT | Local Types ルートからの相対パスで指定する RW ローカル型フォルダー。NULL/'' はルートを意味します |
full_path | TEXT | 型名を含む RO フル dirtree パス |
size | INT | サイズ(バイト単位) |
kind | TEXT | struct/union/enum/typedef/func |
is_struct | INT | 1=構造体 |
is_union | INT | 1=ユニオン |
is_enum | INT | 1=列挙型 |
-- List all structs
SELECT ordinal, name, size FROM types WHERE is_struct = 1 ORDER BY size DESC;
-- List all enums
SELECT ordinal, name FROM types WHERE is_enum = 1;
-- Find types by name pattern
SELECT * FROM types WHERE name LIKE '%CONTEXT%';
-- Review type organization
SELECT ordinal, name, folder_path
FROM types
WHERE folder_path LIKE 'idasql/types/%'
ORDER BY folder_path, name;
パフォーマンス。 types WHERE ordinal = ? と types WHERE name = ? は直接
検索されます(単一の型を解決して表示します)。types WHERE name LIKE 'prefix%' も
最適化されており、名前を低コストで走査して一致するものだけを表示します。これらを
name LIKE '%substr%' より優先してください。後者にはショートカットがなく、すべての型を
表示するため(大きな IDB では低速です)、フィルターのない SELECT * FROM types にも同じことが当てはまります。
クエリータイムアウトによって範囲の広いクエリーが途中で打ち切られた場合でも、正常に終了し、次の
クエリーは引き続き実行できます。完全一致の名前/ordinal または 'prefix%' フィルターで範囲を絞ってください。
ローカル型の整理
型の復元用バケットには types.folder_path を使用し、空のフォルダーのライフサイクル管理には dirtree_folders を使用します。復元したレイアウトが下書き状態から検証済み状態へ移行する場合に便利です。
INSERT INTO dirtree_folders(tree, path)
VALUES ('local_types', 'idasql/types/recovered');
UPDATE types
SET folder_path = 'idasql/types/recovered'
WHERE name IN ('MY_HEADER', 'COMMAND_RECORD');
UPDATE types
SET folder_path = 'idasql/types/verified'
WHERE name = 'MY_HEADER';
UPDATE types SET folder_path = NULL WHERE name = 'MY_HEADER';
すべての IDA dirtree をまたいだ生データの閲覧には dirtree_entries を使用し、通常の型整理には types.folder_path を優先してください。フォルダーの書き込みでは相対 / パスを使用します。IDASQL は ./..、重複した区切り文字、バックスラッシュ、空でないフォルダーの削除、移動先がすでに存在するフォルダーの名前変更を拒否します。
local_type_bookmarks
bookmarks_t ストアを基盤とし、DIRTREE_LTYPES_BOOKMARKS dirtree によってフォルダーに対応するローカル型(Local Types ビュー)のブックマークです。完全な CRUD に対応しています。
| 列 | 型 | 読み書き | 説明 |
|---|---|---|---|
slot | INT | R | ストア内のブックマークスロット |
ordinal | INT | R | ローカル型の序数 |
type_name | TEXT | R | 序数から解決された型名 |
description | TEXT | RW | ブックマークの説明 |
inode | INT | R | Dirtree inode(dirtree にリンクされていない場合は -1) |
folder_path | TEXT | RW | フォルダーパス。NULL/'' はルートを意味します |
full_path | TEXT | R | Dirtree のフルパス |
-- Create a bookmark on a local type
INSERT INTO local_type_bookmarks(ordinal, description)
SELECT ordinal, 'review this struct' FROM types WHERE name = 'MY_STRUCT';
-- Edit / list / delete (derive the ordinal from the type name)
UPDATE local_type_bookmarks SET description = 'done'
WHERE ordinal = (SELECT ordinal FROM types WHERE name = 'MY_STRUCT');
SELECT slot, ordinal, type_name, description FROM local_type_bookmarks;
DELETE FROM local_type_bookmarks
WHERE ordinal = (SELECT ordinal FROM types WHERE name = 'MY_STRUCT');
注:新しく INSERT したブックマークは bookmarks_t ストアに作成されますが、dirtree には自動でリンクされません(そのため、リンクされるまで folder_path は NULL です)。また、現在、フォルダーの移動には、すでにリンクされているブックマークが必要です。ストアのスロットを対応する dirtree inode に確実にマッピングして INSERT 時に自動リンクすることは、既知の制限事項です。
型の作成
-- Create a struct
INSERT INTO types (name, kind) VALUES ('MY_HEADER', 'struct');
-- Create a union
INSERT INTO types (name, kind) VALUES ('PARAM_UNION', 'union');
-- Create an enum
INSERT INTO types (name, kind) VALUES ('CMD_TYPE', 'enum');
-- Verify creation (get the assigned ordinal)
SELECT ordinal, name, kind FROM types WHERE name = 'MY_HEADER';
型の削除
-- Delete a type by name
DELETE FROM types WHERE name = 'MY_HEADER';
-- Delete by ordinal (derive it from the name to avoid a magic number)
DELETE FROM types WHERE ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER');
既存の型を安全に調整する
型がすでに存在する場合は、宣言全体を再インポートするのではなく、対象を絞った types_members の編集を優先してください。メンバーの名前変更、型変更、コメント変更、削除の各操作では、既存のローカル型序数に対して IDA の UDM API を使用するため、依存するプロトタイプやメンバー型の参照は同じ型 ID を参照し続けます。
-- Capture the stable local type ID first
SELECT ordinal, name, kind FROM types WHERE name = 'MY_HEADER';
-- Rename and retype in place (ordinal derived from the type name)
UPDATE types_members
SET member_name = 'payload_len'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'len';
UPDATE types_members
SET member_type = 'unsigned __int16'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'payload_len';
-- Move a struct member by byte offset; this fixes the struct layout so IDA
-- preserves the explicit offset.
UPDATE types_members
SET offset = 16
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'payload_len';
-- Add a member into an existing fixed-layout gap
INSERT INTO types_members (type_ordinal, member_index, member_name, member_type, offset, comment)
SELECT ordinal, 2, 'flags', 'unsigned short', 8, 'inserted in place' FROM types WHERE name = 'MY_HEADER';
注:
- 書き込みでは
type_ordinalとmember_nameまたはmember_indexをキーにし、書き込み後に行を読み戻してください。 member_typeには、int、void *、char[64]、名前付きローカル型などの型テキストを指定できます。無効な型テキストは、暗黙にintにフォールバックするのではなく、エラーになります。offset/offset_bitsが現在サポートするのは、バイト境界に沿った構造体の移動です。ユニオンメンバーのオフセットはゼロのままです。- 新しい関連宣言の追加や、意図的な定義全体の再宣言には
parse_decls()を使用してください。復元済みの既存型を細かく調整する場合は、テーブルを編集する方が安全です。 - 複合型の場合は、参照先の型を編集する前後に
member_type_ordinalを読み取ってください。同じローカル型序数を参照し続けている必要があります。
-- Verify dependent type references stay attached to the same ordinal
SELECT h.member_name, h.member_type_ordinal, t.ordinal AS target_ordinal
FROM types_members AS h
JOIN types AS t ON t.name = 'MY_HEADER'
WHERE h.type_name = 'MY_PACKET'
AND h.member_name = 'header';
types_members
構造体およびユニオンのメンバーです。INSERT、UPDATE、DELETE に対応しています。
| 列 | 型 | 説明 |
|---|---|---|
type_ordinal | INT | 親型の序数 |
type_name | TEXT | 親型の名前 |
member_index | INT | 親型内のメンバーインデックス |
member_name | TEXT | メンバー名 |
offset | INT | バイトオフセット |
offset_bits | INT | ビットオフセット |
size | INT | メンバーサイズ |
size_bits | INT | メンバーのビット単位のサイズ |
member_type | TEXT | 型文字列(例:int、void *、char[256]) |
comment | TEXT | メンバーのコメント |
mt_is_ptr | INT | 1=ポインター |
mt_is_array | INT | 1=配列 |
mt_is_struct | INT | 1=埋め込み構造体 |
member_type_ordinal | INT | 参照先のローカル型序数、または -1 |
-- View members of a struct
SELECT member_name, member_type, offset, size
FROM types_members WHERE type_name = 'MY_HEADER'
ORDER BY offset;
-- Add members (member_type supports: int, void *, char[64], etc.).
-- Derive the ordinal from the type name so no magic ordinal is needed.
INSERT INTO types_members (type_ordinal, member_name, member_type)
SELECT ordinal, 'magic', 'unsigned int' FROM types WHERE name = 'MY_HEADER';
INSERT INTO types_members (type_ordinal, member_name, member_type)
SELECT ordinal, 'data_ptr', 'void *' FROM types WHERE name = 'MY_HEADER';
-- Insert at an explicit byte offset; offset_bits may be used for exact bits
INSERT INTO types_members (type_ordinal, member_name, member_type, offset)
SELECT ordinal, 'reserved', 'char[16]', 16 FROM types WHERE name = 'MY_HEADER';
-- Rename/retype/move a member in place
UPDATE types_members SET member_name = 'signature'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'magic';
UPDATE types_members SET member_type = 'DWORD'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'signature';
UPDATE types_members SET offset = 32
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'data_ptr';
-- Delete a member. DELETE leaves a gap (preserves the following members' offsets),
-- like IDA's Undefine — it never shifts them; see "Fixed layout, gaps & recovery".
DELETE FROM types_members
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'MY_HEADER') AND member_name = 'reserved';
固定レイアウト、ギャップ、復旧
構造体には2つのレイアウトモードがあります。自動レイアウト(デフォルト)では、IDA がメンバーのオフセットを再計算します。再パッキングによってフィールドが移動し、サイズが変わる場合があります。固定レイアウト(types.is_fixed = 1)では、すべてのオフセットが固定され、サイズを固定でき、空き領域がギャップとして公開されます。固定レイアウトを使うと、すでにマッピングしたバイトに影響を与えずに、復元した構造体をその場で調整できます。これにより、通常の編集で使われていた旧来の parse_decls() による全体再構築の回避策は不要になります。
| サーフェス | 意味 |
|---|---|
types.is_fixed(書き込み可能) | 1 にするとメンバーのオフセットが固定されます。0 にすると自動レイアウトに戻ります。IDA が再パッキング/圧縮を行うのは 固定→自動への遷移時のみ です(サイズが縮む場合があります)。すでに自動レイアウトの構造体に対する 0 は何もしません |
types.size(書き込み可能) | 固定 構造体の合計サイズを固定します(自動レイアウトの構造体ではエラーになります) |
types_members.is_gap | メンバーが IDA のギャッププレースホルダー(空き領域)の場合は 1 |
type_gaps | 構造体内の空きバイト範囲ごとに1行を返します。列は gap_offset、gap_size です(type_ordinal/type_name によるフィルターが必要です) |
DELETE は、どの構造体でも(自動レイアウトでも固定レイアウトでも)、スロットを ギャップ として残します(後続メンバーのオフセットと構造体のサイズは保持されます。IDA の Undefine と同様に、詰められません)。後続メンバーの位置がずれることはありません。ギャップ内のオフセットに対する INSERT は、隣接メンバーを移動せずにギャップを埋めます。明示的な offset が既存の(ギャップではない)メンバーと重なる INSERT は 拒否されます(「offset range overlaps an existing member」)。実際のフィールドを上書きすることはありません。type_gaps の空き範囲を対象にするか、offset を省略して末尾に追加してください。構造体を意図的に 圧縮 してサイズを縮める(ギャップを取り除いて再パッキングする)には、is_fixed = 1 の後に is_fixed = 0 を設定します。IDA が再パッキングを行うのは固定→自動への遷移時のみなので、すでに自動レイアウトの構造体に対する単純な is_fixed = 0 は何もしません。
-- Freeze layout, then see where the free space is
UPDATE types SET is_fixed = 1 WHERE name = 'VARBIND_VARIABLE';
SELECT gap_offset, gap_size FROM type_gaps WHERE type_name = 'VARBIND_VARIABLE';
SELECT member_name, "offset" FROM types_members
WHERE type_name = 'VARBIND_VARIABLE' AND is_gap = 1;
-- Absorb a gap: drop a real field into free space (neighbors stay put).
-- Derive the ordinal from the name so the snippet needs no magic number.
INSERT INTO types_members (type_ordinal, member_name, member_type, "offset")
SELECT ordinal, 'handler_cookie', 'int', 28 FROM types WHERE name = 'VARBIND_VARIABLE';
-- Non-collapsing delete: the slot becomes a gap; later offsets don't shift
DELETE FROM types_members
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'VARBIND_VARIABLE')
AND member_name = 'scratch';
-- Pin the total size of a fixed struct
UPDATE types SET size = 68 WHERE name = 'VARBIND_VARIABLE';
-- Deliberately compact (remove gaps, shrink): toggle fixed off
UPDATE types SET is_fixed = 0 WHERE name = 'VARBIND_VARIABLE';
復旧(調整には parse_decls() よりこちらを優先してください)。 以前の編集で固定構造体が不正な状態になった場合は、is_fixed = 1 に設定し、size を固定して、type_gaps/is_gap を確認して空き領域を見つけたうえで、メンバーを段階的に追加/移動/削除してください。parse_decls() による全体置換は、型を一から作成する場合や全面的に再定義する場合に限って使い、通常のメンバー調整には使わないでください。
types_enum_values
列挙定数の値です。INSERT、UPDATE、DELETE をサポートします。
| 列 | 型 | 説明 |
|---|---|---|
type_ordinal | INT | 列挙型の序数 |
type_name | TEXT | 列挙型名 |
value_name | TEXT | 定数名 |
value | INT | 定数値 |
-- View enum values
SELECT value_name, value FROM types_enum_values
WHERE type_name = 'CMD_TYPE'
ORDER BY value;
-- Add enum values (ordinal derived from the enum name; optional comment column)
INSERT INTO types_enum_values (type_ordinal, value_name, value)
SELECT ordinal, 'CMD_INIT', 0 FROM types WHERE name = 'CMD_TYPE';
INSERT INTO types_enum_values (type_ordinal, value_name, value)
SELECT ordinal, 'CMD_READ', 1 FROM types WHERE name = 'CMD_TYPE';
-- Rename / change value / comment / delete enum values in place
UPDATE types_enum_values SET value_name = 'CMD_OPEN'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'CMD_TYPE') AND value_name = 'CMD_INIT';
UPDATE types_enum_values SET value = 11, comment = 'opens a stream'
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'CMD_TYPE') AND value_name = 'CMD_OPEN';
DELETE FROM types_enum_values
WHERE type_ordinal = (SELECT ordinal FROM types WHERE name = 'CMD_TYPE') AND value_name = 'CMD_READ';
列挙値の編集では、既存の列挙型の序数が更新されます。列挙型がすでに構造体、プロトタイプ、オペランド表現、またはデコンパイラーの numforms で使用されている場合は、列挙型を再宣言するよりこの方法を優先してください。
ビットフィールド(ビットマスク)列挙型
ビットマスク列挙型 には OR で組み合わせるフラグメンバーがあり、一致するオペランド値は数値ではなく、(逆アセンブリでは)A or B、(疑似コードでは)A | B として表示されます。書き込み可能な types.is_bitmask 列で列挙型を指定し、書き込み可能な types.size 列でバイト幅を設定します。メンバーは通常どおり追加します(フラットなフラグで、それぞれの値が個別のマスクになります)。
-- 1) create the enum, make it a 4-byte bitmask
INSERT INTO types(name, kind) VALUES ('FILE_FLAGS', 'enum');
UPDATE types SET is_bitmask = 1, size = 4 WHERE name = 'FILE_FLAGS';
-- 2) add single-bit flag members
INSERT INTO types_enum_values(type_ordinal, value_name, value)
SELECT ordinal, 'FF_READ', 1 FROM types WHERE name='FILE_FLAGS'; -- + FF_WRITE 2, FF_EXEC 4
-- 3) apply it to an operand whose immediate is a combination (e.g. 3 = READ|WRITE)
UPDATE instructions SET operand1_format_spec = 'enum:FILE_FLAGS' WHERE addr = 0x401050;
-- now: SELECT disasm FROM instructions WHERE addr=0x401050; -> mov eax, FF_READ or FF_WRITE
-- SELECT line FROM pseudocode WHERE func_addr=0x401000; -> ... == (FF_READ | FF_WRITE)
is_bitmask は列挙型にのみ適用されます。size は 1/2/4/8 である必要があります。フラグと幅は、その後の値の編集後も保持されます。デコンパイラーへの反映はオペランドに依存します(cmp/test、または呼び出し引数の即値が確実なケースです)。ビットマスクメンバーの挿入時に value を省略すると、次に使える単一ビットマスク(1、2、4、…)が自動で割り当てられます。0 は有効なマスクではないため、値を指定しない挿入で 0 が割り当てられることはありません。自動マスクは列挙型の幅によって制限されます。1バイトのビットマスクで使えるのは 0x01..0x80 のみです。そのため、幅内のすべてのビットを使い切った後に値を指定せず挿入すると 失敗します(「no free single-bit mask remains within the enum width」)。types.size を広げるか、明示的に value を指定してください。
types_func_args
詳細な型分類を備えた関数プロトタイプの引数です。
| Column | Type | Description |
|---|---|---|
type_ordinal | INT | 関数型の序数 |
type_name | TEXT | 関数型名 |
arg_index | INT | 引数のインデックス(-1 = 戻り値の型、0+ = 引数) |
arg_name | TEXT | 引数名 |
arg_type | TEXT | 引数の型文字列 |
calling_conv | TEXT | 呼び出し規約(戻り値の行のみ) |
表層の型分類
記述どおりのリテラル型です。宣言で確認できる型です。
| Column | Description |
|---|---|
is_ptr | ポインター型の場合は1 |
is_int | 型が正確に int の場合は1 |
is_integral | 整数型に類する型(int、long、short、char、bool)の場合は1 |
is_float | float/double の場合は1 |
is_void | void の場合は1 |
is_struct | struct/union の場合は1 |
is_array | 配列の場合は1 |
ptr_depth | ポインターの深さ(int** = 2) |
base_type | ポインターを取り除いた型 |
解決後の型分類
typedef の解決後、つまり実際の型です。
| Column | Description |
|---|---|
is_ptr_resolved | 解決後の型がポインターの場合は1 |
is_int_resolved | 解決後の型が正確に int の場合は1 |
is_integral_resolved | 解決後の型が整数型に類する場合は1 |
is_float_resolved | 解決後の型が float/double の場合は1 |
is_void_resolved | 解決後の型が void の場合は1 |
ptr_depth_resolved | 解決後のポインターの深さ |
base_type_resolved | ポインターを取り除いた解決後の型 |
この二重の分類は、typedef を考慮したクエリに不可欠です。たとえば、HANDLE は表層では非ポインターとして表示されますが、解決後は void * になります。
-- Typedefs that hide pointers (HANDLE, HMODULE, etc.)
SELECT DISTINCT type_name, arg_type, base_type_resolved
FROM types_func_args
WHERE is_ptr = 0 AND is_ptr_resolved = 1;
-- Functions with struct parameters
SELECT type_name, arg_name, arg_type FROM types_func_args
WHERE arg_index >= 0 AND is_struct = 1;
文字列引数、ポインター数、戻り値の型によるフィルターなど、types_func_args のクエリパターンについては、references/type-patterns.md を参照してください。
型ビュー
型をフィルタリングするための便利なビューです。
| View | Description |
|---|---|
types_v_structs | SELECT * FROM types WHERE is_struct = 1 |
types_v_unions | SELECT * FROM types WHERE is_union = 1 |
types_v_enums | SELECT * FROM types WHERE is_enum = 1 |
types_v_typedefs | SELECT * FROM types WHERE is_typedef = 1 |
types_v_funcs | SELECT * FROM types WHERE is_func = 1 |
types_v_inheritance | struct/class の継承関係(types_members の基底クラス) |
types_v_inheritance ビュー
基底クラスメンバーから抽出した struct/class の継承関係を表示します。
| Column | Type | Description |
|---|---|---|
derived_ordinal | INT | 派生型の序数 |
derived_name | TEXT | 派生型の名前 |
base_type_name | TEXT | 基底型の名前 |
base_ordinal | INT | 基底型の序数 |
base_offset | INT | 派生型内における基底型のバイトオフセット |
-- Find base classes of a type
SELECT * FROM types_v_inheritance WHERE derived_name = 'MyClass';
-- Recursive ancestors
WITH RECURSIVE ancestors(name, depth) AS (
SELECT base_type_name, 1 FROM types_v_inheritance WHERE derived_name = 'MyClass'
UNION ALL
SELECT i.base_type_name, a.depth + 1
FROM types_v_inheritance i JOIN ancestors a ON i.derived_name = a.name
WHERE a.depth < 10
)
SELECT * FROM ancestors;
C 宣言のインポート(parse_decls)
parse_decls(text) は C 宣言をローカル型ライブラリにインポートします。関連する型、typedef、enum、宣言全体を登録するのに適しています。既存の復元済み型を少し調整する場合は、ローカル型の序数を安定させ、既存の参照を再構築せずに済むよう、types_members の更新を優先してください。
-- Import a simple struct
SELECT parse_decls('
struct MY_HEADER {
unsigned int magic;
unsigned int version;
unsigned int size;
void *data;
};
');
-- Import with pragmas for packing (enums, typedefs, nested unions)
SELECT parse_decls('
#pragma pack(push, 1)
typedef enum operations_e { op_empty=0, op_open=11, op_read=22 } operations_e;
typedef union command_payload_u { void *ptr; unsigned __int64 qword; } command_payload_u;
typedef struct command_t {
operations_e cmd_id;
command_payload_u payload;
unsigned __int64 ret;
} command_t;
#pragma pack(pop)
');
-- Verify imported types
SELECT name, kind, size FROM types WHERE name IN ('command_t', 'operations_e');
ネストした union を含む、複数の構造体を扱う parse_decls の詳しい例については、references/type-patterns.md を参照してください。
関数と変数への型の適用
関数プロトタイプ
-- Apply type to function via prototype column
UPDATE funcs SET prototype = 'void __fastcall exec_command(command_t *cmd);'
WHERE addr = 0x140001BD0;
-- Apply/replace the type at any mapped address
INSERT INTO applied_types(addr, decl)
VALUES (0x140001BD0, 'void __fastcall exec_command(command_t *cmd);');
-- Read current type at address
SELECT decl, ordinal, type_name
FROM applied_types
WHERE addr = 0x140001BD0;
-- Address equality also accepts numeric strings and symbol names
UPDATE applied_types
SET decl = 'void __fastcall exec_command(command_t *cmd);'
WHERE addr = 'exec_command';
-- Clear type (reset to auto-detected)
DELETE FROM applied_types WHERE addr = 0x140001BD0;
-- Re-decompile to see effect
SELECT decompile(0x140001BD0, 1);
applied_types のポイント検索は、書き込みやすさを意図した設計です。WHERE addr = X は、宣言がまだ適用されていない場合も、decl、ordinal、type_name が NULL のマッピング済み行を1行返します。範囲スキャンでは、現在、適用済みの型情報があるアドレスのみが返されます。
ローカル変数
-- Change local variable type
UPDATE ctree_lvars SET type = 'MY_STRUCT *'
WHERE func_addr = 0x401000 AND idx = 0;
-- Change and verify
SELECT decompile(0x401000, 1);
SELECT idx, name, type FROM ctree_lvars
WHERE func_addr = 0x401000 AND idx = 0;
呼び出しサイト
関数プロトタイプとローカル変数の型を使っても特定の呼び出しの型情報が不十分な場合は、間接呼び出しに呼び出しサイトの型付けを使用します。
-- Discover indirect call sites first
SELECT call_addr, target_op, target_var_name, arg_count
FROM ctree_v_indirect_calls
WHERE func_addr = 0x140001BD0
ORDER BY call_addr;
-- Apply a prototype to one call site
UPDATE disasm_calls
SET callee_type = 'int __fastcall emit_message(const char *name, const char *target, int flag, const char *tag);'
WHERE addr = 0x140001C3E;
-- Verify the persisted call-site typing
SELECT callee_type FROM disasm_calls WHERE addr = 0x140001C3E;
SELECT call_arg_addrs(0x140001C3E);
SELECT decompile(0x140001BD0, 1);
型付けサーフェスの一覧
| サーフェス | 対象範囲 | 意味解析か表示のみか | 典型的な用途 |
|---|---|---|---|
UPDATE funcs SET prototype = ... / applied_types | 関数/グローバルアドレス | 意味解析 | 関数またはグローバルに適切な宣言型を設定します |
UPDATE ctree_lvars SET type = ... | 逆コンパイルされたローカル変数/引数 1 つ | 意味解析 | ローカル変数のポインター/構造体の推論を整理します |
UPDATE disasm_calls SET callee_type = ... WHERE addr = ... | 呼び出し箇所 1 つ | 意味解析 | 呼び出し先のプロトタイプを明示する必要がある間接呼び出しを修正します |
instructions.operand*_format_spec | 逆アセンブルのオペランド 1 つ | 表示のみ | リスト出力に列挙型/構造体のオフセットを表示します |
set_union_selection* | デコンパイラー式 1 つ | 表示のみ | 見やすい疑似コードになるよう、共用体のメンバーを選択します |
set_numform* | デコンパイラー式のオペランド 1 つ | 表示のみ | 基本型を変更せずに数値の表示形式を変更します |
名前
-- Set a name at address (or replace any existing name at that EA)
INSERT INTO names(addr, name) VALUES (0x402000, 'g_config');
-- Equivalent: rename in place
UPDATE names SET name = 'g_config' WHERE addr = 0x402000;
注:names に対する INSERT と UPDATE は、どちらも IDA の set_name(addr, name, SN_CHECK) を呼び出します。IDA ではアドレスごとに名前を 1 つしか設定できないため、すでに名前が付いている EA に対する INSERT は置き換えます。また、SN_CHECK は新しい名前の文字列がグローバルに重複する場合、自動的に名前を区別します(foo → foo_0)。実際に保存された名前を確認するには、行を読み戻してください。
逆アセンブルにおける構造体オフセットの表現
instructions テーブルの operand*_format_spec 列を使うと、逆アセンブルのオペランドに構造体オフセットを表示できます。
-- Apply struct-offset: makes `[rax+10h]` display as `[rax+MY_STRUCT.field_name]`
UPDATE instructions SET operand0_format_spec = 'stroff:MY_STRUCT,delta=0'
WHERE addr = 0x401030;
-- Nested member path: separate type names with '/'
UPDATE instructions SET operand0_format_spec = 'stroff:OUTER_T/INNER_T'
WHERE addr = 0x401030;
-- sizeof: an immediate equal to sizeof(STRUCT) renders as `size STRUCT`
UPDATE instructions SET operand1_format_spec = 'sizeof:MY_STRUCT'
WHERE addr = 0x4015EB;
-- Apply enum: `enum:<ENUM_NAME>`; clear back to plain: `clear`
UPDATE instructions SET operand1_format_spec = 'enum:MY_ENUM'
WHERE addr = 0x401020;
数値/オフセット/強制/文字表示形式(hex/dec/oct/bin、char、
offset[:base]、forced:<text>、および ,signed/,bnot 修飾子)も
operand*_format_spec を通じて適用します。利用できる形式の全一覧については、
disassembly スキルを参照してください。
逆コンパイルされたコードにおける列挙型/共用体の表示
numform ヘルパー(set_numform*)と共用体選択ヘルパー(set_union_selection*)については、decompiler スキルを参照してください。
disasm_calls.callee_type は表示のみの側ではなく、意味解析側に属します。これは、表示のみの列挙型/共用体の書式設定ヘルパーとは異なり、呼び出し解析に影響するためです。
パフォーマンス上のルール
| テーブル | アーキテクチャ | 主な制約 | 備考 |
|---|---|---|---|
types | キャッシュ済み | ordinal(任意) | 必要に応じてキャッシュ全体を再構築します。通常は高速です(型が 1000 個未満の場合) |
types_members | キャッシュ済み | type_ordinal | 制約があれば O(1) で検索できます。制約がない場合はすべての型を走査します |
types_enum_values | キャッシュ済み | type_ordinal | 制約があれば O(1) で検索できます |
types_func_args | キャッシュ済み | type_ordinal | 制約があれば O(1) で検索できます |
主なルール:
type_ordinal制約のプッシュダウンにより、単一の型のメンバー、列挙値、または関数引数に O(1) でアクセスできます。- 制約がない場合、これらのテーブルはすべてのローカル型を走査します。通常は高速ですが(ほとんどのバイナリではローカル型が 1000 個未満です)、対象が分かっている場合はフィルターを適用したクエリを優先してください。
- 型ビュー(
types_v_structsなど)はあらかじめフィルターされています。分類別のクエリにはこれらを使用してください。 - 複数の型を一度に登録するには、
parse_decls()が最速の方法です(複数のINSERTではなく、1 回の呼び出しで済みます)。
関連項目
xrefs—struct_member_xrefsは、構造体/共用体メンバーへの参照を検索します (type_name/type_ordinal/member_idでフィルターします)。ここで 型/メンバーを解決した後は、逆アセンブルテキストの走査よりも適切なツールです。annotations—funcs.prototype/applied_typesを使って型を適用します。名前の変更やコメントと組み合わせてください。decompiler— ctree は適用された型を使用します。共用体の選択、numform、変更のループについてはこちらを参照してください。re-source— オフセットキャストから構造を復元する方法です。
その他のリソース
- 型を扱うワークフローの全例と高度な CTE パターンについては、references/type-patterns.md を参照してください。