UTXO_Compiler 调试器用户使用手册
本文档介绍 UTXO_Compiler 内置 CLI 调试器的使用方法,适用于合约源码(.ct)的交互式调试。
1. 概述
1.1 功能简介
- UTXO_Compiler Debugger 在编译后的字节码上运行一台 BVM(字节码虚拟机)模拟器,支持:
- 断点(按行、按函数)
- 单步执行(进入、跳过、跳出函数)
- 查看源码、字节码、栈、调用栈
- 交易数据加载与查看(合约调试场景)
1.2 启动条件
- 项目需在 启用调试器 的情况下构建(
BUILD_DEBUGGER)。 - 启动调试器会先对源文件进行隐式编译,再进入交互式 REPL。
2. 启动调试器
2.1 命令行
./utxo_compiler <源文件.ct> --debug可选参数(与正常编译一致):
| 选项 | 说明 |
|---|---|
--debug | 启动交互式调试器(同时启用调试信息) |
--allow-subscope-altstack / --asa | 允许在子作用域(if/else、私有函数)中使用 setAlt/setMain |
-l <level> / --log-level <level> | 设置日志级别(如 debug、info、warning) |
示例:
./utxo_compiler contract.ct --debug
./utxo_compiler contract.ct --debug --asa2.2 启动流程
- 编译:对
源文件.ct进行编译,生成字节码与调试信息;若编译失败,会输出错误并退出。 - 函数与参数(可选):若调试信息中存在函数列表,会提示:
- 选择要调试的函数:输入编号
1~N只调试该函数;直接回车则调试整个文件,并为所有公有函数依次输入参数。 - 参数输入格式(每个参数可任选其一):
- 整数:
42、-100、0x1a(十六进制) - 十六进制字节:
0x1234abcd - 字符串:
"hello"(双引号包围) - 回车:使用该参数类型的默认值
- 整数:
- 选择要调试的函数:输入编号
- 进入 REPL:显示 “UTXO_Compiler Debugger v1.0” 及加载的源文件名,提示输入
help查看命令。
3. 命令总览
命令不区分大小写;多数命令有简写。下表为速查。
| 类别 | 命令(简写) | 说明 |
|---|---|---|
| 执行控制 | run / r | 开始/重新开始执行 |
reset | 重置虚拟机到初始状态 | |
continue / c | 从暂停处继续执行 | |
step / s | 单步进入 | |
next / n | 单步跳过 | |
finish / f | 跳出当前函数 | |
pause | 暂停执行 | |
| 断点 | break / b <行号|\函数名> | 设置行断点或函数断点 |
delete / d <ID> | 删除断点 | |
disable <ID> | 禁用断点 | |
enable <ID> | 启用断点 | |
info breakpoints / info bp | 列出所有断点 | |
| 查看 | list / l [行号] | 显示源码(默认当前行附近) |
stack | 显示主栈与副栈(支持参数) | |
backtrace / bt | 显示调用栈 | |
bytecode / bc [N] | 显示字节码(可选上下文条数 N) | |
| 交易 | settxfile <文件> | 从文件加载交易数据 |
showtx | 显示当前交易数据 | |
| 其他 | help / h | 显示帮助 |
quit / q / exit | 退出调试器 | |
clear | 清屏 |
4. 执行控制
4.1 run / r
- 作用:开始执行或从当前状态重新执行(不会重置 VM)。
- 说明:若之前已设置初始栈(如函数参数),会从当前 PC 继续;通常与
reset配合实现“重新跑一遍”。
4.2 reset
- 作用:将虚拟机重置到初始状态(PC、栈等恢复为进入 REPL 时状态)。
- 说明:断点保留;之后可用
run或step/next重新执行。 - 注意:
reset不会清除已设置的断点,也不会清除通过settxfile加载的交易数据。
4.3 continue / c
- 作用:在 VM 处于暂停状态时,从当前断点/单步处继续执行,直到再次命中断点、单步、结束或错误。
- 说明:若 VM 未暂停,会提示“VM未暂停,无法继续”。
4.4 step / s(单步进入)
- 作用:执行一条指令;若该指令是“调用”,会进入被调用函数。
- 说明:仅在 VM 为 READY 或 PAUSED 时有效。
4.5 next / n(单步跳过)
- 作用:执行到“当前栈帧”的下一条语句;若当前语句包含调用,不会进入被调用函数内部。
- 说明:仅在 VM 为 READY 或 PAUSED 时有效。
4.6 finish / f(跳出函数)
- 作用:继续执行直到当前函数返回,停在调用方。
- 说明:仅在 VM 为 READY 或 PAUSED 时有效。
4.7 pause
- 作用:在 VM 正在运行时请求暂停(例如正在
run或continue中)。 - 说明:若 VM 未在运行,会提示“VM未运行,无法暂停”。
4.8 VM 状态与生命周期(了解即可)
- READY:初始/重置后的状态,尚未开始执行;此时适合用
run、step、next或finish开始调试。 - RUNNING:正在连续执行脚本;可使用
pause请求暂停,或等待命中断点/执行完成。 - PAUSED:因命中断点、单步完成或手动
pause而停下;此时可使用continue或再次单步(step/next/finish)。 - STEP_MODE:内部用于处理单步逻辑的临时时态,用户通常只在开始和结束时看到“单步进入/跳过/跳出完成”等提示。
- FINISHED:到达当前执行范围或字节码结尾;CLI 会打印“程序执行完成”,如需再次运行请先
reset,或直接run(内部会隐式重新start)。 - ERROR:执行过程中发生错误(如栈下溢、未知指令等);CLI 会显示“错误: ...”,通常需要
reset后重新尝试。
5. 断点管理
5.1 设置断点:break / b
按行:
break <行号>
示例:break 11、b 20
在源文件对应行设置断点;行号会解析为字节码位置(可能对应多条指令)。按函数:
break <函数名>
示例:break main、b myFunc
在该函数入口处设置断点。设置成功会输出断点 ID 及位置;断点会经
resolveBreakpoints解析到具体 PC。
5.2 删除断点:delete / d
- 用法:
delete <断点ID>
示例:delete 1、d 2
按 ID 删除断点;若 ID 不存在会提示。
5.3 禁用/启用:disable / enable
- 禁用:
disable <断点ID>— 断点保留但不触发。 - 启用:
enable <断点ID>— 重新生效。
5.4 查看断点:info breakpoints / info bp
- 列出所有断点,包括:ID、描述(行断点/函数断点)、状态(启用/禁用/待解析)、命中次数。
6. 查看信息
6.1 list / l [行号]
- 无参数:以当前 PC 对应的源码行为中心,显示前后各 10 行;当前行用
=>标出。 - 有参数:
list <行号>以该行为中心显示上下文。 - 若未加载到源码,会显示“(源码未加载)”。
6.2 stack
stack 用于查看当前 VM 的栈状态,包括主栈与副栈。
基本用法
stack
显示 主栈 与 副栈 的当前状态(从栈顶到底),每项以十六进制形式显示。
行首[...]中的数字为从栈底开始的绝对索引,用于与执行语义对照。stack main/stack alt/stack both
仅显示主栈 / 仅显示副栈 / 同时显示两者。
按“高度(index,以栈底为 0)”查看
在下面的参数中,高度/索引统一采用“栈底为 0”的定义:
index = 0表示栈底;index越大越靠近栈顶;CLI 输出中的
[...]与这里的索引一致,都是从栈底开始的绝对索引。stack [main|alt|both] --near <H> [C]
显示栈上某个高度附近的数据:H:目标高度(从栈底开始,H = 0为栈底);C:上下文条数(可选,默认5),实际显示范围为 [H − C, H + C],超出范围会自动裁剪。
stack [main|alt|both] --range <A:B>或stack [main|alt|both] -r <A:B>
显示高度范围 [A, B] 内的元素(含端点):A、B都是从栈底开始的高度(0为栈底);- 若
A > B,内部会自动交换两者。
提示:
- 若不带任何参数,则等价于
stack both,显示主栈与副栈的全部内容;- 上述参数只影响“显示哪些元素”,不改变栈本身的内容。
6.3 backtrace / bt
- 显示调用栈:从当前帧到最外层,每层显示帧号、函数名、调用位置(源文件:行号)。
6.4 bytecode / bc [N]
- 无参数:列出全部字节码,并标出当前 PC(
=>),格式为:PC | 源码行号 | 指令。 - 有参数:
bytecode <N>只显示当前 PC 前后各 N 条的上下文。 - 源码行号来自调试信息,无对应行时显示
-。
7. 停止时的自动显示
- 当因断点命中、单步暂停或步进完成而停止时,若未关闭“停止时显示源码”选项,调试器会自动:
- 输出当前停止原因;
- 调用“当前位置”显示:源位置、PC、当前指令、以及当前行附近的源码(
showCurrentLocation)。
8. 交易数据管理(合约调试)
适用于依赖“交易上下文”的合约(如使用 OP_PUSH_META 等)。
8.1 settxfile <文件名>
- 作用:从文本文件加载交易相关数据到 VM,供执行时使用(主要用于配合
OP_PUSH_META调试交易元数据)。 - 文件格式:每行一个键值对
KEY:VALUE;行内#之后为注释;键不区分大小写。 - 支持的键(与
OP_PUSH_META条件值的对应关系):
| 键 | 说明 |
|---|---|
version | 交易版本 |
locktime | 锁定时间 |
inputCount | 输入数量 |
outputCount | 输出数量 |
inputsHash | 输入数据哈希 |
unlockingInput | 当前正在解锁的输入数据 |
outputsHash | 输出数据哈希 |
- 数值均为
0x十六进制;version、locktime、inputCount、outputCount大小为4字节,小端序;加载成功后可用showtx查看。 settxfile不会自动重置或重新执行脚本,一般在加载或更新交易数据后,需要配合reset/run或单步命令重新调试。
示例文件片段:
version: 02000000
locktime: 20a10700
inputCount: 02000000
outputCount: 01000000
inputsHash: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef
unlockingInput: 02ff01ab
outputsHash: 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff8.2 showtx
- 显示当前已加载的交易数据:version、locktime、inputCount、outputCount、inputsHash、unlockingInput、outputsHash;二进制字段以十六进制打印。
- 若未加载,会提示使用
settxfile <文件名>加载。
9. 其他命令
- help / h:在 REPL 内显示完整命令列表与简短说明。
- quit / q / exit:退出调试器。
- clear:清屏(输出多行空行)。
10. 命令历史与输入
- 调试器会保留最近约 100 条命令历史(仅用于内部记录)。
- 输入时首尾空格会被忽略;命令名会转为小写再匹配,因此大小写不敏感。
11. 错误与状态提示
- 执行/单步:若 VM 未就绪或未暂停,会提示对应状态(如“VM未暂停,无法继续”、“VM未就绪,无法单步执行”)。
- 断点:无效断点 ID 或无法解析的行号/函数名会给出明确错误或警告。
- 交易文件:无法打开文件、键值格式错误或数值解析失败时,会输出错误并说明行号或键名。
- 执行完成:到达执行范围或脚本末尾时,会输出“程序执行完成”;此时栈顶/栈内容即为最终执行结果,可通过
stack查看。 - 运行时错误:发生 VM 内部异常(如未知指令、栈操作非法等)时,会输出“错误: ...”,并进入错误状态;通常需要
reset后重新执行。
12. 典型使用流程示例
启动并选函数/参数
bash./apc my.ct --debug按提示选择要调试的函数(或回车为所有公有函数填参数)。
设断点并运行
text(apc-debug) break 10 (apc-debug) break main (apc-debug) info breakpoints (apc-debug) run停止后查看
text(apc-debug) list (apc-debug) stack (apc-debug) backtrace单步与继续
text(apc-debug) next (apc-debug) step (apc-debug) continue需要交易数据时
text(apc-debug) settxfile test/tx_transaction_test.txt (apc-debug) showtx (apc-debug) run重新运行
text(apc-debug) reset (apc-debug) run退出
text(apc-debug) quit
13. 与构建/编译的关系
- 调试器模式(
--debug)会自动启用调试信息并隐式编译指定源文件,无需单独传-d或--debug-output。 - 若需在非调试模式下仅生成调试信息(如导出到文件),请使用
-d或--debug-output <file>,详见编译器帮助:apc -h。