重新编译arm-linux-androideabi-gdb和gdbserver

一、引言

         Android应用程序在运行的时候,不管是dex还是native的so,都要加载到内存里面,所以直接把与之对应的内存dump出来分析是一个不错的主意,ndk给我们提供了可供开发者远程调试的gdb和gdbserver,但是一些功能比如gcore不能用,本文通过重新编译gdb和gdbserver ,从而可以达到使用gcore把内存dump出来的目的。以下使用的android源码是android4.4.

二、开发环境

Ubuntu 12.04

android-ndk-r9

三、解决过程

首先编译arm-linux-androideabi-gdb,android-ndk-r9中自带了gdbserver和arm-linux-androideabi-gdb,但是使用gdbserver和arm-linux-androideabi-gdb调试手机的时候,用gcore出现Command notimplemented for this target,原因是ndk里面自带的arm-linux-androideabi-gdb把gcore移除了,所以需要自己编译一个arm-linux-androideabi-gdb

以下是编译过程:

首先下载源码

mkdir gdb_build

git clone https://android.googlesource.com/toolchain/build.git
git clone https://android.googlesource.com/toolchain/gdb.git

把build和gdb的源码下载完毕

执行

cd gdb_build
./configure --target=arm-linux-androideabi --prefix=gdb_build/gdb/gdb-7.6/arm-linux
make
make install

等待编译完毕。

arm-linux-androideabi-gdb就在gdb_build/gdb/gdb-7.6/arm-linux下生成了

在远程调试的时候可能发现如下错误

remote g packet reply is too long

需要修改gdb-7.6/gdb/remote.c中把如下2行注释掉

//if (buf_len > 2 * rsa->sizeof_g_packet)
//  error(_("Remote 'g' packet reply is too long: %s"), rs->buf);

修改成

if (buf_len > 2 * rsa->sizeof_g_packet) {
     rsa->sizeof_g_packet = buf_len ;
      for(i = 0; i < gdbarch_num_regs (gdbarch); i++)
      {
        if (rsa->regs[i].pnum == -1)
        continue;
 
        if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
        rsa->regs[i].in_g_packet = 0;
        else
        rsa->regs[i].in_g_packet = 1;
}

以上编译的是gdb7.6,需要与之版本对应的gdbserver。

编译gdbserver流程:

参考http://www.omappedia.org/wiki/Android_-_How-to_Rebuild_gdbserver

需要android源码,首先创建sysroot目录,

cd gdb_build
./build/build-sysroot.sh ~/workspace/androidsrc/out/target/product/generic/ ./sysroot

然后修改~/workspace/androidsrc/ndk/build/tools/build-gdbserver.sh脚本,

if [ "$NOTHREADS" !="yes" ] ; then
     # We're going to rebuild libthread_db.o fromits source
     #that is under sources/android/libthread_db and place its header
     # andobject file into the build sysroot.
    LIBTHREAD_DB_DIR=$ANDROID_NDK_ROOT/sources/android/libthread_db/gdb-$GDB_VERSION
     if[ ! -d "$LIBTHREAD_DB_DIR" ] ; then
        dump "ERROR: Missing directory: $LIBTHREAD_DB_DIR"
        exit 1
     fi
     #Small trick, to avoid calling ar, we store the single object file
     #with an .a suffix. The linker will handle that seamlessly.
     runcp $LIBTHREAD_DB_DIR/thread_db.h $BUILD_SYSROOT/usr/include/
     run$TOOLCHAIN_PREFIX-gcc --sysroot=$BUILD_SYSROOT -o$BUILD_SYSROOT/usr/lib/libthread_db.a -c $LIBTHREAD_DB_DIR/libthread_db.c
     if [$? != 0 ] ; then
        dump "ERROR: Could not compile libthread_db.c!"
        exit 1
     fi
 fi 

修改为 

<<NOT_NEEDED
 # Removelibthread_db to ensure we use exactly the one we want.
 rm -f$BUILD_SYSROOT/usr/lib/libthread_db*
 rm -f$BUILD_SYSROOT/usr/include/thread_db.h
 
 if ["$NOTHREADS" != "yes" ] ; then
     #We're going to rebuild libthread_db.o from its source
     #that is under sources/android/libthread_db and place its header
     # andobject file into the build sysroot.
    LIBTHREAD_DB_DIR=$ANDROID_NDK_ROOT/sources/android/libthread_db/gdb-$GDB_VERSION
     if[ ! -d "$LIBTHREAD_DB_DIR" ] ; then
        dump "ERROR: Missing directory: $LIBTHREAD_DB_DIR"
        exit 1
     fi
     #Small trick, to avoid calling ar, we store the single object file
     #with an .a suffix. The linker will handle that seamlessly.
     runcp $LIBTHREAD_DB_DIR/thread_db.h $BUILD_SYSROOT/usr/include/
     run$TOOLCHAIN_PREFIX-gcc --sysroot=$BUILD_SYSROOT -o$BUILD_SYSROOT/usr/lib/libthread_db.a -c $LIBTHREAD_DB_DIR/libthread_db.c
     if [$? != 0 ] ; then
        dump "ERROR: Could not compile libthread_db.c!"
        exit 1
     fi
 fi
 NOT_NEEDED

修改~/workspace/androidsrc/ndk/build/tools/build-gdbserver.sh

get_toolchain_install ()
 {
     localNDK=”$1”
     shift
     echo"$ NDK/$(get_toolchain_install_subdir “%@”)”
 }

 修改为

 get_toolchain_install ()
 {
     echo"$1/prebuilts/gcc/$HOST_TAG/arm/$TOOLCHAIN"
 }

然后执行

sudo ~/workspace/androidsrc/ndk/build/tools/build-gdbserver.sh
~/workspace/gdb_build ~/workspace/androidsrcarm-linux-androideabi-4.6 --verbose --build-out=~/workspace/gdb_build/install--gdb-version=7.6 --sysroot=~/workspace/gdb_build/sysroot

编译的时候可能会出现2个错误,

~/workspace/gdb_build/gdb/gdb-7.6/gdb/gdbserver/gdb_proc_service.h:79:1:error: unknown type name 'elf_gregset_t'
~/workspace/gdb_build/gdb/gdb-7.6/gdb/gdbserver/linux-low.c:113:3:error: conflicting types for 'Elf32_auxv_t'
~/workspace/gdb_build/install/sysroot/usr/include/elf.h:40:3:note: previous declaration of 'Elf32_auxv_t' was here
~/workspace/gdb_build/gdb/gdb-7.6/gdb/gdbserver/linux-low.c:128:3:error: conflicting types for 'Elf64_auxv_t'
~/workspace/gdb_build/install/sysroot/usr/include/elf.h:47:3:note: previous declaration of 'Elf64_auxv_t' was here

elf_gregset_t类型不识别,Elf32_auxv_t和Elf64_auxv_t定义冲突。

修改~/workspace/gdb_build/gdb/gdb-7.6/gdb/gdbserver/linux-low.c的结构体Elf32_auxv_t和Elf64_auxv_t,把他的名字改变。

修改

~/workspace/gdb_build/gdb/gdb-7.6/gdb/gdbserver/gdb_proc_service.h

#ifndef HAVE_PRGREGSET_T
typedef elf_gregset_t prgregset_t;
#endif

上面添加

typedef unsigned long elf_greg_t;
typedef elf_greg_t elf_gregset_t[35];
编译好的gdbserver在~/workspace/gdb_build/install生成。


你可能感兴趣的:(linux,ubuntu,gdb,native,ARM)