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