Android emulator中C代碼的調試——gdb/gdbservers時遇到的坑


版權聲明:本文為博主原創文章,未經博主允許不得轉載。

 

先寫個helloworld吧,在Android源碼樹中創建文件夾external/helloworld,加入文件:

// helloworld.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** arv)
{
    printf("Hello world~\n"); 
    return 0;
}
# Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := helloworld
LOCAL_CFLAGS += -march=armv4
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)

執行

$ mmm external/helloworld

生成可執行文件。

  • 啟動模擬器並將待調試的文件上傳到模擬器/data目錄,(注意要傳帶調試信息的)
$ emulator&
$ adb push out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld /data
  • 把gdbserver上傳到模擬器
$ adb push prebuilts/misc/android-arm/gdbserver /data

我的平台是Mac OSX,在不同的平台下gdbserver的位置可能會不同。不過我發現在emulator的system/bin下面是有gdbserver的,所以如果不傳,用這個默認的應該也可以。

  • 在設備上通過gdbserver啟動Native程序
$ adb shell gdbserver :1234 /data/helloworld
  • 在遠程調試機器上把本地tcp端口forward到設備的tcp端口
$ adb forward tcp:1234 tcp:1234
  • 在遠程調試機器上運行gdb
$ ./prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-gdb out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld

gdb的路徑會因平台而不同,helloworld要保證和模擬器上被調試的是同一個可執行程序。

  • 接下來是gdb的具體調試命令
(gdb) target remote :1234    # 連接到emulator的gdbserver
Remote debugging using :1234
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Cannot access memory at address 0x0
0xb3446658 in ?? ()
(gdb) b main
Breakpoint 1 at 0xb34665cc: file external/helloworld/helloworld.c, line 6.
(gdb) c
Continuing.
warning: Could not load shared library symbols for 5 libraries, e.g. /system/bin/linker.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?

Breakpoint 1, main (argc=1, arv=0xbe8c5ba4) at external/helloworld/helloworld.c:6
6        printf("Hello world~\n");
(gdb) n 5    { (gdb) info sharedlibrary
From        To          Syms Read   Shared Object Library
                        No          /system/bin/linker
                        No          /system/lib/libc++.so
                        No          /system/lib/libc.so
                        No          /system/lib/libm.so
                        No          /system/lib/libnetd_client.so
(gdb) set solib-absolute-prefix out/target/product/generic/symbols/
Reading symbols from out/target/product/generic/symbols/system/bin/linker...done.
Loaded symbols for out/target/product/generic/symbols/system/bin/linker
Reading symbols from out/target/product/generic/symbols/system/lib/libc++.so...done.
Loaded symbols for out/target/product/generic/symbols/system/lib/libc++.so
Reading symbols from out/target/product/generic/symbols/system/lib/libc.so...done.
Loaded symbols for out/target/product/generic/symbols/system/lib/libc.so
Reading symbols from out/target/product/generic/symbols/system/lib/libm.so...done.
Loaded symbols for out/target/product/generic/symbols/system/lib/libm.so
Reading symbols from out/target/product/generic/symbols/system/lib/libnetd_client.so...done.
Loaded symbols for out/target/product/generic/symbols/system/lib/libnetd_client.so
(gdb) info sharedlibrary
From        To          Syms Read   Shared Object Library
0xb3445e20  0xb345af18  Yes         out/target/product/generic/symbols/system/bin/linker
0xb33bc920  0xb34032d8  Yes         out/target/product/generic/symbols/system/lib/libc++.so
0xb331c8d0  0xb33685ac  Yes         out/target/product/generic/symbols/system/lib/libc.so
0xb32e8e30  0xb3300450  Yes         out/target/product/generic/symbols/system/lib/libm.so
0xb32bcb08  0xb32be914  Yes         out/target/product/generic/symbols/system/lib/libnetd_client.so (gdb)……

這部分命令是純調試功夫了,可是我遇到的大坑就在這!上面的順序是連接到emulator、設置斷點、continue斷住、設置動態庫搜索路徑、開始調試……


 

說一下我遇到的坑及現象。我認為連接設備、設置搜索路徑這些都屬於環境的搭建和配置,所以都放到了前面執行。next了兩步就收到了signal,說是非法指令:

(gdb) target remote :1234
Remote debugging using :1234
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Cannot access memory at address 0x0
0xb1df5658 in ?? ()
(gdb) set solib-absolute-prefix out/target/product/generic/symbols/
Reading symbols from out/target/product/generic/symbols/system/bin/linker...done.
Loaded symbols for out/target/product/generic/symbols/system/bin/linker
(gdb) n 33      bl __linker_init
(gdb) n

Program received signal SIGILL, Illegal instruction.
notify_gdb_of_load (info=0xbed759d8) at bionic/linker/linker.cpp:194
194      rtld_db_dlactivity();
(gdb) l 189      rtld_db_dlactivity();
190
191      insert_soinfo_into_debug_map(info);
192
193      _r_debug.r_state = r_debug::RT_CONSISTENT;
194      rtld_db_dlactivity();
195    }
196
197    static void notify_gdb_of_unload(soinfo* info) {
198      if (info->is_main_executable()) {
(gdb)

此時還沒有碰到helloworld就掛了,list查看當前的位置在bionic/linker/linker.cpp:194。

google了好多地兒,有的說這是Android4.1.2的一bug,這類文章大多是2012年的,而且號稱是已經fix掉了(http://code.google.com/p/android/issues/detail?id=40941)。還有的地兒出主意說現在這一行上斷住,然后修改PC寄存器(http://visualgdb.com/android/linker-sigill/)我看signal的位置是由arm指令跳轉到thumb指令,我試過,修改之后又冒出別的問題。我是用的是Android官方6.0.1_r11正式版的代碼數,不應該有這么嚴重的問題。

后來請教別的同事,發現他的操作就能完成完整的調試。跟我操作上最明顯的差別就是他每次都會換一個映射端口,懷疑是用過的端口再次映射會出問題。然后我反復回溯他的調試過程,發現真正的原因在於gdb命令的執行過程——不要過早地設定so路徑。


免責聲明!

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



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