08 10月 2013

[Android] NDK Debug 與 breakpoint 失效的解決之道

在 Android 開發環境裡,新版的 NDK (目前為 r9 )提供的 GDB Debug C//C++環境其實已經算是很友善的了。不像以前需要下一堆的 command line 才行。

目前我的開發環境:

  • ADT - adt-bundle-windows-x86_64-20130729
  • NDK - android-ndk-r9


簡單說一下 Debug NDK 的步驟

1. Eclipse Preferences

設定  Eclipse Preference | Android | NDK | NDK Location 
填入正確的 NDK 下載路徑

2. 設定 Project property NDK_DEBUG=1

 Project Property | C/C++ Builder | Builder Settings 
取消 Use default build command的選項
輸入 ndk-build NDK_BUILD=1
註:Application.mk or Android.mk 都無需修改,新版的 ADT/NDK 都已經 handle 好其他的設定了

3. 設好中斷點

在 Eclipse 裡的 C/C++ code,設好中斷點,等著上鉤

4. Debug As "Android Native Application"

由於目前 ADT 在 Debug 時,同一時間只能選擇 Debug Java or C/C++
所以如果 Debug As "Android Application"的話,就是 Debug Java level
如果 Debug As "Android Native Application"的話,就是 Debug C/C++ level


* 問題 *

Debug 時設中斷點,可能會出現類似這樣的Error

  • No symbol table is loaded.  Use the "file" command.




* 原因 *

原因是 GDB 在 attach 上去時,如果 shared library(.so) 檔還沒被 load 進來時,所設的中斷點就沒有用了(不確定是 GDB 的限制還是 NDK 的 bug )

所以,如果在 App 執行起來後,馬上就 load shared library 的話,應該是不會遇到這樣的問題。但是為了執行效能,很多 .so 的 module 都會等到使用者用到時才會將它 load 起來,就會遇到這樣的問題了。

* 解決之道 *

假設今天要 Debug libTestNDK.so
試著讓 GDB server 暫停住,按下 Debug 的 Suspend 的 button,然後在才能在 GDB Console 輸入指令
info shared

From        To          Syms Read   Shared Object Library 
                        No          /system/bin/linker 
0x4012b860  0x4015b184  Yes         D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libc.so 
                        No          libstdc++.so 
                        No          libm.so 

上面並沒有顯示 libTestNDK.so ,表示 libTestNDK.so 還沒被load起來
試著操作App,確保 Java layer 的 loadLibrary 有被執行到
java.lang.System.loadLibrary("TestNDK");

再次讓GDB Suspend,接著再輸入info shared一次
From        To          Syms Read   Shared Object Library 
                        No          /system/bin/linker 
0x4012b860  0x4015b184  Yes         D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libc.so 
                        No          libstdc++.so 
                        No          libm.so 
0x69817898  0x69922680  No          D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libTestNDK.so

有顯示 libTestNDK.so,但是 Syms Read 的狀態是 No
輸入下面的指令,讓 GDB 重新 load sharedlibrary 的 symbol
sharedlibrary

然後再輸入一次 info shared 看結果,狀態會變成 Yes,就代表你成功了!
0x69817898  0x69922680  Yes          D:/WorkRoom/Android/TestNDK/obj/local/armeabi-v7a/libTestNDK.so


再試著去新增中斷點,應該就不會有 Error,可以正常 Debug 了!



註:

  • 用 Eclipse 去 Debug NDK,其實問題還滿多的
  • Android 4.3 不能 Debug 進 NDK,不用試了,直接升級到 4.4 吧!
  • 真的是很慢....
  • 有時候中斷了,可是無法 Step Into、Step Next,也無法成功看到 Watch 的參數


Reference




3 則留言:

Ho YuanHou 提到...

您有試過VisualGDB 嗎,我是個新手,光弄這些工具就快煩死了,NDK的Native Audio的 Sample 一直裝不起來,試了VisualGDB,簡單多了

Falldog 提到...

VisualGDB好像很威的樣子,感謝分享!

Juwan Zhu 提到...

非常感谢,解决我的问题,将
```Java
Static {
...
}部分代码放入MainActivity,breakpoint就可以起作用了,感谢。