关于 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
详细介绍
这项 skill 是通过 idasql 暴露的 IDA 类型系统的权威参考。如需了解使用类型的标注工作流,请参阅 annotations。如需了解反编译器专属的类型交互(ctree、lvars、联合体成员选择、numform),请参阅 decompiler。
触发意图
在用户要求以下操作时使用此 skill:
- 创建/编辑结构体、联合体、枚举、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;
解读指南:
- 先盘点类型,并优先处理规模大、扇出高的类型。
- 使用
types_func_args中已解析的字段进行 typedef 感知推理。
失败与恢复
- 类型插入/更新失败:
- 验证声明语法以及目标序号/名称是否存在。
- 类型信息相互冲突/不完整:
- 在提交更改前,结合
decompiler(ctree_lvars、调用参数)进行核对。
- 在提交更改前,结合
- 反汇编显示异常:
- 重新检查操作数格式设置和已应用的声明。
- 使用实际存在的名称——常见错误:
- 成员存储在
types_members中(不是struct_members);枚举常量存储在types_enum_values中(不是enum_members)。 - 没有
print_type()/exec_python()SQL 函数——使用SELECT definition FROM types WHERE ...渲染类型;通过idapythonskill 运行 Python。 - 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* 表。
| 列 | 类型 | 说明 |
|---|---|---|
ordinal | INT | 类型序号(本地类型 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 组织本地类型文件夹。
| 列 | 类型 | 说明 |
|---|---|---|
ordinal | INT | 类型序号(唯一标识符) |
name | TEXT | 类型名称 |
folder_path | TEXT | RW 本地类型文件夹相对于 Local Types 根目录的路径;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 也是如此。如果
宽泛查询因查询超时而中止,它会正常返回,后续查询仍可使用——通过精确的名称/序号或
'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
本地类型(Local Types 视图)书签,由 bookmarks_t 存储区提供支持,并通过
DIRTREE_LTYPES_BOOKMARKS dirtree 支持文件夹。支持完整的 CRUD 操作:
| 列 | 类型 | RW | 说明 |
|---|---|---|---|
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';
固定布局、空隙与恢复
结构体有两种布局模式。自动布局(默认):IDA 会重新计算成员偏移量——重新打包可能会移动字段并改变大小。固定布局
(types.is_fixed = 1):每个偏移量都会被冻结,大小可以固定,空余空间会以空隙形式显示。使用固定布局可以就地完善恢复出的结构体,而不会影响已映射的字节——对于常规编辑,这取代了旧的 parse_decls() 全量重建变通方案。
| 界面 | 含义 |
|---|---|
types.is_fixed(可写) | 1 会冻结成员偏移量;0 会恢复为自动布局——IDA 仅在固定布局→自动布局的转换时重新打包/压缩(可能缩小),因此对已经是自动布局的结构体设置 0 不会产生任何效果 |
types.size(可写) | 固定固定布局结构体的总大小(对自动布局结构体操作会报错) |
types_members.is_gap | 如果成员是 IDA 的空隙占位符(空余空间),则为 1 |
type_gaps | 结构体中每个空余字节范围对应一行:gap_offset、gap_size(需要使用 type_ordinal/type_name 过滤) |
对任意结构体(自动布局或固定布局)执行 DELETE 时,槽位会保留为空隙(后续成员的偏移量和结构体大小都会保留——不会收缩,类似 IDA 的 Undefine),不会移动其后的成员。在空隙内某个偏移量执行 INSERT 会吸收该空隙,而不会移动相邻成员。如果 INSERT 的显式 offset 与现有(非空隙)成员重叠,则会被拒绝(“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
具有深层类型分类的函数原型参数。
| 列 | 类型 | 描述 |
|---|---|---|
type_ordinal | INT | 函数类型序号 |
type_name | TEXT | 函数类型名称 |
arg_index | INT | 参数索引(-1 = 返回类型,0+ = 参数) |
arg_name | TEXT | 参数名称 |
arg_type | TEXT | 参数类型字符串 |
calling_conv | TEXT | 调用约定(仅返回行) |
表层类型分类
按字面写出的类型 — 即声明中显示的内容:
| 列 | 描述 |
|---|---|
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 解析后 — 即类型的实际含义:
| 列 | 描述 |
|---|---|
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。
类型视图
用于筛选类型的便捷视图:
| 视图 | 描述 |
|---|---|
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 | 结构体/类的继承关系(来自 types_members 的基类) |
types_v_inheritance 视图
显示从基类成员中提取的结构体/类继承关系。
| 列 | 类型 | 描述 |
|---|---|---|
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、枚举和完整声明。若要对现有恢复类型进行小幅调整,建议更新 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');
有关包含嵌套联合体的多结构体 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。范围扫描仅返回当前已应用类型信息的地址。
局部变量
-- 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 = ... | 单个反编译局部变量/参数 | 语义性 | 修正局部指针/结构体推断 |
UPDATE disasm_calls SET callee_type = ... WHERE addr = ... | 单个调用点 | 语义性 | 当被调函数原型必须明确指定时,修正间接调用 |
instructions.operand*_format_spec | 单条反汇编指令的一个操作数 | 仅渲染 | 在列表输出中显示枚举/结构体偏移 |
set_union_selection* | 单个反编译表达式 | 仅渲染 | 选择联合体成员,让伪代码更易读 |
set_numform* | 单个反编译表达式操作数 | 仅渲染 | 更改数值的显示方式,而不更改基本类型 |
名称
-- 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 在每个地址只能有一个名称,因此对已有名称的 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)。
另请参阅
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