我們在嵌入式Linux開發過程中經常會遇到一個問題,就是程式崩潰後不知道具體位置。因為我們釋出到生產環境的一般是沒有除錯符號的(使用strip或編譯時加-s引數,CMake生成的編譯指令中的-O3也會造成除錯符號丟失),畢竟嵌入式的儲存都比較有限,肯定是需要剝離除錯符號的。
另外一個經常遇到的問題是Release版本會崩潰,Debug不崩潰,因為-g引數有時候會讓編譯器對一些變數進行預設賦值,這又給我們除錯增加難度:上Debug吧空間不允許,執行速度也不夠(沒有-O了);上Release,又崩潰……
接下來我為大家提供一個思路,可以在無除錯符號的情況下定位崩潰位置。
首先我們準備一個簡單的測試程式碼,讓他崩潰一下。
#include <stdio.h> #include <stdlib.h> int func1() { printf("%d\n",__LINE__); int *p = NULL; *p = 0; printf("%d\n",__LINE__); return *p; } void func2() { printf("%d\n",__LINE__); func1(); printf("%d\n",__LINE__); } void func3() { printf("%d\n",__LINE__); func2(); printf("%d\n",__LINE__); } int main() { func3(); return 0; } //gcc -s -O3 main.c
我們編譯執行後,毋庸置疑,它會崩潰。
此時如果我們用gdb除錯,當然是無法定位問題,因為沒有除錯符號,它無法backtrace,直接給你兩個問號。
接下來重頭戲來了,我們使用Ida Pro來試試定位!
首先我們使用gdb的一些命令獲取崩潰的模組(是主程式還是某個so),以及崩潰的程式碼位置。
我們使用info proc map指令獲取崩潰的程式碼所在模組,確定是我們主程式a.out程式碼崩潰的(這個很重要,咱作為程式設計師,一定要用事實說話,不可以猜)
然後我們透過x/16x $pc來獲取崩潰的彙編程式碼(這個指令就是獲取是哪句彙編程式碼導致程式崩潰的)。
(當然,一般崩潰就是幾個位元組的一句彙編導致的,用不了16個位元組,不過我們要做特徵匹配)
緊接著,我們開啟16進位制檢視工具,搜尋這組16進位制的位置
可以看到,彙編程式碼在整個程序的偏移量是0x1242
我們開啟Ida Pro,裝載a.out
在Hex View介面找到0x1242,滑鼠點選,會得到一個函式名和偏移量。
我們在左側的Functions窗格雙擊對應函式名可以進入
(有時候這個函式比較複雜,我們在這種圖形下不好定位,可以右鍵切換到Text View進行檢視)
當然,走到這裡之後我能給大家的參考就少了。接下來就要靠大家自己聯絡上下文彙編找到報錯的程式碼對應的原始碼了。
也可以按F5進入虛擬碼視窗(虛擬碼是Ida Pro提供的彙編轉c語言的功能,不一定完全對,但很大程度上提供了幫助)
最後更新時間 2024-11-02 17:49:50