gdb调试android原生程序,使用gdb调试android原生程序

Android NDK目录下的gdb虽然可以调试android程序,但是这个不包含符号信息,调试时需要设置Android系统动态链接库的符号加载路径,并且只能调试拥有调试信息的原生程序,而一般情况下,使用 Android NDK编译的原生程序都不包含调试信息,因此无发使用官方的gdb

我们可以手动编译一个静态版本的gdb调试器,首先到gdb的官方下载gdb的源代码,我们这里下载的版本为7.3.1,下载地址为:ftp://sourceware.org/pub/gdb/gdb-7.3.1.tar.gz,

下载后解压源代码,在终端下使用命令安装编译gdb所需的软件包。

sudo apt-get install bison flex  libncurses5-dev texinfo gawk libtool

编译gdb时不要使用自带的多线程库thread_db.c,应使用Android NDK中的修改版本,位于Android NDk 的sources/android/libthread_db/gdb-7.3.x/libthread_db.c,为了避免兼容性的问题,将其编译成静态库,配置gdb编译脚本如下

export TOOLCHAIN_PATH=/home/android/tools/android/android-ndk-r8b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86

export PATH=$TOOLCHAIN_PATH/bin:$PATH

export SYSROOT=/home/android/tools/android/android-ndk-r8b/platforms/android-14/arch-arm

export TOOLCHAIN_PREFIX=$TOOLCHAIN_PATH/bin/arm-linux-androideabi

export CC="$TOOLCHAIN_PREFIX-gcc --sysroot=$SYSROOT"

export  AR="$TOOLCHAIN_PREFIX-ar"

$CC -o $SYSROOT/usr/lib/libthread_db.o -c /home/android/tools/android/android-nkd-r8b/sources/android/libthread_db/gdb-7.3.x/libthread_db.c

$AR -r $SYSROOT/usr/lib/ibthread_db.a $SYSROOT/usr/lib/libthread_db.o

#配置gdb编译脚本

./configure --target=arm-elf-linux --enable-static --disable-stripping -with-libthread-db=$SYSROOT/usr/lib/libthread_db.a

"--target=arm-elf-linux" 指定了被调试的程序运行的系统平台,“--enable-static”指定了静态编译,“--disable-stripping”指定禁止剥离符号信息,“--with-libthread-db”手动指定多线程库文件,在终端上依次执行以上命令会声称makefile 我呢间,接下来还需要手动修改gdb-7.3.1/gdb目录下的remote.c文件,找到process_G_packet()函数的代码,将一下的内容

if(but_len>2*rsa->sizeof_g_packet)

error(_("Remote 'g' packet reply is too long:%s"),rs->but);

修改为

if(but_len>2*rsa->sizeof_g_packet)

rsa->sizeof_g_packet=buf_len;

