java 调试 gdb_android gdb 调试实例演示(有源代码篇)
android ndk代碼的調(diào)試本身還是有點(diǎn)麻煩的,因?yàn)楸旧韌oogle android的sdk
主要是面向廣大的java程序員的,所以后來發(fā)布的 ADT 集成開發(fā)環(huán)境對java的代碼調(diào)試
支持還是很好的,但是對于 ndk編寫的so代碼就沒有那么直觀的圖形界面的調(diào)試工具了。
相信將來google肯定要開發(fā)出來 調(diào)試c/c++代碼的圖形調(diào)試工具,但是目前大多數(shù)剛開始
用ndk編寫c或者c++代碼的程序員調(diào)試的時(shí)候一般還是打log,然后再根據(jù)log來進(jìn)行分析。
這種方法雖然簡單,但是缺點(diǎn)也是很明顯的,很多詳細(xì)的信息不能調(diào)試,為了解決這個(gè)問題,
我寫了這篇 android gdb 調(diào)試本地so的實(shí)例演示,以供大家參考。
做任何事情都是有代價(jià)的,用log調(diào)試的方法簡單方便,用android gdb調(diào)試就需要記下一些
命令,并且做一些前期的準(zhǔn)備工作了。
前期準(zhǔn)備工作:
1 gdbserver 這個(gè)是需要放在android 手機(jī)里面的,一般放在 /system/bin/目錄即可。
注意:直接從android源碼編譯出來的 gdbserver 放到android 手機(jī)中運(yùn)行一般會(huì)crash的
官方的說法是 bionic 庫不匹配導(dǎo)致,所以建議重新編譯一個(gè)gdbserver。具體如何
編譯 gdbserver 見我的另外一篇博客
http://sunzeduo.blog.51cto.com/2758509/1381552
2 對應(yīng)版本的 androidgdb
比如我的gdbserver是shell@android:/ # gdbserver --version
GNU gdbserver (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
gdbserver is free software, covered by the GNU General Public License.
This gdbserver was configured as "arm-eabi-linux"
而使用的 android gdb應(yīng)該是
root@ubuntu:~/Desktop# ./androidgdb --version
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
.
注意版本一致,而./androidgdb 需要你下載一個(gè)ndk里面有
我使用的在
/root/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb
這個(gè)路徑里面
3 會(huì)使用常用gdb命令,具體命令的介紹,見我的另外一篇博文
http://sunzeduo.blog.51cto.com/2758509/1387538
4 一個(gè)自己寫好的demo程序,這個(gè)我會(huì)放在附件中的,后面的調(diào)試都是以這個(gè)demo例子來進(jìn)行的
這里先大概介紹一下 這個(gè)demo程序中 jni的文件,一共有三個(gè)文件,如下圖
target.c ? ? 是一個(gè)服務(wù)器代碼,隨著代碼啟動(dòng)而啟動(dòng)運(yùn)行
socketclient.c ?是個(gè)客戶端代碼,給java層提供jni接口
socketback.c ? ?打醬油的不用管他
開始調(diào)試
前期準(zhǔn)備的工作做好以后,可以開始調(diào)試了。
1 首先啟動(dòng)要調(diào)試的程序,ps 獲取其進(jìn)程號 (手機(jī)界面操作即可)
shell@android:/ # ps | busybox grep socketcomm
u0_a66 26175 125 494016 50792 ffffffff 40090a40 S com.example.socketcomm
root 27938 27933 860 336 c04fbc9c 4004a5f4 S /data/data/com.example.socketcomm/files/target
2 啟動(dòng)gdbserver attach到目標(biāo)進(jìn)程 ?(手機(jī)shell中操作)
shell@android:/ # gdbserver remote:1234 --attach 26175
Attached; pid = 26175
Listening on port 1234
其中 remote:1234 表示映射成tcp的1234端口,這個(gè)時(shí)候重新打開一個(gè) adb shell 在ps com.example.socketcomm
發(fā)現(xiàn)
shell@android:/ # ps | busybox grep example
u0_a66 26175 125 494016 50792 ffffffff 40090a40 t com.example.socketcomm
root 27938 27933 860 336 c04fbc9c 4004a5f4 S /data/data/com.example.socketcomm/files/target
進(jìn)程狀態(tài)已經(jīng)變成 t了,表示 attach已經(jīng)成功了
3 啟動(dòng)gdb 來進(jìn)行調(diào)試 (pc環(huán)境中操作,我用的是ubuntu系統(tǒng))
root@ubuntu:~/Desktop# adb forward tcp:1234 tcp:1234
首先端口映射,映射成 1234 端口號
root@ubuntu:~/Desktop# ./androidgdb
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
.
(gdb) target remote:1234
Remote debugging using :1234
0x40090a40 in ?? ()
(gdb)
這個(gè)時(shí)候已經(jīng)進(jìn)入 gdb了,當(dāng)然現(xiàn)在還沒有加載symbols 所以gdb的很多調(diào)試還不能用 輸入 list
bt 這些命令還是不太直觀或者不能使用
這里使用 file命令將symbols文件加載進(jìn)來。因?yàn)槲覀冇性创a,而本身android 源碼ndk編譯的時(shí)候
默認(rèn)是加 -g選項(xiàng)的,沒有被 strip的so庫在
/root/android/temp/socketcomm/obj/local/armeabi
這個(gè)目錄下,而在libs下的so是被 strip過的版本(strip剝光,表示去掉了symbols符號表的版本)
如下圖:
(gdb) set solib-search-path /root/android/temp/socketcomm/obj/local/armeabi
這個(gè)命令將so 的路徑設(shè)置一下
設(shè)置完成以后
(gdb) list socketclient.c:97
92 LOGI("read data fail !");
93 return NULL;
94 }
95
96
97 buffer[recbytes]='\0';
98 LOGI("recv buff %s",buffer);
99
100 close(cfd);
發(fā)現(xiàn)已經(jīng)有代碼顯示了
(gdb) b socketclient.c:97
Breakpoint 1 at 0x56dd7044: file jni/socketclient.c, line 97.
具體代碼看 socketclient.c 這兩行是接收到服務(wù)器打代碼,然后通過logcat 打印出來的
我們在這里設(shè)置斷點(diǎn)(gdb) b socketclient.c:97
Breakpoint 1 at 0x56dd7044: file jni/socketclient.c, line 97.
繼續(xù)執(zhí)行(gdb) c
Continuing.
[New Thread 26648]
[Switching to Thread 26648]
Breakpoint 1, Java_com_example_socketcomm_JniSocketClient_cliensocket (
env=0x56d7e870, thiz=, jstr=)
at jni/socketclient.c:97
97 buffer[recbytes]='\0';
(gdb) print buffer
$1 = "server back buff 64", '\000'
(gdb) bt
#0 Java_com_example_socketcomm_JniSocketClient_cliensocket (env=0x56d7e870,
thiz=, jstr=) at jni/socketclient.c:97
#1 0x4074de34 in ?? ()
#2 0x4074de34 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
ok 在斷點(diǎn)處停止了,然后值也打出來了
更多調(diào)試技巧,需要看gdb的命令,demo程序見附件。
總結(jié)
以上是生活随笔為你收集整理的java 调试 gdb_android gdb 调试实例演示(有源代码篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 惰性_Python学习--
- 下一篇: @responseBody java_j