1#!/bin/bash
2
3echo "WARNING: gdbclient is deprecated in favor of gdbclient.py" >&2
4
5# TODO:
6# 1. Check for ANDROID_SERIAL/multiple devices
7
8if [ -z "$ANDROID_BUILD_TOP" ]; then
9  >&2 echo '$ANDROID_BUILD_TOP is not set. Source build/envsetup.sh.'
10  exit 1
11fi
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.
16source $ANDROID_BUILD_TOP/build/envsetup.sh
17echo
18
19function 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
29function 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
33function get_symbols_directory()
34{
35    echo $(get_abs_build_var TARGET_OUT_UNSTRIPPED)
36}
37
38function gdbwrapper()
39{
40    local GDB_CMD="$1"
41    shift 1
42    $GDB_CMD -x "$@"
43}
44
45function 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
206gdbclient $*
207