for(i=0;i

{

if(rsa->regs[i].pnum==-1)

continue;

if(rya->regs[i].offset>=rsa->sizeof_g_packet)

rsa->regs[i].in_g_packet=0;

else

rsa->regs[i].in_g_packet=1;

}

修改保存后,在终端上执行make编译gdb

单独使用gdb还不能调试android原生程序 还需要编译gdbserver,这个的源代码在 gdb-7.3.1/gdb/gdbserver 目录下,在终端下执行一下命令配置gdbserver编译脚本

export CC="$TOOLCHAIN_PREFIX-gcc --sysroot=$SYSROOT"

export CFLAGS="-02 -D__ANDROID__ -DANDROID -DSTDC_HEADERS -D__GLIBC__"

./configure --host=arm-linux-androideabi --with-libthread-db=$SYSROOT/usr/lib/libthread_db.a

命令执行完成后会在gdb-7.3.1/gdb/gdbserver 目录下声称makefile文件,打开该文件找到 WERROR_CFLAGS的定义,将它的值清空,然后打开config.h文件,将“/*#undef HAVE_LWPID_T */”改为“#define HAVE_LWPID_T 1”,修改后保存,然后在终端下执行make编译gdbserver.

下面介绍如何调试,首先准备一个android app,这个用一个名为testapp的程序,在终端下执行以下两个命令将testapp与gdbserver复制到android石碑的/data/local/tmp目录

adb push test app /data/local/tmp

dab push gdbserver /data/local/tmp

执行以下两行命令给两个文件加上可执行权限

adb shell chmod 755 /data/local/tmp/testapp

adb shell chnod 755 /data/local/tmp/gdbserver

接着执行 “adb shell /data/local/tmp/gdbserver:12345 /data/local/tmp/testapp”,启动dgb调试服务器,会输入如下信息

Process /data/local/tmp/testapp create; pid=292

Listening on port 12345

程序其实调试服务器已经启动,并且监听了12345号端口,打开另一个终端窗口执行以下命令开启端口转发

dab forward tcp:12345 tcp:12345

在pc 端的终端下执行./gdb启动gdb调试器,然后执行以下命令连接gdb调试服务器

target remote localhost:12345

命令执行后会输出

(gdb) target remote localhost:12345

Remote debugging using localhost:12345

warning: Can not parse XML target description; XML support was disabled at compile time

0xb000100 in ?? ()

(gdb)

使用 ida pro 或者objdump 找到程序main()函数地址,例如 0x8580,在gdb Shell 环境下执行命令“b *0x8580” 在main()函数的第一行上设置断点,输出信息如下

(gdb) b *0x8580

Breakpoint 1 at 0x8580

(gdb)

断点设置完成后输入continue 让程序继续执行,输出信息如下

(gdb)continue

Continuing.

Program received signal SIGSEGV,Segmentation fault.

0x00008584 in ??()

执行"set disassemble-next on "设置反汇编显示代码,然后执行“dosas 0x8580,+20”显示0x8580以下20各字符的反汇编代码,输出信息如下

(gdb)disas 0x8580,+20

Dump of assembler code from 0x8580 to 0x8594

0x00008580:ldr r0,[pc,#16] ;0x8598

=>  0x00008584:push {r4,lr}

0x00008588:add r0,pc,r0

0x0000858c:bl 0x84f8

0x00008590:mov r0,#0

End of assembler dump.

(gdb)

接下来可以输入si或者ni 命令来单步调试了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《移动开发经典丛书:Android C++高级编程:使用NDK》提供了移植、开发以及利用Android平台上的C++和其他原生代码所需要的知识和技能,以便于运行图形化的高级应用和更复杂的原生应用。 内容简介   Android是移动电话市场的主要角色而且其市场份额正在持续增长。它是一个完整的、开放的、免费的移动平台,该平台给移动应用开发者提供了无限的机会。   虽然Android平台的官方程序语言是Java,但应用开发者不限于仅使用Java技术。   Android允许应用开发者通过Android原生开发包(NDK)使用诸如C和C++之类的原生代码语言实现他们的部分应用。《移动开发经典丛书·Android C++高级编程:使用NDK》中我们将学习如何用AndroidNDK通过原生代码语言去实现自己的Android应用中对性能要求较高的部分。   《移动开发经典丛书·Android C++高级编程:使用NDK》介绍了原生应用开发、可用的原生API以及故障排除技术的详细叙述,包括用按步骤的指导和屏幕截图以帮助Android开发人员迅速达到开发原生应用的目的。   主要内容:   在主要的操作系统上安装Android原生开发环境。   使用Eclipse集成开发环境开发原生代码。   使用Java原生接口(JNI)将原生代码与Java代码连接。   用SWIG自动生成JNI代码。   用POSIX和Java线程开发多线程原生应用。   用POSIXsockets开发网络原生应用。   用logging、GDB和Eclipse调试器调试原生代码。   用Valgrind分析内存问题。   用GProf测试应用性能。   用SIMD/NEON优化原生代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值