Android 異常問題分析

1. Introduction

解決問題通常分爲以下幾個步驟:

a) 確定問題,這是個什麼樣的問題,有什麼外在表現;

b) 分析問題,根據log裏面的蛛絲馬跡,定位出問題的原因;

c) 對症下藥,儘量用最少的代碼解決問題,並確保不會引入新的問題;

d) 驗證修改,把自己的修改導入,確保自己的修改起了作用,並已經徹底解決了問題,同時觀察是否引入新的問題;

此文檔主要面對的是幾類問題:

a) 重啓;

b) 死機(定屏);

c) 開機;

d) 黑屏;

下面會介紹各個問題,但基本只會從理論上介紹如何分析,所以不要期望看了這個文檔,你就能解決問題,這就像抓魚一樣,知道了如何抓魚,不代表你能抓得到魚;

2.重啓問題

重啓問題分爲兩類,一類是內核重啓(包含Modem重啓),一類是上層重啓,如何區分?

如果有震動,那麼就是內核重啓,反之則是上層重啓;如果不記得有無震動,也可以通過開機時間來判斷,設置裏面可以看開機經過了多少時間,dmesg的輸出也有時間標籤;還可以通過ps看進程號來判斷,如果zygoteservicemanager等的進程號比較小(一般100左右),那麼通常是內核重啓,否則就是上層重啓;如果你沒有看到現場,就只能通過Log來判斷了,後面會說到。

2.1 上層重啓

對於上層導致的重啓,這個比較普遍,一般有watch dog導致的重啓,需要進一步分析anr,一般是應用死鎖導致的問題,很遺憾這裏沒有例子;還有一種常見的問題就是native crash。重啓問題需要關注的就是時間點,一般在重啓之前一定有異常的log,往上繼續查找出現的異常,通常不遠處就是系統重啓的原因,並會打印出具體的棧信息。

如果是watch dog觸發的重啓,就需要分析anr裏面的文件traces.txt,如果前面的進程名字不是system_server,通常意味着這個anr已經被覆蓋了,這時候需要去dropbox裏面找到對應時間的文件,裏面會保留下來;如果是system_server,就搜索ServerThread,這個是主線程,裏面會告訴你它阻塞在了什麼地方,然後順着它阻塞的路徑,一直追,就可以找到真正觸發系統阻塞的原因,通過棧信息,找到具體的文件,函數,並聯繫上下文,猜測出可能的路徑;這裏是非常需要靈感的地方,不同的情景不同的原因,基本上沒有一個萬能的方法,全靠分析者自己的造化。

如果是native crash引發,當發生native crash的時候,一般在tombstone目錄下都能找到記錄。native調用棧一般都是在tombstone或者applogcat-log中打印出來。會有類似以下的log信息出現。

pid: 2363,tid: 2756, name: rild >>> /system/bin/rild <<<

