使用 GDB 恢复堆栈信息
用 C/C++ 編寫的程序, 如果遇到 Segmentation Fault 則可以通過生成 coredump 來進行調(diào)試, 根據(jù)記錄的信息定位到出錯代碼行. 但很多時候可能用 gdb 打開 coredump 文件查看堆棧時, 卻出現(xiàn)一堆問號, 無法直接定位到出錯代碼行. 本文介紹另一種方法來還原錯亂的堆棧信息.
例如, 下圖是 coredump 后用 gdb 看到的堆棧信息, 可以看到這些代碼都是系統(tǒng)依賴庫中的函數(shù)信息, 如果太多地方調(diào)用這些庫接口, 就很難定位到問題所在. 下圖中應是在調(diào)用字符串轉(zhuǎn)數(shù)字接口時出錯.
coredump 堆棧信息示例
上圖中仍無法定位到代碼中的具體某一行. 不過寄存器 ebp 中存放了函數(shù)幀指針, 這就提供了一個追蹤棧信息的線索. 首先將 ebp 的內(nèi)容打印出來:
寄存器 ebp 的內(nèi)容
眾所周知, 棧即函數(shù)的調(diào)用棧布局. 每次函數(shù)調(diào)用, 就會將當前函數(shù)的地址及局部變量壓入棧頂. 這些調(diào)用信息是以一個單向鏈表來組織的, 上面看到的 ebp 內(nèi)容就是這個鏈表的 head 指針. 那么打印出 ebp 內(nèi)容 0x9e76f354 指針所指內(nèi)容如下:
寄存器 ebp 內(nèi)容所指向的區(qū)域信息
與 head 節(jié)點一樣, 第一個節(jié)點的最低 4 個字節(jié)存儲的是下一鏈表節(jié)點位置的指針, 緊隨其后的 4 個字節(jié)是該層調(diào)用的返回地址, 查看其內(nèi)容如下:
第一個節(jié)點調(diào)用的返回地址
可以看到, 棧頂?shù)暮瘮?shù)地址是與 bt 命令打印的信息一致, 依次打印出該鏈表上節(jié)點信息如下:
鏈表各節(jié)點信息
上述信息已經(jīng)基本還原了 bt 所能打印出來信息, 上圖中后面的節(jié)點可以看出導致 coredump 的代碼位置, 是在 TtcThmDescOper::tbThmDesc_get 函數(shù)中一次 atoll 調(diào)用時導致.
以上就是在 bt 無法打印堆棧內(nèi)容時, 采用另一種方式還原函數(shù)調(diào)用層級的方式, 希望能對大家定位問題有一定幫助. 另外需要提醒大家的是, 在 64 位系統(tǒng)中, 寄存器 esp 變成了 rsp, 寄存器 ebp 變成了 rbp, 寄存器 ip 變成了 rip. 而在 arm 平臺中, 寄存器 ebp 則變成了 fp.
總結(jié)
以上是生活随笔為你收集整理的使用 GDB 恢复堆栈信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (计算机组成原理)第五章中央处理器-第一
- 下一篇: Atitit 发帖机系列(7) 词法分析