標籤:coredump signal 彙編 register debug
撰寫不易,轉載需註明出處: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可參考:
[email protected]:/ # 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
2.gdb模式下設定動態庫搜尋載入路徑:
set solib-search-path /home/..../out/target/product/../symbols/system/lib/
設定到源碼編譯的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地址記憶體,null 指標,導致段錯誤
記錄
報非法指令,反組譯碼看到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
objdump -x obj 以某種分類資訊的形式把目標檔案的資料群組織(被分為幾大塊)輸出 <可查到該檔案的所有動態庫>objdump -t obj 輸出目標檔案的符號表()objdump -h obj 輸出目標檔案的所有段概括()objdump -j .text/.data -S obj 輸出指定段的資訊,大概就是反組譯碼原始碼把objdump -S obj C語言與組合語言同時顯示
查看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.sob6ef4000-b6ef9000 r--p 0002e000 5d:10 1567 /system/lib/libsurfaceflinger.sob6ef9000-b6efa000 rw-p 00033000 5d:10 1567 /system/lib/libsurfaceflinger.sob6feb000-b6fed000 r-xp 00000000 5d:10 464 /system/bin/surfaceflingerb6fed000-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第六列是映像檔案的路徑
這裡發現記憶體中指令是對的,考慮可能是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開始減少,依次儲存。。。
暫時記錄這麼多~ 後續有需要再添加~
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android——coredump解析