# 打印函數堆棧幀信息
## 例子
#include <stdio.h>
int func(int a, int b)
{
int c = a * b;
printf("c is %d\n", c);
}
int main(void)
{
func(1, 2);
return 0;
}
## 技巧
使用gdb調試程序時,可以使用“`i frame`”命令(`i`是`info`命令縮寫)顯示函數堆棧幀信息。以上面程序為例:
Breakpoint 1, func (a=1, b=2) at a.c:5
5 printf("c is %d\n", c);
(gdb) i frame
Stack level 0, frame at 0x7fffffffe590:
rip = 0x40054e in func (a.c:5); saved rip = 0x400577
called by frame at 0x7fffffffe5a0
source language c.
Arglist at 0x7fffffffe580, args: a=1, b=2
Locals at 0x7fffffffe580, Previous frame's sp is 0x7fffffffe590
Saved registers:
rbp at 0x7fffffffe580, rip at 0x7fffffffe588
(gdb) i registers
rax 0x2 2
rbx 0x0 0
rcx 0x0 0
rdx 0x7fffffffe688 140737488348808
rsi 0x2 2
rdi 0x1 1
rbp 0x7fffffffe580 0x7fffffffe580
rsp 0x7fffffffe560 0x7fffffffe560
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7dea560 140737351951712
r10 0x7fffffffe420 140737488348192
r11 0x7ffff7a35dd0 140737348066768
r12 0x400440 4195392
r13 0x7fffffffe670 140737488348784
r14 0x0 0
r15 0x0 0
rip 0x40054e 0x40054e <func+24>
eflags 0x202 [ IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) disassemble func
Dump of assembler code for function func:
0x0000000000400536 <+0>: push %rbp
0x0000000000400537 <+1>: mov %rsp,%rbp
0x000000000040053a <+4>: sub $0x20,%rsp
0x000000000040053e <+8>: mov %edi,-0x14(%rbp)
0x0000000000400541 <+11>: mov %esi,-0x18(%rbp)
0x0000000000400544 <+14>: mov -0x14(%rbp),%eax
0x0000000000400547 <+17>: imul -0x18(%rbp),%eax
0x000000000040054b <+21>: mov %eax,-0x4(%rbp)
=> 0x000000000040054e <+24>: mov -0x4(%rbp),%eax
0x0000000000400551 <+27>: mov %eax,%esi
0x0000000000400553 <+29>: mov $0x400604,%edi
0x0000000000400558 <+34>: mov $0x0,%eax
0x000000000040055d <+39>: callq 0x400410 <printf@plt>
0x0000000000400562 <+44>: leaveq
0x0000000000400563 <+45>: retq
End of assembler dump.
可以看到執行“`i frame`”命令后,輸出了當前函數堆棧幀的地址,指令寄存器的值,局部變量地址及值等信息,可以對照當前寄存器的值和函數的匯編指令看一下。
參見[gdb手冊](https://sourceware.org/gdb/onlinedocs/gdb/Frame-Info.html).
## 貢獻者
nanxiao
- 版權
- 內容
- 調整窗口大小
- 一個gdb會話中同時調試多個程序
- 調試已經運行的進程
- 在匿名空間設置斷點
- 在程序地址上打斷點
- 在程序入口處打斷點
- 在函數的第一條匯編指令打斷點
- 在文件行號上打斷點
- 使用斷點命令改變程序的執行
- 直接執行函數
- 為exec調用設置catchpoint
- 為fork調用設置catchpoint
- 為ptrace調用設置catchpoint
- 為系統調用設置catchpoint
- 為vfork調用設置catchpoint
- 改變字符串的值
- 配置gdb init文件
- 設置源文件查找路徑
- 自動反匯編后面要執行的代碼
- 顯示程序原始機器碼
- 顯示將要執行的匯編指令
- 打印內存的值
- 退出正在調試的函數
- 為調試進程產生core dump文件
- 得到命令的幫助信息
- 忽略斷點
- 信息顯示
- 打印函數堆棧幀信息
- 列出函數的名字
- 查看信號處理信息
- 顯示共享鏈接庫信息
- 跳轉到指定位置執行
- 顯示匯編代碼窗口
- 顯示寄存器窗口
- 加載可執行程序和core dump文件
- 打印程序進程空間信息
- 在Solaris上使用maintenance命令查看線程信息
- 將源程序和匯編指令映射起來
- 修改PC寄存器的值
- 命令行選項的格式
- 信號發生時是否把信號丟給程序處理
- 修改被調試程序的二進制文件
- 支持預處理器宏信息
- 打印STL容器中的內容
- 打印數組的索引下標
- 打印ASCII和寬字符字符串
- 打印數組中任意連續元素值
- 按照派生類型打印對象
- 打印調用棧幀中變量的值
- 打印大數組中的內容
- 打印函數局部變量的值
- 打印程序動態分配內存的信息
- 打印進程內存信息
- 打印寄存器的值
- 信號發生時是否打印信號信息
- 打印源代碼行
- 打印靜態變量的值
- 查看線程信息
- 打印變量的類型和所在文件
- gdb退出時不顯示提示信息
- 在gdb中執行cd和pwd命令
- 在gdb中執行shell命令和make
- 保存已經設置的斷點
- 保存歷史命令
- 選擇函數堆棧幀
- 給程序發送信號
- 設置條件斷點
- 打印尾調用堆棧幀信息
- 同時調試父進程和子進程
- 設置匯編指令格式
- 調試子進程
- 指定程序的輸入輸出設備
- 記錄執行gdb的過程
- 輸出信息多時不會暫停輸出
- 每行打印一個結構體成員
- 設置被調試程序的參數
- 設置命令提示符
- 設置命令提示符
- 設置讀觀察點
- 設置讀寫觀察點
- 只允許一個線程運行
- 按何種方式解析腳本文件
- 進入不帶調試信息的函數
- 設置臨時斷點
- 設置變量的值
- 設置觀察點只針對特定線程生效
- 設置觀察點
- 顯示gdb版權相關信息
- 不顯示線程啟動和退出信息
- 顯示gdb版本信息
- 啟動時不顯示提示信息
- 是否進入帶調試信息的函數
- 信號發生時是否暫停程序
- 替換查找源文件的目錄
- 讓catchpoint只觸發一次
- 進入和退出圖形化調試界面
- 向上或向下切換函數堆棧幀
- 使用“$_”和“$__”變量
- 使用“$_exitcode”變量
- 使用“$_siginfo”變量
- 使用“$_thread”變量
- 使用命令的縮寫形式