ndk-gdb對java/native code聯合調試


 

 

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

    

      1.  gdb 調試器 與 gdbserver 的關系,就是 gdb 與 stub的關系,如下圖所示 

 

[ex1]

        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文件,方法為

  (1). 在PC的命令提示符下進入ndk根目錄,執行ndk-build NDK_DEBUG=1 這樣,將會強制生成debug調試版的文件,將設我們NDK工程名為androidApp ,這里要說明的是編譯出來的庫文件在libs目錄下是沒有符號的,我們要obj下的文件,否則symbol無法正確加載。
  (2).  使用ant debug 或者 eclipse 直接生成 androidApp_debug.apk

  (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

 


免責聲明!

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



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