From 9b8e4b377208db6d405bc84e9af73bd37f75a93c Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Thu, 30 Oct 2014 22:00:17 -0700 Subject: [PATCH] Replacement for gdbclient Differences between this implementation and the old one: 1. Resolves symbols/gdb based on device information (lunch target is irrelevant) 2. Works with downloaded from build-server symbols 3. Does not require user to specify exe file - detects it automatically Change-Id: I4e7ce0a51868634593a9f104fe3f2fa67b54ca9f --- envsetup.sh | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) diff --git a/envsetup.sh b/envsetup.sh index 18bc97201..8394cf698 100644 --- a/envsetup.sh +++ b/envsetup.sh @@ -963,10 +963,151 @@ function is64bit() fi } +function adb_get_product_device() { + echo `adb shell getprop ro.product.device | sed s/.$//` +} + +# returns 0 when process is not traced +function adb_get_traced_by() { + echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" | sed s/.$//` +} + +function gdbclient() { + # TODO: + # 1. Check for ANDROID_SERIAL/multiple devices + local PROCESS_NAME="n/a" + local PID=$1 + local PORT=5039 + if [ -z "$PID" ]; then + echo "Usage: gdbclient [port number]" + return -1 + fi + local DEVICE=$(adb_get_product_device) + + if [ -z "$DEVICE" ]; then + echo "Error: Unable to get device name. Please check if device is connected and ANDROID_SERIAL is set." + return -2 + fi + + if [ -n "$2" ]; then + PORT=$2 + fi + + local ROOT=$(gettop) + if [ -z "$ROOT" ]; then + # This is for the situation with downloaded symbols (from the build server) + # we check if they are available. + ROOT=`realpath .` + fi + + local OUT_ROOT="$ROOT/out/target/product/$DEVICE" + local SYMBOLS_DIR="$OUT_ROOT/symbols" + + if [ ! -d $SYMBOLS_DIR ]; then + echo "Error: couldn't find symbols: $SYMBOLS_DIR does not exist or is not a directory." + return -3 + fi + + # let's figure out which executable we are about to debug + + # check if user specified a name -> resolve to pid + if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then + PROCESS_NAME=$PID + PID=$(pid --exact $PROCESS_NAME) + if [ -z "$PID" ]; then + echo "Error: couldn't resolve pid by process name: $PROCESS_NAME" + return -4 + fi + fi + + local EXE=`adb shell readlink /proc/$PID/exe | sed s/.$//` + # TODO: print error in case there is no such pid + local LOCAL_EXE_PATH=$SYMBOLS_DIR$EXE + + if [ ! -f $LOCAL_EXE_PATH ]; then + echo "Error: unable to find symbols for executable $EXE: file $LOCAL_EXE_PATH does not exist" + return -5 + fi + + local USE64BIT="" + + if [[ "$(file $LOCAL_EXE_PATH)" =~ 64-bit ]]; then + USE64BIT="64" + fi + + local GDB= + local GDB64= + local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | sed s/.$//` + # TODO: we assume these are available via $PATH + if [[ $CPU_ABI =~ (^|,)arm64 ]]; then + GDB=arm-linux-androideabi-gdb + GDB64=aarch64-linux-android-gdb + elif [[ $CPU_ABI =~ (^|,)arm ]]; then + GDB=arm-linux-androideabi-gdb + elif [[ $CPU_ABI =~ (^|,)x86_64 ]]; then + GDB=x86_64-linux-androideabi-gdb + elif [[ $CPU_ABI =~ (^|,)x86 ]]; then + GDB=x86_64-linux-androideabi-gdb + elif [[ $CPU_ABI =~ (^|,)mips64 ]]; then + GDB=mipsel-linux-android-gdb + GDB64=mips64el-linux-android-gdb + elif [[ $CPU_ABI =~ (^|,)mips ]]; then + GDB=mipsel-linux-android-gdb + else + echo "Error: unrecognized cpu.abilist: $CPU_ABI" + return -6 + fi + + # TODO: check if tracing process is gdbserver and not some random strace... + if [ $(adb_get_traced_by $PID) -eq 0 ]; then + # start gdbserver + echo "Starting gdbserver..." + # TODO: check if adb is already listening $PORT + # to avoid unnecessary calls + echo ". adb forward for port=$PORT..." + adb forward tcp:$PORT tcp:$PORT + echo ". starting gdbserver to attach to pid=$PID..." + adb shell gdbserver$USE64BIT :$PORT --attach $PID & + echo ". give it couple of seconds to start..." + sleep 2 + echo ". done" + else + echo "It looks like gdbserver is already attached to $PID (process is traced), trying to connect to it using local port=$PORT" + fi + + local OUT_SO_SYMBOLS=$SYMBOLS_DIR/system/lib$USE64BIT + local OUT_VENDOR_SO_SYMBOLS=$SYMBOLS_DIR/vendor/lib$USE64BIT + local ART_CMD="" + + echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $SYMBOLS_DIR" + echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines:$OUT_SO_SYMBOLS/drm:$OUT_SO_SYMBOLS/egl:$OUT_SO_SYMBOLS/soundfx:$OUT_VENDOR_SO_SYMBOLS:$OUT_VENDOR_SO_SYMBOLS/hw:$OUT_VENDOR_SO_SYMBOLS/egl" + local DALVIK_GDB_SCRIPT=$ROOT/development/scripts/gdb/dalvik.gdb + if [ -f $DALVIK_GDB_SCRIPT ]; then + echo >>"$OUT_ROOT/gdbclient.cmds" "source $DALVIK_GDB_SCRIPT" + ART_CMD="art-on" + else + echo "Warning: couldn't find $DALVIK_GDB_SCRIPT - ART debugging options will not be available" + fi + echo >>"$OUT_ROOT/gdbclient.cmds" "target remote :$PORT" + if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then + echo >> "$OUT_ROOT/gdbclient.cmds" $ART_CMD + fi + + echo >>"$OUT_ROOT/gdbclient.cmds" "" + + local WHICH_GDB=$GDB + + if [ -n "$USE64BIT" -a -n "$GDB64" ]; then + WHICH_GDB=$GDB64 + fi + + gdbwrapper $WHICH_GDB "$OUT_ROOT/gdbclient.cmds" "$LOCAL_EXE_PATH" +} + # gdbclient now determines whether the user wants to debug a 32-bit or 64-bit # executable, set up the approriate gdbserver, then invokes the proper host # gdb. -function gdbclient() +function gdbclient_old() { local OUT_ROOT=$(get_abs_build_var PRODUCT_OUT) local OUT_SYMBOLS=$(get_abs_build_var TARGET_OUT_UNSTRIPPED)