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