如何在LLDB或GDB中查看完整函数栈帧?求操作示例及输出解析
下面分别介绍GDB和LLDB中查看函数参数、旧ebp、返回地址、局部变量的具体操作和示例。
GDB 操作指南
核心命令
bt:打印所有栈帧的概览,快速定位目标栈帧frame <帧编号>:切换到指定栈帧(例如frame 0是当前正在执行的栈帧)info frame:显示当前栈帧的详细元数据,包含栈帧起止地址、返回地址、参数列表位置info args:列出当前栈帧的所有函数参数及对应值info locals:列出当前栈帧的所有局部变量及对应值x/[数量][格式] $ebp:手动查看ebp附近的栈内存,直接读取旧ebp、返回地址、参数等原始数据
实操示例
先准备一个测试C程序:
#include <stdio.h> int add(int a, int b) { int c = a + b; return c; } int main() { int x = 5, y = 7; int result = add(x, y); printf("Result: %d\n", result); return 0; }
编译时带上调试信息:gcc -g test.c -o test
启动GDB并运行程序:
gdb ./test break add # 在add函数入口设断点 run # 启动程序,触发断点查看当前栈帧元数据:
info frame输出示例:
Stack level 0, frame at 0x7fffffffdd90:
rip = 0x555555555149 in add (test.c:4); saved rip = 0x555555555176
called by frame at 0x7fffffffddb0
source language c.
Arglist at 0x7fffffffdd80, args: a=5, b=7
Locals at 0x7fffffffdd80, Previous frame's sp is 0x7fffffffdd90
Saved registers:
rbp at 0x7fffffffdd80, rip at 0x7fffffffdd88
这里的saved rip就是返回地址,rbp at 0x7fffffffdd80是当前栈帧的ebp值。查看旧ebp(调用者的ebp):
当前ebp指向的内存值就是旧ebp,执行:x/x $rbp输出示例:
0x7fffffffdd80: 0x00007fffffffddb0,这个值就是main函数栈帧的ebp。查看参数和局部变量:
info args # 查看参数 info locals # 查看局部变量输出示例:
a = 5
b = 7
c = 0手动查看栈内存(验证结构):
x/8x $ebp输出示例:
0x7fffffffdd80: 0x00007fffffffddb0 0x0000555555555176 0x0000000000000005 0x0000000000000007
0x7fffffffdd90: 0x0000000000000000 0x00007fffffffde38 0x0000555555555150 0x00007fffffffddb0
从左到右依次是:旧ebp、返回地址、参数a、参数b。
LLDB 操作指南
核心命令
bt:打印所有栈帧概览frame select <帧编号>:切换到指定栈帧(例如frame select 0)frame info:显示当前栈帧的基础信息,包含函数参数值frame variable:同时列出当前栈帧的参数和局部变量register read rbp:查看当前rbp(对应x86的ebp)的值x/[数量][格式] $rbp:手动查看rbp附近的栈内存,读取旧ebp、返回地址等数据
实操示例
使用同样的测试程序,编译后启动LLDB:
lldb ./test breakpoint set -n add # 在add函数入口设断点 run # 启动程序,触发断点
查看当前栈帧基础信息:
frame info输出示例:
frame #0: 0x0000000100003f49 test`add(a=5, b=7) at test.c:4:9
1 #include <stdio.h>
2
3 int add(int a, int b) {
-> 4 int c = a + b;
5 return c;
6 }
这里直接显示了参数a和b的值。查看寄存器(获取rbp和当前指令地址):
register read rbp rip输出示例:
rbp = 0x00007ff7bfeff580
rip = 0x0000000100003f49 test`add(a=5, b=7) at test.c:4:9查看返回地址和旧ebp:
- 返回地址存储在
$rbp + 8的位置:x/x $rbp+8,输出示例:0x7ff7bfeff588: 0x0000000100003f76 - 旧ebp是
$rbp指向的内存值:x/x $rbp,输出示例:0x7ff7bfeff580: 0x00007ff7bfeff5a0
- 返回地址存储在
查看参数和局部变量:
frame variable输出示例:
(int) a = 5
(int) b = 7
(int) c = 0
关于你提到的命令说明
finish:这个命令是执行完当前函数并返回调用者,不是用来查看当前栈帧细节的,执行后栈帧会自动切换到上一级。frame info:GDB中它只显示栈帧的元数据(地址、返回地址等),需要结合info args/info locals查看变量;LLDB中它会直接显示参数,但要获取旧ebp、返回地址还需要结合寄存器和内存查看命令。
内容的提问来源于stack exchange,提问作者Kato Megumi

