Android——coredump解析


撰寫不易,轉載需注明出處:http://blog.csdn.net/jscese/article/details/46916869本文來自 【jscese】的博客!

coredump文件生成
前文Android——coredump 配置 記錄了android平台上的環境配置,生成方式 正常即為process觸發那幾種signal

手動coredump狀態:
連接gdb -gcore pid
終端發送signal終止process: kill -s signal pid 自然發送能產生coredump的signal ,前文有記錄,但是有時一次還殺不掉process signal可以被忽視。
signal可參考:

root@:/ # kill -l 
1 HUP Hangup 33 33 Signal 33 
2 INT Interrupt 34 34 Signal 34 
3 QUIT Quit 35 35 Signal 35 
4 ILL Illegal instruction 36 36 Signal 36 
5 TRAP Trap 37 37 Signal 37 
6 ABRT Aborted 38 38 Signal 38 
7 BUS Bus error 39 39 Signal 39 
8 FPE Floating point exception 40 40 Signal 40 
9 KILL Killed 41 41 Signal 41 
10 USR1 User signal 1 42 42 Signal 42 
11 SEGV Segmentation fault 43 43 Signal 43 
12 USR2 User signal 2 44 44 Signal 44 
13 PIPE Broken pipe 45 45 Signal 45 
14 ALRM Alarm clock 46 46 Signal 46 
15 TERM Terminated 47 47 Signal 47 
16 STKFLT Stack fault 48 48 Signal 48 
17 CHLD Child exited 49 49 Signal 49 
18 CONT Continue 50 50 Signal 50 
19 STOP Stopped (signal) 51 51 Signal 51 
20 TSTP Stopped 52 52 Signal 52 
21 TTIN Stopped (tty input) 53 53 Signal 53 
22 TTOU Stopped (tty output) 54 54 Signal 54 
23 URG Urgent I/O condition 55 55 Signal 55 
24 XCPU CPU time limit exceeded 56 56 Signal 56 
25 XFSZ File size limit exceeded 57 57 Signal 57 
26 VTALRM Virtual timer expired 58 58 Signal 58 
27 PROF Profiling timer expired 59 59 Signal 59 
28 WINCH Window size changed 60 60 Signal 60 
29 IO I/O possible 61 61 Signal 61 
30 PWR Power failure 62 62 Signal 62 
31 SYS Bad system call 63 63 Signal 63 
32 32 Signal 32 64 64 Signal 64

gdb調試coredump
以simplejni apk中 jni崩潰 得到的core.droid.simplejni.1797文件拷貝到編譯源碼的根目錄為例

源碼目錄下使用編譯工具鏈的gdb
也可以cygwin終端下或者eclipse環境下使用ndk的gdb操作,經過多次調試發現有的動態庫中的symbol信息, ndk的gdb無法顯示完全!

開啟android gdb:
./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gdb
1
2.gdb模式下設置動態庫搜索加載路徑:

set solib-search-path /home/..../out/target/product/../symbols/system/lib/
1
設置到源碼編譯的out目錄下的symbol

3.加載啟動程序:

file out/target/product/../symbols/system/bin/XXX
//app進程最后XXX就是app_process32,zygote的啟動程序,根據情況修改
4.加載core文件:

5.常用命令:
==============command=========
set logging on/off log保存

backtrace(bt) n 回溯n個調用棧

list n 顯示源碼 或者顯示行數
list - 向上顯示

set listsize n 設置打印行數

frame(f) n 切換棧幀
info frame(f) 0 第幾棧幀的信息

info args 顯示當前棧幀函數參數

info locals 當前幀函數局部變量

info threads / thread n 查看線程信息/切換線程

info (all-)register/ info r rname 查看全部寄存器/根據寄存器名查看

info line filename:func/line 查看文件中某行代碼當時在內存中的地址:

 

disassemble fuc / disassemble $pc 反匯編函數/反匯編pc寄存器指向的指令所屬函數:

 

x/fu address 查看內存中的值
f表示顯示方式, 可取如下值
x 按十六進制格式顯示變量。
d 按十進制格式顯示變量。
u 按十進制格式顯示無符號整型。
o 按八進制格式顯示變量。
t 按二進制格式顯示變量。
a 按十六進制格式顯示變量。
i 指令地址格式
c 按字符格式顯示變量。
f 按浮點數格式顯示變量。

