3. TRACE32命令系统与调试对象
TRACE32 的调试能力并不是靠某一个“万能命令”完成的,而是由一套分层、可组合的命令系统支撑。理解这套命令系统,关键不是背命令表,而是先分清“命令作用于什么对象、返回什么结果、结果如何被脚本消费”。本节围绕四件事展开:命令分类、寄存器与内存访问、符号与调试信息加载、返回值处理。
一、常用调试命令的分类逻辑
TRACE32 命令按作用对象大致可分为四类,这个分类直接决定了脚本中命令的书写顺序和参数形式。
- 运行控制类:
Go、Break、Step、StepOver、Wait。它们改变 CPU 的执行状态,通常不返回数据,而是改变调试会话的“当前状态”。 - 数据访问类:
Data.List、Data.Set、Register.View、Register.Set。它们读写寄存器、内存、外设地址,是脚本获取现场信息的主要手段。 - 符号与调试信息类:
Data.Load、Data.LOAD.Elf、Symbol.SourcePATH、List.auto。它们把可执行文件、符号表、源码路径与调试器关联起来。 - 脚本与流程类:
PRINT、IF、WHILE、GOSUB、RETURN、ENTRY。它们不直接操作目标,而是组织命令的执行顺序和结果判断。
分类的意义在于:运行控制类命令往往改变状态,数据访问类命令产生可读取的值,符号类命令决定“地址能否翻译成名字”,脚本类命令负责把这些值串成判断逻辑。脚本出错时,先判断错误发生在哪一类,比逐行猜测更高效。
二、CPU 寄存器与内存访问
寄存器访问使用 Register 命令族。查看单个寄存器可用 Register.View R0,批量查看可用 Register.View 配合窗口或 PRINT。修改寄存器用 Register.Set R0 0x12345678。需要注意:寄存器宽度与目标架构相关,ARM Cortex-M 的 R0 是 32 位,而 AArch64 的 X0 是 64 位,脚本中若用固定掩码会出错。
内存访问使用 Data 命令族。读取一段内存的典型写法是:
Data.List 0x20000000 /Long 16
Data.Set 0x20000010 %Long 0xDEADBEEF
Data.List 0x20000010 /Long 1
这里 /Long 表示按 32 位字长解释,16 表示读取 16 个单元。地址、字长、数量三者必须匹配,否则读出的值会与预期错位。对于外设寄存器,建议使用 /Long 或 /Word 明确宽度,避免默认字长带来的歧义。
Break,再读取。三、符号与调试信息加载
符号加载决定调试器能否把地址显示为函数名、变量名和源码行。常用命令是 Data.Load 或 Data.LOAD.Elf,加载时通常需要指定文件路径和加载选项。例如:
Data.LOAD.Elf demo.elf /NoClear
Symbol.SourcePATH C:\project\src
List.auto
/NoClear 表示加载符号时不自动清除已有符号,适合分模块加载;Symbol.SourcePATH 告诉调试器源码根目录,使源码行能正确关联;List.auto 让列表窗口自动跟随当前 PC。若符号加载后仍显示地址而非函数名,优先检查三件事:ELF 是否包含调试段、加载地址与链接地址是否一致、源码路径是否可访问。
四、命令返回值处理
TRACE32 脚本中,命令的返回值通常通过 PRINT 或函数形式获取。例如 PRINT Register(R0) 可输出 R0 的值,PRINT Data.Long(0x20000000) 可读取一个 32 位内存值。返回值可以参与条件判断:
IF Register(PC) == 0x08000100
(
PRINT "Hit entry point"
Go
)
ELSE
(
PRINT "PC = " Register(PC)
)
返回值处理的关键是类型与比较方式。寄存器值通常按无符号整数处理,若需要按有符号解释,应显式转换。内存读取要指定字长,否则默认宽度可能与预期不同。对于返回字符串的命令,比较时应使用字符串比较而非数值比较。
五、脚本中的典型组合与判断依据
把上述四部分串起来,一个可复用的脚本片段通常包含:加载符号、设置断点、运行到断点、读取寄存器与内存、根据返回值判断、输出结果。例如判断某函数是否被调用,可以先在函数入口设断点,运行后检查 PC 是否等于函数地址,再读取参数寄存器。若返回值符合预期,则记录“命中”;否则记录“未命中”并继续运行。
判断依据要明确:寄存器比较用精确值或范围,内存比较用字长和掩码,符号比较用名称或地址。脚本中不要依赖“看起来对”的模糊判断,而应把每个条件的阈值、字长、比较方式写清楚。这样即使目标程序变化,脚本仍能给出可解释的结果。
/Long 与 /long 在不同版本中可能表现不同,建议统一使用官方文档中的写法,并在脚本中保持一致的命名风格。掌握命令分类、寄存器与内存访问、符号加载和返回值处理这四块,就具备了编写可判断、可复用调试脚本的基础。后续更复杂的自动化流程,都是在这四块之上组合出来的。