无调试信息时如何在GDB中查找指针及变量内存位置?
问题解答
1. 能否识别变量的内存位置?
可以。核心思路是利用你手中的源码,结合二进制逆向分析来定位——相同编译选项下(除了调试符号),编译器生成的栈帧布局和汇编逻辑完全一致。
2. 具体定位方法
- 先将源码用相同编译器、相同编译参数(仅额外添加
-g开启调试符号)编译出带调试信息的版本。执行objdump -dS <带调试程序>反汇编,找到main函数的汇编代码,重点看栈帧构建逻辑(比如push ebp; mov ebp, esp这类指令),同时记录buffer和p相对于栈帧基址(ebp/rbp)的偏移值——比如32位程序中,buffer可能在ebp-128位置,p在ebp-4位置。 - 对无符号表的目标程序,执行
objdump -d <无调试程序>反汇编,通过对比带调试版本的main函数汇编指令片段,定位出无调试版本中main函数的入口和范围。 - 调试无符号表程序时,在
main函数执行到栈帧构建完成后(比如刚执行完mov ebp, esp),用栈帧基址加上之前记录的偏移,就能计算出buffer和p的内存位置。
3. 使用x/x <addr of p>能否正确查看指针指向的内存地址?
可以。x/x是GDB中以十六进制格式读取指定内存地址内容的命令,而指针p本身就是一个存储目标地址的内存单元。只要你拿到了p的正确内存地址,x/x读取的结果就是p指向的地址值。注意如果是64位程序,需要用x/gx来读取8字节的完整指针值,避免截断。
4. 如何跟踪指针p在不同执行阶段的状态?
- 先通过上述方法确定
p的栈帧偏移,在GDB中给main函数的关键执行点设置断点(比如通过汇编指令地址设置:b *<main函数汇编起始地址+偏移量>)。 - 断点触发后,直接通过栈帧基址计算
p的地址,比如32位用p $ebp-4,64位用p $rbp-8(根据实际偏移调整),再用x/x查看其指向的地址;也可以直接用p *(char**)($ebp-4)(32位)来直接获取指针指向的地址。 - 还可以给
p的内存位置设置观察点:watch *<p的内存地址>,这样当p指向的地址发生变化时,GDB会自动触发断点,方便跟踪不同执行阶段的状态。
内容的提问来源于stack exchange,提问作者A. Trevelyan
相关产品推荐
相关产品推荐