signal 11(SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000

檢查發生錯誤的類型,比如SIGSEGVSIGBUSSIGPIPE等,這裏是SIGSEGV表示地址錯誤,那就檢查訪問地址。

這裏有一個上層導致的重啓例子:

pid: 2363,tid: 2756, name: rild >>> /system/bin/rild <<<

signal 11(SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000

r0 00000000r1 00000000 r2 1e7c32c2 r3 00000000

r4 b6d65565r5 b6d561a4 r6 00000000 r7 00000000

r8 b6d6be1cr9 b6b25cf8 sl b6d58e17 fp b6d6c1e8

ip b6d6beecsp b6b25a08 lr b6d3be41 pc b6f79140 cpsr 600f0030

d0676f6c522d657352 d1 6464615f79617749

d272207473756a204c d3 756e2074726f705f

d4002d00650074006c d5 007000750067006c

d6002e00730075006c d7 006b002e006f0063

d80000000000000000 d9 0000000000000000

d100000000000000000 d11 0000000000000000

d120000000000000000 d13 0000000000000000

d140000000000000000 d15 0000000000000000

d164150c82e3d2f1aa0 d17 0000000000000000

d18 41b7ccaa7c000000d19 0000000000000000

d200000000000000000 d21 0000000000000000

d220000000000000000 d23 0000000000000000

d240000000000000000 d25 0000000000000000

d260000000000000000 d27 0000000000000000

d280000000000000000 d29 0000000000000000

d30 0000000000000000d31 0000000000000000

scr 00000010

backtrace:

#00 pc00023140 /system/lib/libc.so (strlen+83)

#01 pc00015e3d /system/lib/libbalong-ril.so

#02 pc0001a1a3 /system/lib/libbalong-ril.so

#03 pc0001a903 /system/lib/libbalong-ril.so (on_data_call_list_changed+42)

#04 pc0002dffd /system/lib/libbalong-ril.so

#05 pc0000d410 /system/lib/libc.so (__thread_entry+72)

#06 pc0000d5a8 /system/lib/libc.so (pthread_create+240)

#07 pc00001014 [heap]

2.2 Modem重啓

關鍵log:sys rebootreason: Software EXCE CP

出現內核重啓問題,首先應該看看是不是Modem重啓,在目前發現的重啓問題來看,大部分是Modem導致的,當然隨着版本的穩定,現在也比較少了。

相關問題log

06-0915:29:00.746 <6>[17425.253448] [1198.0, rdr_init_thread] rdr:sys rebootreason: Software EXCE CP

06-0915:29:00.748 <6>[17425.271850] [1198.0, rdr_init_thread] rdr:we shouldsave file to emmc before reboot!

06-0915:29:01.774 <6>[17426.294281] [1198.1, rdr_init_thread] save resetlog:rdr:system reboot reason: Software EXCE CP

06-0915:29:11.739 <6>[17436.260955] [1198.2, rdr_init_thread] we need rebootnow ...

06-09 15:29:14.645<6>[17439.164001] [1198.3, rdr_init_thread] sysreboot reason: SoftwareEXCE AP, tick: 20140609072914_17857.690150, systemError para: ModId=0x82000006,Arg1=5, Arg2=0

06-0915:29:14.648 <6>[17439.169677] [1198.3, rdr_init_thread] rdr:we shouldsave file to emmc before reboot!

06-0915:29:15.599 <6>[17440.122100] [1198.0, rdr_init_thread] save resetlog:sysreboot reason: Software EXCE AP, tick: 20140609072914_17857.690150

2.3 內核重啓

關鍵logsysreboot reason: Software EXCE AP

導致內核重啓的原因主要是以下兩種:

1、代碼異常直接主動panic、被動panic(一般出現了踩了內存、非法指針等致命錯誤)

2、硬件狗復位

內核檢測到異常,直接調用BUG函數觸發panic,這裏的BUG函數是一個宏定義,最終會調用panic函數打印出調用棧,同時導致手機重啓。在kmseg中能看到oops字串和backtrace調用棧,另外會生成dontpanic/APANIC_CONSOLEdontpanic/APANIC_THREAD兩個文件,前者能看出引起重啓的時刻每個核的調用棧,後者能看出重啓時刻所有線程的調用棧信息。

panic信息位於apanic_console的末段,首先的找到panic信息的有關描述。通過分析堆棧信息可以找到問題的根因。

如果是因爲指針異常一般會有以下log信息:

Unable tohandle kernel NULL pointer dereference at virtual address 00000000

踩內存log一般如下:

Unable tohandle kernel paging request at virtual address 656d616e

踩內存問題一般很難定位,需要往前追溯看看有沒有異常的log警告也需要重點關注。例如:字符串操作不當,引起的內存越界問題。

3.開機問題

這個問題的現象就是機器一直在開機界面,有兩種情況,一是靜態LOGO;一種是動態LOGO

3.1靜態的LOGO的情景

1、硬件故障,基本adb都無法連接上,需要硬件同事幫忙分析。

主要可能出現的硬件故障有:

CPU(包括L1,L2 cache)、DDR EMMC BUS PMU(電源管理)

2、內核(BOOT)故障,不能連接adb,需要連接串口分析。

3zygote反覆重啓引起的問題,導致systemserver沒有起來。

4、如果不是以上問題,就需要分析內核日誌。

3.2 停在動態的LOGO界面

一般是因爲開機時因爲各種異常導致系統應用層面出現崩潰,一般還是可以正常使用adb shell的。

1、如果動畫界面,是否卡死Systemserver

2、反覆播放動畫,是否Systemserver反覆重啓。

3、關注內核死鎖問題。關注dmesg_sysrq.txt文件,文件的尾部都有SYSRQ信息,會打印出當前的D進程狀態,可以逐個查看是否有死鎖的情況。

4.死機(定屏)問題

如何判斷一個問題是否是一個死機問題?

對於Android平臺,從現象上說,就是屏幕以及按鍵沒有任何反應,給此設備打電話,也不會有任何反應,但是對於分析者來說,是插入USB線沒有反應,也就是Windows的設備管理器,不會因爲插USB線而出來新的設備(如果屏幕按鍵無反應,但出現了新的設備,那這個是後面要說的白屏問題)

需要收集哪些現場?

對於這類問題,我們當前的策略通常是需要抓取串口log,也就是說,如果出現這種情況的時候,沒有連接串口,基本上是無能爲力的(Google默認提供了一種機制叫做last_kmsg,似乎是可以在重啓的時候把上次crashkernel log寫到/proc/last_kmsg裏面去),如果連接了串口,通過判斷串口是否有輸出,可以定位出內核到底死了沒有,如果是kernel死,會打印出kernel crash的棧信息以及寄存器信息,可以根據棧信息,定位出是什麼模塊導致的;

簡單點說,如果是對於死機問題,我們需要抓取串口log

如何分析:

如果一定要有祕籍的話,那麼就是認真觀察死之前的遺言!

通常都會有棧信息出來,根據棧信息就可以看到是那個函數引起的,所以相對來說好定位,當然也出現過出事的函數只是替罪羊,真正的罪魁禍首在幕後的情況,但是,打印的信息都會做出一定的暗示,透過現象看本質,不輕易下結論。

給出一些判斷建議:

1、連接不了adb,也沒有按鍵中斷,只能連接jtag調試了;

2、連接不了adb,有按鍵中斷,連接串口、按鍵觸發panic

3、可以連接adb,觸發SYSRQ,檢查是否內核異常卡死,OOM(分析卡死原因、內存是否真的少了)。

5getevent是否上報,找出不上報原因;

6InputDispatch出現異常,隊列爆了,無法正常分發事件;

7、界面無刷新,分析surfacefingerLCD驅動(顯示異常定位)。

5.黑屏問題

黑屏問題,很好確認,屏變黑了,撥電話沒反應,並且維持這個狀態很長一段時間,如果插入USB沒有反應,那麼它就是一個死機問題,請看死機部分;如果有反應,那麼它就是我們這裏說的黑屏問題了;

正常情況下,都應該是系統重啓,所以它的情報蒐集以及分析過程和上面說的重啓是一樣的!(但是,有種黑屏的現象是觸屏,按鍵都無法響應,但是打電話還有反應,是我們說的點不亮的問題,這個問題通常是在睡眠或者喚醒的時候被阻塞住了,它的分析,比較複雜,需要在內核裏的睡眠喚醒的核心加大量的信息來定位,通常是suspend的線程被阻塞了,導致後面的late_resume函數,也就是點亮lcd的動作一直沒有被觸發執行,因爲它們是放在同一個work queue suspend_work_queue來做的,需要去檢查爲什麼前面的suspend被阻塞了,當然,如果你對內核非常的熟悉,也能從串口或者dmesg信息裏面看出蛛絲馬跡,然後做對應的測試,這裏就不討論了)

6.總結

1、當我們被測試部的同事急急忙忙的叫去看現場的時候,通常並不知道這是個什麼樣的現象,所以要儘量抓取足夠多的信息。尤其是需要知道出現問題的時間點。

2、根據現場,初步判斷是死機,重啓,白屏中的哪種?

3、根據第二步的判斷,如果是內核死機,則重點查看dmesg信息;如果是上層死機,重點查看tombstonebugreportlogcatanr;如果是內核重啓,重點查看dmesg信息;如果是上層重啓,重點查看logcatanr

4、然後就根據面的介紹,逐個分析,如果還無法定位的話,就需要添加自己的打印信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章