• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
14
15function 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
24function 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
28function get_symbols_directory()
29{
30    echo $(get_abs_build_var TARGET_OUT_UNSTRIPPED)
31}
32
33function gdbwrapper()
34{
35    local GDB_CMD="$1"
36    shift 1
37    $GDB_CMD -x "$@"
38}
39
40function 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
211gdbclient $*
212