一、Crash?
當linux系統內核發生崩潰的時候,可以通過KEXEC+KDUMP等方式收集內核崩潰之前的內存,生成一個轉儲elf文件vmcore或者其他dump形式。內核開發者通過分析該elf dump文件就可以診斷出內核崩潰的原因,從而進行操作系統的代碼問題修復。那么Crash就是一個被廣泛使用內核崩潰轉儲文件分析工具。
對調試來講,gdb/trace32是非常適合的,但gdb始終是調試native的工具,不支持kernel信息顯示,比如task信息之類的。crash補足了這個短板,由Dave Anderson開發和維護的一個內存轉儲分析工具,是基於GDB開發的,GDB適用於用戶進程的coredump,而Crash擴展了GDB,使其適用於linux kernel coredump,目前它的最新版本是7.3。在沒有統一標准的內存轉儲文件的格式的情況下,Crash工具支持眾多的內存轉儲文件格式,包括:
-
Live linux系統
-
kdump產生的正常的和壓縮的內存轉儲文件
-
由makedumpfile命令生成的壓縮的內存轉儲文件
-
由Netdump生成的內存轉儲文件
-
由Diskdump生成的內存轉儲文件
-
由Kdump生成的Xen的內存轉儲文件
-
IBM的390/390x的內存轉儲文件
-
LKCD生成的內存轉儲文件
-
Mcore生成的內存轉儲文件
二、安裝
crash是redhat開源工具,因此需要自己下載代碼編譯成linux可執行文件。
1)從官方網站下載crash源代碼;
git clone git://github.com/crash-utility/crash.git
2)編譯前確保必要的組件(ncurese和zlib);
sudo apt-get install libncurses5-dev
sudo apt-get install zlib1g-dev
3)解壓后編譯ARM 32bit的crash:
cd crash-7.2.8
make target=ARM64
4)如果是ARM 64bit的,則是:
cd crash-7.2.8
make target=ARM64
5)編譯后會在當前目錄下生成crash,可以將多余的符號去除:
strip -s crash
6)當發生kernel crash時,會有db生成;
7)然后可以使用crash的各種命令了,詳情請看:http://people.redhat.com/anderson/crash_whitepaper/
三、調試
使用crash來調試vmcore,至少需要兩個參數:
-
NAMELIST:帶symbol的內核映像文件vmlinux,由內核調試信息包提供;
-
MEMORY-IMAGE:內存轉儲elf dump文件。
如果有使能KASLR 功能需要提供--kaslr 對應的offset地址:
Eg:./crash ../dump/vmlinux ../dump/DDRCS0_0.BIN@0x80000000,../dump/DDRCS0_1.BIN@0x100000000,../dump/DDRCS1_0.BIN@0x180000000,../dump/DDRCS1_1.BIN@0x200000000 --kaslr <kaslr_offset> -m kimage_voffset=0xffffffe5d6200000 -m vabits_actual=39
注:vabits_actual=39 是VB_bits: CONFIG_ARM64_VA_BITS配置
基本輸出:
四、常用命令
crash使用gdb7.6作為它的內部引擎,crash中的很多命令和語法都與gdb相同。常用命令如下:如果想獲得crash更多的命令和相關命令的詳細說明,可以使用crash的內部命令help來獲取:
log | tail -n 100 查看log cpu watdog bark觸發dump
struct msm_watchdog_data wdog_data查看wdog_data 狀態:
Non-secure Watchdog data
Pet time: 9.36s
Bark time: 20.0s
Watchdog last pet: 10741.000
Watchdog task running on core 2 from 10750.686741
CPUs responded to pet(alive_mask): 00000001
CPU which didn't respond to pet: 1
CPU#0 : ping_start: 10750.686769 : ping_end: 10750.686779
CPU#1 : ping_start: 10750.686780 : ping_end: 0.000000
ps | grep RU 查看cpu1上活躍進程狀態:
當前dump為cpu1 watchdog bark觸發 , 需要查看percpu變量irq_stat在cpu1 狀態, 使用per_cpu__ 加變量查看percpu 地址,新版本crash per_cpu已經能自動識別:
通過地址查看變量:__softirq_pending = 8 對應softirq 為 NET_RX
五、擴展命令
crash支持擴展命令,其中trace/gcore這2個命令對分析問題非常方便,其他具體請看crash擴展命令說明。
trace導出ftrace到FTRACE文件:
trace show > FTRACE
gcore導出init進程coredump [kernel中如有打開zram等類似功能,需要crash中添加對應解壓縮函數實現]:
gcore -f 255 1
使用擴展命令前,需要先編譯好對應的so庫,下面介紹如何編譯擴展命令的庫,以trace為例。
六、ftrace
ftrace對分析kernel性能和死機等問題非常重要,有些異常類問題需要借助mrdump查看ftrace。crash和T32都可以做到,這里講crash如何利用擴展命令支持查看ftrace。
1. 編譯擴展命令庫
1)trace擴展命令需要trace-cmd支持,先編譯trace-cmd
$git clone git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git
pc端trace-cmd ,將生成的trace-cmd放到crash_master目錄
cd trace-cmd
make
手機端trace-cmd
cd trace-cmd
編譯32bit
make LDFLAGS=-static CC=<android codebase>/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-gcc trace-cmd
編譯64bit
make LDFLAGS=-static CC=~/Android_tool/aarch64-linux-gnu-6.3.1/bin/aarch64-linux-gnu-gcc trace-cmd
2)編譯trace.so
將trace.c放入crash源碼里的extensions目錄,然后在crash源碼目錄下輸入如下命令:make extensions
編譯好后,就有so庫生成,文件放在extensions目錄,比如trace.so。
2. 使用擴展命令
進入crash前,需設定環境變量TRACE_CMD,否則使用時會有異常提示:
因此在啟動crash前,先:
exprot trace-cmd 環境變量 export TRACE_CMD=<path-to>/trace-cmd
進入crash后,在crash命令行添加擴展 extend <path-to>/trace.so
至此就可以正確使用trace擴展命令了,比如查看trace有哪些參數可以使用:
執行trace show如下:
參考材料
[1] http://people.redhat.com/anderson/
[2] https://www.dedoimedo.com/computers/crash-analyze.html#mozTocId904879
[3] https://github.com/crash-utility/crash

“內核工匠”微信公眾號
Linux 內核黑科技 | 技術文章 | 精選教程