ARM RealView Debugger是ARM公司开发的一款专业级调试工具,主要面向嵌入式系统开发人员。作为ARM开发工具链的重要组成部分,它提供了强大的底层调试能力,特别适合ARM架构处理器的开发调试工作。
在实际嵌入式开发中,调试器命令是开发者的"瑞士军刀"。与常见的IDE集成调试器不同,RealView Debugger提供了更底层的控制能力,允许开发者直接与处理器和内存交互。这种细粒度的控制对于嵌入式系统开发至关重要,特别是在以下场景:
提示:RealView Debugger的命令行界面虽然学习曲线较陡,但一旦掌握可以大幅提高调试效率,特别是在处理复杂的内存问题时。
EXPAND命令是调试过程中查看函数调用栈和局部变量的利器。它的基本语法如下:
code复制EXPAND [@stack_level] [{,windowid | ,fileid}]
这个命令的核心功能是显示指定栈帧中的参数和局部变量值。当程序在断点处停止时,开发者可以通过EXPAND命令快速了解当前函数的执行上下文。
@stack_level:指定要展开的栈层级。栈层级从0开始计数,0表示当前函数,1表示调用当前函数的函数,以此类推。windowid | fileid:指定输出目标窗口或文件的ID,用于将结果重定向到特定窗口或文件。最简单的用法是直接输入EXPAND命令,不带任何参数:
code复制> expand
这将显示从当前函数开始的所有可访问栈帧中的参数和局部变量。
典型输出示例:
code复制00. Proc_1: at line 309.
Ptr_Val_Par07FFFF60 = (record *)0x01000260
Next_Record00000005 = (record *)0x0100C274
01. main: at line 170.
Int_1_Loc 07FFFF60 = 16777824
Int_2_Loc 07FFFF60 = 16777824
当调用栈较深时,可以指定具体的栈层级来查看特定函数的信息:
code复制> expand @2
这将只显示栈层级为2的函数(即当前函数的调用者的调用者)的参数和局部变量。
EXPAND命令可能会返回各种错误消息,理解这些消息对调试很有帮助:
| 错误消息 | 含义 | 可能原因 |
|---|---|---|
<Bad float> |
无效的浮点数值 | 浮点寄存器或内存值损坏 |
<bad size> |
类型大小无效 | 变量类型定义不匹配 |
<UNKNOWN: xx> |
无效的枚举值 | 枚举变量被赋了非法值 |
<not alive> |
局部寄存器变量不存在 | 变量生命周期已结束 |
<Not in procedure> |
PC位于第一个可执行行之前 | 程序计数器位置异常 |
WHERE命令显示当前的调用栈,而EXPAND则展示栈帧的详细信息。两者结合使用可以快速定位问题:
code复制> where
> expand @1 // 查看调用者帧
当调试复杂问题时,可以将EXPAND输出重定向到文件供后续分析:
code复制> fopen 50, 'stack_dump.txt'
> expand ,50
> vclose 50
在调试经过优化的代码时,EXPAND命令可能会显示<optimized out>,表示变量已被优化掉。这时需要:
FILL命令用于填充内存区域,是内存调试和初始化的强大工具。基本语法:
code复制FILL [{/B|/H|/W|/8|/16|/32}] addressrange ={expression | expressionlist}
大小限定符:
/B或/8:按字节填充(默认)/H或/16:按半字(16位)填充/W或/32:按字(32位)填充地址范围:指定要填充的内存区域,格式为start..end
填充内容:可以是单个表达式或表达式列表
用特定值填充内存区域:
code复制> fill 0x1000..0x1013=0x55 // 用0x55填充
> fill /h 0x2000..0x2010=0x1234 // 用16位值0x1234填充
使用表达式列表实现模式填充:
code复制> fill 0x3000..0x301F=0xAA,0x55,0x00 // 循环填充AA,55,00
直接用字符串填充内存:
code复制> fill 0x4000..0x4010="Hello"
注意:字符串不会自动添加NULL终止符,这与C语言不同。
在嵌入式开发中,FILL常用于内存初始化:
code复制> fill 0x20000000..0x20001000=0xCD // 用特定模式填充栈区
code复制> fill _heap_start.._heap_end=0x00 // 清零堆区
FILL命令可用于内存测试:
code复制// 写入测试模式
> fill /w 0x80000000..0x8000FFFF=0xAAAAAAAA
> fill /w 0x80010000..0x8001FFFF=0x55555555
// 然后使用verify命令验证内存内容
使用MEMWINDOW命令查看内存窗口,然后使用FILL修改内存内容,实时观察变化:
code复制> memwindow 0x20000000
> fill 0x20000000..0x2000000F=0x11,0x22,0x33,0x44
/H或/W时确保地址是对齐的将调试命令写入脚本,实现自动化调试:
code复制// debug_script.inc
fill 0x20000000..0x20001000=0x00 // 清零内存
break 0x08001234 // 设置断点
go // 运行程序
expand // 到达断点后显示变量
code复制alias ex=expand
alias fl=fill /w
掌握EXPAND和FILL等调试器命令需要实践和经验积累。建议在非关键项目中多练习这些命令的使用,熟悉它们的各种特性和限制。随着经验的增长,这些命令将成为解决复杂调试问题的有力工具。