使用GDB進行Android Native調試

使用腳本工具快速進行Android Native調試。

安裝android_gdbserver_attach腳本

使用GDB遠程調試指定Android進程的時候,經常要查詢pid,然後再attach。爲了簡化步驟,就寫了個腳本。
file name: android_gdbserver_attach

#!/usr/bin/env bash
gdbServerPid=`adb shell ps | grep gdbserver | awk '{print $2}'`

if [[ "" != ${gdbServerPid} ]]; then
    adb shell su -c "kill ${gdbServerPid}"
fi

adb forward tcp:1234 tcp:1234

if [[ `adb shell whoami` == 'root'  ]]; then
    is_root=true
fi

if [[ -n $1 ]]; then
    OLDIFS=$IFS
    IFS='
'
	grepPsResult=(`adb shell ps | grep $1 | awk '{print $1"\t"$2"\t"$9}'`)
    IFS=$OLDIFS
    NUMPIDS=${#grepPsResult[@]}
    declare -a appPid
    for (( x=0; x < $NUMPIDS; x++ )); do
	    appPid[x]=`echo ${grepPsResult[x]} | awk '{print $2}'`
    done
    selectedPid=0
    if [[ 0 -eq "$NUMPIDS" ]]; then
	    echo "No this process name - nothing to do."
	    exit 0;
    elif [[ 1 -eq "$NUMPIDS" ]]; then
	    # Just one process
        selectedPid=${appPid[0]}
    else
        # Select one process
        echo "Multiple processes detected, please select one"
        for (( x=0; x < $NUMPIDS; x++ )); do
            echo -e "$[x+1]: ${grepPsResult[x]}"
        done
        echo -n "> "
        read USER_CHOICE

        # Validate user entered a number
        if [[ $USER_CHOICE =~ ^[0-9]+$ ]]; then
            echo "Selected Process : ${grepPsResult[$USER_CHOICE-1]}"
            selectedPid=${appPid[$USER_CHOICE-1]}
        else
            echo "You must enter a number"
            exit 0;
        fi
    fi
    adb forward tcp:12345 jdwp:${selectedPid}

	if [[ $is_root == true  ]]; then
        adb shell gdbserver :1234 --attach ${selectedPid}
    else
        adb shell su -c "gdbserver :1234 --attach ${selectedPid} "
    fi
else
	echo "Please input the name of the process to be debugged (app's process name is the package name)。Example: $0 <process name>"
fi

GDB調試正在運行的App進程

  1. 使用腳本attach到指定的進程
    腳本後面輸入進程名,如果發現多個匹配,就會出現選擇列表,輸入數字選擇即可
    $ android_gdbserver_attach gms
    Multiple processes detected, please select one
    1: u0_a40	1584	com.google.android.gms.persistent
    2: u0_a40	2039	com.google.android.gms
    3: u0_a40	3244	com.google.android.gms.unstable
    4: u0_a40	25548	com.google.android.gms.ui
    > 2
    Selected Process : u0_a40	2039	com.google.android.gms
    Attached; pid = 2039
    Listening on port 1234
    
  2. 使用gdb或者clion remote gdb 連接本地端口1234即可

GDB在App啓動階段進行調試

  1. 以等待調試的方式啓動App

    adb shell am force-stop <包名> && adb shell am start -n
    “<包名>/<啓動的Activity名>” -a android.intent.action.MAIN -c
    android.intent.category.LAUNCHER -D

    例如

    $ adb shell am force-stop com.kevin.jni.jniworld && adb shell am start -n "com.kevin.jni.jniworld/com.kevin.jni.jniworld.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
    

    出現如下圖對話框
    在這裏插入圖片描述

  2. 使用android_gdbserver_attach腳本attach到改進程

    $ android_gdbserver_attach com.kevin.jni.jniworld                                                                                                                                                                             
    Attached; pid = 7578
    Listening on port 1234
    
  3. 使用gdb或者CLion remote gdb 連接本地端口1234即可
    這裏以CLion GDB Remote 配置截圖
    在這裏插入圖片描述
    連接成功如下圖所示
    在這裏插入圖片描述

  4. 通過jdb attach進程
    爲了讓App繼續運行,結束Waiting。需要通過jdb attach 該進程。jdwp端口轉發已經在腳本中執行了(第50行)。所以這裏直接attach即可

    $ jdb -attach localhost:12345
    Set uncaught java.lang.Throwable
    Set deferred uncaught java.lang.Throwable
    Initializing jdb ...
    > 
    
  5. 程序就會在斷點處停下來,現在就可以開始愉快的調試了
    在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章