u表示一個地址單元的長度
b表示單字節,
h表示雙字節,
w表示四字節,
g表示八字節

pc 的值為下一條指令存放的地址,此時的pc值所指向的指令為:


后面0x2004681b代表的即為匯編的arm指令

此時執行的指令是 ldr r3, [r3, #0]
加載 [r3, #0] 地址的值給 r3寄存器, 可以看到前面還有一句:
movs r3, #0 設成了0
可查看r3 寄存器當前的值,p X:

 

這里就是從 0 地址加載,訪問了 0地址內存,空指針,導致段錯誤

記錄

報非法指令,反匯編看到pc所指的指令,這里指向的是gdb反匯編了symbol下對應的動態庫(libsurfaceflinger.so)再根據內存地址以及在動態庫中的偏移得到的,同樣可以查看當時內存中的指令:

 

由於報非法指令,我們可以手動去反匯編libsurfaceflinger.so 校驗一下實際的與內存中的指令是否一致:
源碼目錄下:

prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-objdump -S -D out/target/product/../symbols/system/lib/libsurfaceflinger.so > libsurfaceflinger.txt
1
objdump -x obj 以某種分類信息的形式把目標文件的數據組織(被分為幾大塊)輸出 <可查到該文件的所有動態庫>

objdump -t obj 輸出目標文件的符號表()

objdump -h obj 輸出目標文件的所有段概括()

objdump -j .text/.data -S obj 輸出指定段的信息,大概就是反匯編源代碼把

objdump -S obj C語言與匯編語言同時顯示
1
2
3
4
5
6
7
8
9
查看libsurfaceflinger.txt匯編文件
可根據上面的 info line 得到的地址與這里的地址算偏移,算出libsurfaceflinger.txt中應該對應的指令

或者以沒有崩潰前的cat /proc/4702(pid)/maps 查看內存映射,算偏移地址得到指令:

//動態庫被加載到內存的映射
root:/ # cat /proc/4702(pid)/maps | grep surface
b6ec5000-b6ef4000 r-xp 00000000 5d:10 1567 /system/lib/libsurfaceflinger.so
b6ef4000-b6ef9000 r--p 0002e000 5d:10 1567 /system/lib/libsurfaceflinger.so
b6ef9000-b6efa000 rw-p 00033000 5d:10 1567 /system/lib/libsurfaceflinger.so
b6feb000-b6fed000 r-xp 00000000 5d:10 464 /system/bin/surfaceflinger
b6fed000-b6fee000 r--p 00001000 5d:10 464 /system/bin/surfaceflinger
一共有6列
第一列代表內存段的虛擬地址
第二列代表執行權限,r,w,x不必說,p=私有 s=共享
不用說,heap和stack段不應該有x,否則就容易被xx,不過這個跟具體的版本有關
第三列代表在進程地址里的偏移量
第四列映射文件的主設備號和次設備號
通過 cat /proc/devices
得知fd是253 device-mapper
第五列映像文件的節點號,即inode
第六列是映像文件的路徑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
這里發現內存中指令是對的,考慮可能是cpu取指出錯

//匯編
//寄存器存儲
stmia, 比如當前ro指向的內存地址是 0x1000,STMIA RO!,{R1-R7} 就是 首先把r1存入 0x1000,
然后r2存入0x1004,然后r3存入0x1008,如果是32位的處理器就是每次加4個字節,以此類推把 r1-r7按照遞增的地址存入。。。。
這個r0!就是從r0的地址開始存的意思。。。

stmia.w r11, {r2, r3, r4, r5} //.w的意思是告訴編譯器,這條指令采用32bit編碼。
相同:
str.w r2 [r11] //將寄存器r2的值存入r11指向的地址上 ,寄存器本身r11本身的值不變
str.w r3, [r11,#4]
str.w r4, [r11,#8]
str.w r5, [r11,#12]

32bit 一次+4 byte

stmdb 則是地址從r0開始減少,依次存儲。。。

暫時記錄這么多~ 后續有需要再添加~
---------------------
作者:南丶煙
來源:CSDN
原文:https://blog.csdn.net/jscese/article/details/46916869
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM