網上有不少文章,談論 ndk-gdb對java/native code聯合調試 ,本人參考了不少,雖然這些文章沒能解決問題,但是給了不少的幫助,在此,分享本人搭建 java +native code(c c++)環境的整個過程。
1. gdb 調試器 與 gdbserver 的關系,就是 gdb 與 stub的關系,如下圖所示

2. 調試工具 及調試環境
在搭建android調試環境過程中,很多文章中原理上做了比較好的介紹,但開始始終無法成功,最后發現運行的平台,使用的工具等一些細節方面是失敗的主要原因。
運行環境 : cygwin
ndk : android-ndk-r7b
gdb : ${ndk-home}\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gdb
(version = 6.6)
gdbserver : 每個模擬器上, 在system/bin/gdbserver 有默認的程序
失敗配置: gdbserver (version 7.1) : android emulator : 4.0 (version) 14 (API level)
成功配置: gdbserver() : android emulator : 2.3.3 (version) 10 (API level)
注意:經過嘗試必須注意 gdb vs gdbserver版本的匹配,
如果system/bin下的gdbserver 不匹配,可以把匹配的gdbserver push emulator 然后指定./gdbserver ,
必須指定"./",因為linux下面,默認是尋找 system目錄 (第一個陷阱)
如何才能最快的找到匹配的 gdb 和 gdbserver呢?
最簡單的就是使用 $(NDK_HOME)\toolchains\arm-linux-androideabi-4.4.3\prebuilt\gdbserver, 這個必定是和你所使用的gdb是相互匹配的。[ex2]
3. ndk 與 native code 這里不具體分析,可參考我其他的文章,
這里我們使用 ndk-build NDK_DEBUG=1 生成帶符號表的 .so
4. gdb gdbserver 調試過程 [2]
Android NDK使用C/C++開發的native code,在Linux下調試主要使用GDB調試。
當然使用Logcat或自己寫入文件的方式調試也是可以的。
有關Log打印可以參考Android開發網早期文章。
對於使用ndk-build編譯出來的工具,除了so庫文件外,會有gdbserver和gdb.setup文件,方法為
(3). 我們將生成的gdbserver和so庫文件復制到/data目錄下面,使用adb push命令,或者直接使用Eclipse中DDMS的File Explorer手動復制,不過對於真機可能沒有這個列舉目錄的權限,你可以使用Android模擬器。
或者 使用 adb install -r androidApp_debug.apk 將apk加載到模擬器
(4). 使用adb shell命令 進入Android手機或模擬器的命令行,進入androidApp 包,
ps 查看androidApp 進程 pid
啟動gdbserver,如 ./gdbserver :5039 --attach pid
會看到 Listening on port 5039 這代表正在監聽。
(5). 啟動客戶端 adb forward tcp:5039 tcp:5039 重定向到gdbserver監聽端口
(6) . ${NDK-HOME}\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gdb.exe 進入調試狀態

