Coredump介紹及如何在Android中開啟和使用來分析Crash等問題
文章目錄:
Coredump簡介及使用... 1
目錄... 2
一、什麼是Coredump. 3
二、Coredump產生的原因... 3
三、如何控制產生Coredump. 4
四、使用Coredump的準備... 4
五、開始使用Coredump. 5
一、什麼是Coredump
有些C/C++程式或者通過JNI呼叫了C/C++的APK程式可以通過編譯, 但在執行時會出現錯誤,比如常見的signal 11 (SIGSEGV),這樣的程式都是可以通過編譯的,而且這樣的錯誤一般情況下不會像編譯錯誤一樣告訴你具體在程式碼的那一行有問題,所以除錯起來比較困難和麻煩。
因為上面的這種debug困難的情況,所以就產生了coredump這種機制(很多作業系統都支援這種機制,並不是
二、Coredump產生的原因
造成程式coredump的原因很多,這裡根據以往的經驗總結一下:
1、 記憶體訪問越界
a) 由於使用錯誤的下標,導致陣列訪問越界
b) 搜尋字串時,依靠字串結束符來判斷字串是否結束,但是字串沒有正常的使用結束符
c) 使用strcpy,strcat, sprintf, strcmp, strcasecmp等字串操作函式,將目標字串讀/寫爆。應該使用strncpy,strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函式防止讀寫越界。
2、 多執行緒程式使用了執行緒不安全的函式
第1類:不保護共享變數的函式
第2類:保持跨越多個呼叫的狀態函式
第3類:返回指向靜態變數指標的函式
第4類:呼叫執行緒不安全函式的函式
3、 多執行緒讀寫的資料未加鎖保護
一個執行緒做完條件判斷準備使用時發生了排程,另外一個執行緒將其釋放並置空或者修改了內容,就會導致程式執行流錯亂,要麼指標異常,要麼狀態錯亂髮生另外的異常
4、 非法指標
a) 使用空指標
b) 隨意使用指標轉換。一個指向一段記憶體的指標,除非確定這段記憶體原先就分配為某種結構或型別,或者這種結構或型別的陣列,否則不要將它轉換為這種結構或型別 的指標,而應該將這段記憶體拷貝到一個這種結構或型別中,再訪問這個結構或型別。這是因為如果這段記憶體的開始地址不是按照這種結構或型別對齊的,那麼訪問它 時就很容易因為bus error而core dump
c) 使用未初始化或者已經釋放或者狀態不明的野指標
5、 堆疊溢位
不要使用大的區域性變數(因為區域性變數都分配在棧上),這樣容易造成堆疊溢位,破壞系統的棧和堆結構,導致出現莫名其妙的錯誤
三、如何控制產生Coredump
直接修改init.rc(system/core/rootdir)檔案,在setrlimit13 40 40後面新增:
setrlimit 4 -1 -1
mkdir /data/coredump 0777 system system
write /proc/sys/kernel/core_pattern/data/coredump/core.%e.%p
write /proc/sys/fs/suid_dumpable 1
這些命令的目的是將RLIMIT_CORE的大小修改為unlimited,具體參見:keywords.h中do_setrlimit函式。其中RLIMIT_CORE的定義在Resource.h中。在data目錄下建立coredump資料夾,並給系統賦予可讀可寫許可權。改寫coredump檔案的儲存路徑。使呼叫了seteuid()/setegid()的程式能夠生成coredump,預設情況下系統不會為這些程序生成Coredump,需要設定suid_dumpable為1。
儘管是做了上面這些動作,但是仍然只能為native程式產生coredump,對於由zygotefork的apk程序則不會生成coredump,因為zygote在做初始化的時候會忽略Linux的配置,使用預設不生成coredump的配置,system server同樣是由zygote fork的,所以也不會產生coredump,所以如果出現因為system server的thread crash引起的重啟則會非常頭疼,需要為system server配置生成coredump,如果其他apk程序需要產生coredump同樣需要在開機初始化的時候為zygote做特殊的設定。
所謂的特殊設定就是將zygote的啟動引數中應用rlimit的配置,system server也是同樣。
四、使用Coredump的準備
通過設定在出問題時產生了coredump,接下來我們就要使用這個coredump為我們分析具體的問題。工欲善其事必先利其器,我們首先要準備好解析coredump的環境和工具。
1、GDB,由於我們是分析嵌入式Linux核心下的產生的coredump,所以我們需要專門的交叉編譯工具鏈中的arm-linux-androideabi-gdb,大概位置:
prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb
2、有了GDB還不夠,我們需要更加人性化、簡單易操作的圖形化工具—Eclipse+CDT來檢視coredump
如何獲得:
3、準備與coredump版本對應的原始碼環境,最好與編譯版本時的路徑保持一致,以便定位具體的程式碼
4、準備與coredump版本對應的symbols