1#!/bin/bash 2# TODO: 3# 1. Check for ANDROID_SERIAL/multiple devices 4 5if [ -z "$ANDROID_BUILD_TOP" ]; then 6 >&2 echo '$ANDROID_BUILD_TOP is not set. Source build/envsetup.sh.' 7 exit 1 8fi 9 10# We can use environment variables (like ANDROID_BUILD_TOP) from the user's 11# shell, but not functions (like gettop), so we need to source envsetup in here 12# as well. 13source $ANDROID_BUILD_TOP/build/envsetup.sh 14echo 15 16function adb_get_product_device() { 17 local candidate=`adb shell getprop ro.hardware | tr -d '\r\n'` 18 if [[ "$candidate" =~ ^(goldfish|ranchu)$ ]]; then 19 # Emulator builds use product.device for OUT folder 20 candidate=`adb shell getprop ro.product.device | tr -d '\r\n'` 21 fi 22 echo $candidate 23} 24 25# returns 0 when process is not traced 26function adb_get_traced_by() { 27 echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" | tr -d '\r\n'` 28} 29 30function get_symbols_directory() 31{ 32 echo $(get_abs_build_var TARGET_OUT_UNSTRIPPED) 33} 34 35function gdbwrapper() 36{ 37 local GDB_CMD="$1" 38 shift 1 39 $GDB_CMD -x "$@" 40} 41 42function gdbclient() { 43 local PROCESS_NAME="n/a" 44 local PID=$1 45 local PORT=5039 46 if [ -z "$PID" ]; then 47 echo "Usage: gdbclient <pid|processname> [port number]" 48 return -1 49 fi 50 local DEVICE=$(adb_get_product_device) 51 52 if [ -z "$DEVICE" ]; then 53 echo "Error: Unable to get device name. Please check if device is connected and ANDROID_SERIAL is set." 54 return -2 55 fi 56 57 if [ -n "$2" ]; then 58 PORT=$2 59 fi 60 61 local ROOT=$(gettop) 62 if [ -z "$ROOT" ]; then 63 # This is for the situation with downloaded symbols (from the build server) 64 # we check if they are available. 65 ROOT=`realpath .` 66 fi 67 68 local SYS_OUT_ROOT=$(get_build_var OUT_DIR) 69 local OUT_ROOT="${SYS_OUT_ROOT:-${OUT_DIR:-$ROOT/out}}/target/product/$DEVICE" 70 local SYMBOLS_DIR="$OUT_ROOT/symbols" 71 local IS_TAPAS_USER="$(get_build_var TARGET_BUILD_APPS)" 72 local TAPAS_SYMBOLS_DIR= 73 74 if [ $IS_TAPAS_USER ]; then 75 TAPAS_SYMBOLS_DIR=$(get_symbols_directory) 76 fi 77 78 if [ ! -d $SYMBOLS_DIR ]; then 79 if [ $IS_TAPAS_USER ]; then 80 mkdir -p $SYMBOLS_DIR/system/bin 81 else 82 echo "Error: couldn't find symbols: $SYMBOLS_DIR does not exist or is not a directory." 83 return -3 84 fi 85 fi 86 87 # let's figure out which executable we are about to debug 88 89 # check if user specified a name -> resolve to pid 90 if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then 91 PROCESS_NAME=$PID 92 PID=$(pid --exact $PROCESS_NAME) 93 if [ -z "$PID" ]; then 94 echo "Error: couldn't resolve pid by process name: $PROCESS_NAME" 95 return -4 96 else 97 echo "Resolved pid for $PROCESS_NAME is $PID" 98 fi 99 fi 100 101 local ID=`adb shell id -u` 102 if [ "$ID" != "0" ]; then 103 echo "Error: gdbclient only works if you've run 'adb root'" 104 return -4 105 fi 106 107 local EXE=`adb shell readlink /proc/$PID/exe | tr -d '\r\n'` 108 if [ -z "$EXE" ]; then 109 echo "Error: couldn't find executable for pid $PID --- is the process still alive?" 110 return -4 111 fi 112 113 local LOCAL_EXE_PATH=$SYMBOLS_DIR$EXE 114 115 if [ ! -f $LOCAL_EXE_PATH ]; then 116 if [ $IS_TAPAS_USER ]; then 117 adb pull $EXE $LOCAL_EXE_PATH 118 else 119 echo "Error: unable to find symbols for executable $EXE: file $LOCAL_EXE_PATH does not exist" 120 return -5 121 fi 122 fi 123 124 local USE64BIT="" 125 126 if [[ "$(file $LOCAL_EXE_PATH)" =~ 64-bit ]]; then 127 USE64BIT="64" 128 fi 129 130 # and now linker for tapas users... 131 if [ -n "$IS_TAPAS_USER" -a ! -f "$SYMBOLS_DIR/system/bin/linker$USE64BIT" ]; then 132 adb pull /system/bin/linker$USE64BIT $SYMBOLS_DIR/system/bin/linker$USE64BIT 133 fi 134 135 local GDB 136 case $(uname -s) in 137 Darwin) 138 GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/darwin-x86/bin/gdb 139 ;; 140 141 Linux) 142 GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/linux-x86/bin/gdb 143 ;; 144 145 *) 146 echo "Error: Unknown platform '$(uname -s)'" 147 return 1 148 ;; 149 esac 150 151 local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | tr -d '\r\n'` 152 153 # TODO: check if tracing process is gdbserver and not some random strace... 154 if [ "$(adb_get_traced_by $PID)" -eq 0 ]; then 155 # start gdbserver 156 echo "Starting gdbserver..." 157 # TODO: check if adb is already listening $PORT 158 # to avoid unnecessary calls 159 echo ". adb forward for port=$PORT..." 160 adb forward tcp:$PORT tcp:$PORT 161 echo ". starting gdbserver to attach to pid=$PID..." 162 adb shell gdbserver$USE64BIT :$PORT --attach $PID & 163 echo ". give it couple of seconds to start..." 164 sleep 2 165 echo ". done" 166 else 167 echo "It looks like gdbserver is already attached to $PID (process is traced), trying to connect to it using local port=$PORT" 168 adb forward tcp:$PORT tcp:$PORT 169 fi 170 171 local OUT_SO_SYMBOLS=$SYMBOLS_DIR/system/lib$USE64BIT 172 local TAPAS_OUT_SO_SYMBOLS=$TAPAS_SYMBOLS_DIR/system/lib$USE64BIT 173 local OUT_VENDOR_SO_SYMBOLS=$SYMBOLS_DIR/vendor/lib$USE64BIT 174 local ART_CMD="" 175 176 local SOLIB_SYSROOT=$SYMBOLS_DIR 177 local SOLIB_SEARCHPATH=$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 178 179 if [ $IS_TAPAS_USER ]; then 180 SOLIB_SYSROOT=$TAPAS_SYMBOLS_DIR:$SOLIB_SYSROOT 181 SOLIB_SEARCHPATH=$TAPAS_OUT_SO_SYMBOLS:$SOLIB_SEARCHPATH 182 fi 183 184 echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $SOLIB_SYSROOT" 185 echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $SOLIB_SEARCHPATH" 186 local DALVIK_GDB_SCRIPT=$ROOT/development/scripts/gdb/dalvik.gdb 187 if [ -f $DALVIK_GDB_SCRIPT ]; then 188 echo >>"$OUT_ROOT/gdbclient.cmds" "source $DALVIK_GDB_SCRIPT" 189 ART_CMD="art-on" 190 else 191 echo "Warning: couldn't find $DALVIK_GDB_SCRIPT - ART debugging options will not be available" 192 fi 193 echo >>"$OUT_ROOT/gdbclient.cmds" "target remote :$PORT" 194 if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then 195 echo >> "$OUT_ROOT/gdbclient.cmds" $ART_CMD 196 fi 197 198 echo >>"$OUT_ROOT/gdbclient.cmds" "" 199 200 gdbwrapper $GDB "$OUT_ROOT/gdbclient.cmds" "$LOCAL_EXE_PATH" 201} 202 203gdbclient $* 204