(7). (gdb) target remote :5039 連接 gdbserver進行調試
注意: 在第(6)過程中,可以發現 "no symbol table is loaded",
是應為打包在 androidApp_debug.apk 里面的androidApp.so 是不帶有符號表的,
需要設置 solib-search-path 來指定收索so的路徑,
之前可通過show solib-search-path 先觀察當前搜索so的路徑
( 陷阱二:在linux下面,路徑 使用/,如 debug版本so文件所在路徑為
solib-search-path ./obj/local/armeabi/***.so,
而在window下使用cygwin,set solib-search-path .\obj\local\armeabi\***.so )
此處,由於剛開始對原理不是很清楚,花費了很多時間,都無法加載sysbol table,痛苦啊!!!
接下來,就可以使用gdb進行調試。
5. 上述調試方法,所有的都由使用者完成,對於理解整個調用過程,很有幫助,但在實際的項目過程中,可以采用ndk-gdb 來進行調試
具體過程可參考如下 http://www.devdiv.com/thread-32770-1-1.html
再次強調,
(1). 利用這種方式,必須保證gdb 版本與 gdbserver一致, android emulator 版本不能太高,
我采用的版本為 2.3.3 api level 10 才成功,否則,可能會產生莫名其妙的問題
(2). 利用這種方式,eclipse 生成的gdb.setup 文件中 set solib-search-path ./obj/local/armeabi/***.so
在cygwin下運行需要人工修正 set solib-search-path .\obj\local/armeabi\***.so
補充:
5-x. 基本的調試方法都需要gdb 和 gdbserver的配合來調試,而ndk-gdb將兩者集成,方便用戶來調試。
采用5所描述的方法,也需要eclipse先運行啟動,然后通過ndk-gdb自動連接上,這種方法有其優勢,方便同時調試android中的 java,native。
那么,可否僅僅使用ndk-gdb直接來調試native嗎?
本人測試環境是目前采用的android-ndk-r9a
(1). adb install 安裝 *.apk 到 手機
(2). 在工程目錄下 ndk-gdb --start -x gdbinit
其中gdbinit是用戶自定義文件,包含用戶設置的命令(這些命令也可以在gdb進入手手動輸入,
比如 set solib-search-path)
(3). 進入gdb后,可以通過設置 set solib-search-path 來加載動態庫和符號表
(4). 如果步驟(3)失敗,可以通過 set breakpoint pending on 來開啟breakpoint pending
pending on 是指指定的庫和符號沒有加載,允許預先設置斷點,當代程序運行符號加載后可以在斷點處停止,
默認情況下是 off
(5). 通過第四步設置后,雖然你無法通過 l命令顯示代碼,但你可以通過break file:line命令來設置pending的斷點,等設置后斷點
c 運行程序,會自動加載符號表並且在斷點處停止。
6. 如果你把所有的都集成到eclipse中,ide圖形化統一對java,native code 進行編碼,運行與調試,
參考Eclipse+CDT+GDB調試android NDK程序[4] http://www.cnblogs.com/shadox/archive/2011/12/02/2272564.html
補充: A1: 通過網絡使用ADB
電腦可以通過網絡(尤指無線網絡)與Android的adbd進行連接。
原理:
adb server: 計算機上的一個服務進程,進程名為adb
adb daemon: Android 手機上的一個服務進程,進程名為adbd
adb client: 你可以認為是計算機上的一個終端窗口,進程名也為adb
你的指令通過adb client 交給adb server,server和daemon之間進行通訊。
因此,這里建立的連接實際上是server和daemon之間的連接。
最簡單的方法:
通過USB連接后直接通過ADB設置
1. adb tcpip 5555 #讓adbd重新啟動,並監聽端口5555
2. adb connect 192.168.0.101:5555
改回原先狀態:
adb usb
如果發現失敗,那么原因主要是通過adb發出的命令是用戶級的(實際在手機上的用戶為shell),而切換監聽方式所需的權限需要root才行。
如果你的手機有足夠的權限的話,運行
adb root
如果成功的話,再執行上面的命令。
參考:
1. GDBstub系列剖析與改進 http://www.jdzj.com/plc/article/2011-12-28/33206-1.htm
GDB 遠程調試 gdbserver http://zjf30366.blog.163.com/blog/static/411164582009319501626/
2. 使用GDB調試Android NDK開發的程序 http://www.android123.com.cn/topic/ndk/962.html
3. 使用eclipse/ndk-gdb對java/native code聯合調試 http://www.devdiv.com/thread-32770-1-1.html
4. Eclipse + CDT +GDB 調試android NDK程序 : http://www.cnblogs.com/shadox/archive/2011/12/02/2272564.html
--------------------------------------------------------------------------------------------------------------------------------
補充: 最近研讀android 源碼,一直想調試native部分,回顧這篇文章在 ex1 ex2 處做了些補充。(該方法不局限於ndk編程時使用,采用gdb /adb 調試的情況,均可參考)
5. http://blog.chinaunix.net/uid-12567959-id-3214283.html