自己动手写ndk-gdb

来源:互联网 发布:艾薇儿已经去世 知乎 编辑:程序博客网 时间:2024/06/05 00:09

做NDK开发,经常会用到ndk-gdb,但ndk-gdb的启动规则比较严格,甚至需要检查工程文件,在一些手机上往往无法启动;所以,研究了一下ndk-gdb的代码,实现了一个简单的版本,基本的原理如下:

1. 首先进入android工程目录,该目录下包含了jni, obj, bin工程相关的子目录;


2. 使用awk找到package进程对应的PID(具体实现参考后面的代码)

    如果PID为0, 说明程序没有运行,需要强制启动

     adb shell am start -n $package/$ActivityName

     如:adb shell am start -n  com.xxx.yyy/com.xxx.main.xxxx

     其中,ActivityName 可以在android的工程配置文件 AndroidManefest.xml中找到;

     强制启动后,再通过awk找到$package进程对应的PID;


3.  通过run-as命令在非root权限下,启动package中的gdbserver, 并且attach到$PID进程。

      adb shell run-as $packagelib/gdbserver +debug-socket --attach $PID


4. 端口映射, 将本地端口5039映射到Android上的域套接字对应的端口

    adb forward tcp:5039 localfilesystem:/data/data/$package/debug-socket


5. Pull调试相关的filesobj/local/armeabi目录

    包括:/system/bin/app_process,/system/bin/linker, /system/lib/libc.so


6. 将GDB启动后需要进行的操作添加到obj/local/armeabi/gdb.setup文件

    其中gdb.setup是在编译阶段生成的(android-ndk-r8d/build/core/setup-toolchain.mk)gdb.setup默认有两个命令:

    set solib-search-path./obj/local/armeabi

    directory src-dir1src-dir2 ... src-dirN

    需要自己添加的操作包括:

    file./obj/local/armeabi/app_process

    target remove :5039

    set print object on

    可以根据需要,再添加其他命令,比如启动的是gdbtui,可以添加:

    winheight src 25

    focus cmd


7. 以gdb.setup为配置文件启动gdb

    arm-linux-androideabi-gdb/gdbtui-x ./obj/local/armeabi/gdb.setup

以下是一个例子,其中Activity可以在工程配置文件AndroidManifest.xml文件中找到,改成对应的名字即可:

#!/bin/sh #Author: Kyle(justbitguy@gmail.com)#Date:2013-10-12VERSION="4.0"pid_for_package (){   pack_name=$1   _pid=`adb shell ps | awk -v PACKAGE="$pack_name" '   BEGIN {       FS=" "          if (PACKAGE == "") {           PACKAGE="com.google.android.apps.maps"       }          PID=0       PID_COLUMN=2    }    {       gsub("\r","",$NF)       if (NR == 1) {           for (n = 1; n <= NF; n++) {               if ($n == "PID") {                   PID_COLUMN=n;               }           }       } else {       if ($NF == PACKAGE) {           PID=$PID_COLUMN           }       }    }   END {       print PID    }   '`    echo $_pid}#start of this script###########################################USAGE="usage: `basename $0` package"if [ $# -lt 1 ]; then   echo $USAGE    exitfipackage=$1if [ -z $package ]; then    echo $USAGE   exit 13   fi ARM_TYPE=armeabi APP_OUT=./obj/local/$ARM_TYPEAPP_PROCESS=$APP_OUT/app_processDEBUGGER=`basename $0`DEBUGGER_PATH=`which $DEBUGGER`DEBUGGER_DIR=`dirname $DEBUGGER_PATH`echo "debugger dir is $DEBUGGER_DIR"GDBSERVER_PID=`pid_for_package lib/gdbserver`echo "gdbserver pid is $GDBSERVER_PID"if [ "$GDBSERVER_PID" != "0" ]; then     adb shell kill -9 $GDBSERVER_PIDfiPID=`pid_for_package $package`if [ "$PID" -eq "0" ]; then## COMMAND: adb_cmd shell am start -n $package/$Activity#Starting: Intent { cmp=$package/$Activity}## COMMAND: adb_cmd shell sleep 2    adb shell am start -n $package/$Activity    adb shell sleep 5    PID=`pid_for_package $package`fi echo "$packge pid is $PID"adb forward tcp:5039 localfilesystem:/data/data/$package/debug-socketecho adb shell run-as $package lib/gdbserver +debug-socket --attach $PIDadb shell run-as $package lib/gdbserver +debug-socket --attach $PID > ~/.gdb.log &#pull files from devices#####################################adb pull /system/bin/app_process $APP_OUT/app_processecho "Pulled app_process from device/emulator."adb pull /system/bin/linker $APP_OUT/linkerecho "Pulled linker form device/emulator."adb pull /system/lib/libc.so $APP_OUT/libc.soecho "Pulled libc.so from device/emulator."#start gdb clientGDB_PREFIX=arm-linux-androideabi-GDBCMD=${GDB_PREFIX}gdbGDBSETUP=$APP_OUT/gdb.setupcp -f ./libs/$ARM_TYPE/gdb.setup $GDBSETUP -vecho "file $APP_PROCESS" >> $GDBSETUPecho "target remote :5039" >> $GDBSETUPecho "set print object on" >> $GDBSETUPGDBCLIENT=$GDBCMD   $GDBCLIENT -x $GDBSETUP






原创粉丝点击