Android emulator中C代码的调试——gdb/gdbservers时遇到的坑

来源:互联网 发布:sql 动态生成临时表 编辑:程序博客网 时间:2024/06/05 16:22

先写个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.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_MODULE := helloworldLOCAL_CFLAGS += -march=armv4LOCAL_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的具体调试命令
<strong>(gdb)</strong> target remote :1234    # 连接到emulator的gdbserverRemote debugging using :1234warning: Unable to find dynamic linker breakpoint function.GDB will be unable to debug shared library initializersand track explicitly loaded dynamic code.Cannot access memory at address 0x00xb3446658 in ?? ()<strong>(gdb) b main</strong>Breakpoint 1 at 0xb34665cc: file external/helloworld/helloworld.c, line 6.(gdb) cContinuing.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:66        printf("Hello world~\n");<strong>(gdb) </strong>5    {<strong>(gdb) info sharedlibrary</strong>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<strong>(gdb) set solib-absolute-prefix out/target/product/generic/symbols/</strong>Reading symbols from out/target/product/generic/symbols/system/bin/linker...done.Loaded symbols for out/target/product/generic/symbols/system/bin/linkerReading symbols from out/target/product/generic/symbols/system/lib/libc++.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libc++.soReading symbols from out/target/product/generic/symbols/system/lib/libc.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libc.soReading symbols from out/target/product/generic/symbols/system/lib/libm.so...done.Loaded symbols for out/target/product/generic/symbols/system/lib/libm.soReading 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<strong>(gdb) info sharedlibrary</strong>From        To          Syms Read   Shared Object Library0xb3445e20  0xb345af18  Yes         out/target/product/generic/symbols/system/bin/linker0xb33bc920  0xb34032d8  Yes         out/target/product/generic/symbols/system/lib/libc++.so0xb331c8d0  0xb33685ac  Yes         out/target/product/generic/symbols/system/lib/libc.so0xb32e8e30  0xb3300450  Yes         out/target/product/generic/symbols/system/lib/libm.so0xb32bcb08  0xb32be914  Yes         out/target/product/generic/symbols/system/lib/libnetd_client.so<strong>(gdb)……</strong>

这部分命令是纯调试功夫了,可是我遇到的大坑就在这!上面的顺序是连接到emulator、设置断点、continue断住、设置动态库搜索路径、开始调试……


说一下我遇到的坑及现象。我认为连接设备、设置搜索路径这些都属于环境的搭建和配置,所以都放到了前面执行。next了两步就收到了signal,说是非法指令:

<strong>(gdb) target remote :1234</strong>Remote debugging using :1234warning: Unable to find dynamic linker breakpoint function.GDB will be unable to debug shared library initializersand track explicitly loaded dynamic code.Cannot access memory at address 0x00xb1df5658 in ?? ()<strong>(gdb) set solib-absolute-prefix out/target/product/generic/symbols/</strong>Reading symbols from out/target/product/generic/symbols/system/bin/linker...done.Loaded symbols for out/target/product/generic/symbols/system/bin/linker<strong>(gdb) n</strong>33      bl __linker_init<strong>(gdb) n</strong>Program received signal SIGILL, Illegal instruction.notify_gdb_of_load (info=0xbed759d8) at bionic/linker/linker.cpp:194194      rtld_db_dlactivity();<strong>(gdb) l</strong>189      rtld_db_dlactivity();190191      insert_soinfo_into_debug_map(info);192193      _r_debug.r_state = r_debug::RT_CONSISTENT;194      rtld_db_dlactivity();195    }196197    static void notify_gdb_of_unload(soinfo* info) {198      if (info->is_main_executable()) {<strong>(gdb)</strong>

此时还没有碰到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路径。

0 0
原创粉丝点击