一、前言
我们在Linux-x86_64、Linux-aarch64等环境下可以通过编译对应的gdb工具直接在宿主机上面进行gdb调试,非常方便。但是我们发现在android上面进行gdb调试的话,只能通过系统自带的gdbserver和ndk自带的host主机(一般都是window、Linux)上的gdb进行网络调试,非常的不方便。
对于这种需求,我们是否可以像Linux-aarch64一样利用交叉编译出android环境的gdb工具,显然是可以的。
二、准备环境
1.官方下载gdb源码:https://sourceware.org/pub/gdb/releases/?C=M;O=D
这里我选择的是gdb-8.0.tar.gz
2.NDK环境准备
这里我下载的是NDK-r18b, 下载地址:Unsupported Downloads · android/ndk Wiki · GitHub
重点说明下: gdb版本和ndk版本最好能匹配上,否则编译过程中遇到各种不同的编译报错问题(猜测是高版本的需要编译器支持)。上面是我通过无数次实验得到的可以编译通过版本。
3.构建android工具链
通过以下命令进行编译生成
export ANDROID_NDK="/opt/android-ndk-r18b"
//32位
sh ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-21 --install-dir=$HOME/android-toolchain_32 --toolchain=arm-linux-androideabi-4.9
//64位
sh ${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh --arch=aarch64 --platform=android-21 --install-dir=$HOME/android-toolchain_64 --toolchain=aarch64-linux-android-4.9
三、编译
1.解压gdb-8.0.tar.gz
tar -xvf gdb-8.0.tar.gz
2.进入gdb-8.0目录,配置编译脚本,如下
//64位,build_android64.sh
./configure --host=aarch64-linux-android --target=aarch64-linux-android CC=aarch64-linux-android-gcc CXX=aarch64-linux-android-g++ --prefix=/home/yw/opensource/gdb-8.0/android64
make -j4
make install
//32位,build_android32.sh
./configure --host=arm-linux-androideabi --target=arm-linux-androideabi CC=arm-linux-androideabi-gcc CXX=arm-linux-androideabi-g++ --prefix=/home/yw/opensource/gdb-8.0/android32
make -j4
make install
以上脚本最后是两个单独的sh脚本,单独编译出来。记得编译前make clean掉上次的缓存。及config.cache清理:
find . -name "config.cache" | xargs rm -f
3.环境变量配置
在用户目录下.bash_profile中添加工具链path:
export PATH=$PATH:/opt/android-ndk-r18b:/home/yw/android-toolchain_64/bin:/home/yw/android-toolchain_32/bin
然后执行source .bash_profile命令激活,或者在当前终端直接执行export都可以。
4.执行编译
sh build_android64.sh
以上为64位编译脚本,32位同理。程序生成在对应指定的目录下。
四、gdb调试使用
通过adb push gdb到android设备上。运行可能需要libc++_shared.so,在将NDK中的库上传到android设备上
现在就开始愉快使用gdb工具啦!
5.编译过程可能遇到的问题及解决方法
1.类型冲突 Elf32_auxv_t Elf64_auxv_t
linux-low.c:116:3: error: typedef redefinition with different types (‘struct Elf32_auxv_t’ vs ‘struct Elf32_auxv_t’)
linux-low.c:131:3: error: typedef redefinition with different types (‘struct Elf64_auxv_t’ vs ‘struct Elf64_auxv_t’)
这个在ndk的elf.h 中已经有定义,直接注释掉gdb/gdbserver/linux-low.c 中的定义
2. setpwent 没定义
complete.c:2060: error: undefined reference to ‘setpwent’
readline/complete.c 中假如宏判断包含
#if defined(HAVE_GETPWENT)
setpwent ();
#endif
运行段错误
手动加打印 发现在signals-state-save-restore.c --> save_original_signals_state 挂掉,
直接注释掉internal_error这行,如下:
参考链接:https://blog.csdn.net/shumanzhou/article/details/119148514