重新编译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生成。


编译 `arm-linux-gnueabih-gdb` 和 `arm-linux-gnueabih-gdbserver` 的步骤如下: 1. 下载 GNU 工具链 - 从官网下载源代码:https://ftp.gnu.org/gnu/binutils/binutils-2.36.tar.gz - 解压缩源代码:`tar -zxvf binutils-2.36.tar.gz` 2. 配置交叉编译环境变量 - `export CC=arm-linux-gnueabihf-gcc` - `export CXX=arm-linux-gnueabihf-g++` - `export AR=arm-linux-gnueabihf-ar` - `export AS=arm-linux-gnueabihf-as` - `export LD=arm-linux-gnueabihf-ld` - `export RANLIB=arm-linux-gnueabihf-ranlib` 3. 配置和编译 `binutils` - 进入源代码目录:`cd binutils-2.36` - 创建编译目录:`mkdir build && cd build` - 配置交叉编译环境:`../configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=/usr/local/arm-linux-gnueabihf` - 编译:`make` - 安装:`make install` 4. 配置和编译 `gdb` - 下载 GDB 源代码:https://ftp.gnu.org/gnu/gdb/gdb-10.1.tar.gz - 解压缩源代码:`tar -zxvf gdb-10.1.tar.gz` - 进入源代码目录:`cd gdb-10.1` - 创建编译目录:`mkdir build && cd build` - 配置交叉编译环境:`../configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=/usr/local/arm-linux-gnueabihf` - 编译:`make` - 安装:`make install` 5. 配置和编译 `gdbserver` - 下载 GDB 源代码:https://ftp.gnu.org/gnu/gdb/gdb-10.1.tar.gz - 解压缩源代码:`tar -zxvf gdb-10.1.tar.gz` - 进入源代码目录:`cd gdb-10.1/gdb/gdbserver` - 创建编译目录:`mkdir build && cd build` - 配置交叉编译环境:`export CC=arm-linux-gnueabihf-gcc` - 配置编译选项:`../configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=/usr/local/arm-linux-gnueabihf` - 编译:`make` - 安装:`make install` 注意:以上步骤仅供参考,实际操作时可能会因为环境和版本差异而有所不同。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值