blob: acbbdda4af5855599ef2da7ecf6f2ccd0aefe08b [file] [log] [blame]
#!/bin/bash
# TODO:
# 1. Check for ANDROID_SERIAL/multiple devices
if [ -z "$ANDROID_BUILD_TOP" ]; then
>&2 echo '$ANDROID_BUILD_TOP is not set. Source build/envsetup.sh.'
exit 1
fi
# We can use environment variables (like ANDROID_BUILD_TOP) from the user's
# shell, but not functions (like gettop), so we need to source envsetup in here
# as well.
source $ANDROID_BUILD_TOP/build/envsetup.sh
echo
function adb_get_product_device() {
local candidate=`adb shell getprop ro.hardware | tr -d '\r\n'`
if [[ "$candidate" =~ ^(goldfish|ranchu)$ ]]; then
# Emulator builds use product.device for OUT folder
candidate=`adb shell getprop ro.product.device | tr -d '\r\n'`
fi
echo $candidate
}
# returns 0 when process is not traced
function adb_get_traced_by() {
echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:[[:blank:]]//" | tr -d '\r\n'`
}
function get_symbols_directory()
{
echo $(get_abs_build_var TARGET_OUT_UNSTRIPPED)
}
function gdbwrapper()
{
local GDB_CMD="$1"
shift 1
$GDB_CMD -x "$@"
}
function gdbclient() {
local PROCESS_NAME="n/a"
local PID=$1
local PORT=5039
if [ -z "$PID" ]; then
echo "Usage: gdbclient <pid|processname> [port number]"
return -1
fi
local DEVICE=$(adb_get_product_device)
if [ -z "$DEVICE" ]; then
echo "Error: Unable to get device name. Please check if device is connected and ANDROID_SERIAL is set."
return -2
fi
if [ -n "$2" ]; then
PORT=$2
fi
local ROOT=$(gettop)
if [ -z "$ROOT" ]; then
# This is for the situation with downloaded symbols (from the build server)
# we check if they are available.
ROOT=`realpath .`
fi
local SYS_OUT_ROOT=$(get_build_var OUT_DIR)
local OUT_ROOT="${SYS_OUT_ROOT:-${OUT_DIR:-$ROOT/out}}/target/product/$DEVICE"
local SYMBOLS_DIR="$OUT_ROOT/symbols"
local IS_TAPAS_USER="$(get_build_var TARGET_BUILD_APPS)"
local TAPAS_SYMBOLS_DIR=
if [ $IS_TAPAS_USER ]; then
TAPAS_SYMBOLS_DIR=$(get_symbols_directory)
fi
if [ ! -d $SYMBOLS_DIR ]; then
if [ $IS_TAPAS_USER ]; then
mkdir -p $SYMBOLS_DIR/system/bin
else
echo "Error: couldn't find symbols: $SYMBOLS_DIR does not exist or is not a directory."
return -3
fi
fi
# let's figure out which executable we are about to debug
# check if user specified a name -> resolve to pid
if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
PROCESS_NAME=$PID
PID=$(pid --exact $PROCESS_NAME)
if [ -z "$PID" ]; then
echo "Error: couldn't resolve pid by process name: $PROCESS_NAME"
return -4
else
echo "Resolved pid for $PROCESS_NAME is $PID"
fi
fi
local ID=`adb shell id -u`
if [ "$ID" != "0" ]; then
echo "Error: gdbclient only works if you've run 'adb root'"
return -4
fi
local EXE=`adb shell readlink /proc/$PID/exe | tr -d '\r\n'`
if [ -z "$EXE" ]; then
echo "Error: couldn't find executable for pid $PID --- is the process still alive?"
return -4
fi
local LOCAL_EXE_PATH=$SYMBOLS_DIR$EXE
if [ ! -f $LOCAL_EXE_PATH ]; then
if [ $IS_TAPAS_USER ]; then
adb pull $EXE $LOCAL_EXE_PATH
else
echo "Error: unable to find symbols for executable $EXE: file $LOCAL_EXE_PATH does not exist"
return -5
fi
fi
local USE64BIT=""
if [[ "$(file $LOCAL_EXE_PATH)" =~ 64-bit ]]; then
USE64BIT="64"
fi
# and now linker for tapas users...
if [ -n "$IS_TAPAS_USER" -a ! -f "$SYMBOLS_DIR/system/bin/linker$USE64BIT" ]; then
adb pull /system/bin/linker$USE64BIT $SYMBOLS_DIR/system/bin/linker$USE64BIT
fi
local GDB
case $(uname -s) in
Darwin)
GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/darwin-x86/bin/gdb
;;
Linux)
GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/linux-x86/bin/gdb
;;
*)
echo "Error: Unknown platform '$(uname -s)'"
return 1
;;
esac
local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | tr -d '\r\n'`
# TODO: check if tracing process is gdbserver and not some random strace...
if [ "$(adb_get_traced_by $PID)" -eq 0 ]; then
# start gdbserver
echo "Starting gdbserver..."
# TODO: check if adb is already listening $PORT
# to avoid unnecessary calls
echo ". adb forward for port=$PORT..."
adb forward tcp:$PORT tcp:$PORT
echo ". starting gdbserver to attach to pid=$PID..."
adb shell gdbserver$USE64BIT :$PORT --attach $PID &
echo ". give it couple of seconds to start..."
sleep 2
echo ". done"
else
echo "It looks like gdbserver is already attached to $PID (process is traced), trying to connect to it using local port=$PORT"
adb forward tcp:$PORT tcp:$PORT
fi
local OUT_SO_SYMBOLS=$SYMBOLS_DIR/system/lib$USE64BIT
local TAPAS_OUT_SO_SYMBOLS=$TAPAS_SYMBOLS_DIR/system/lib$USE64BIT
local OUT_VENDOR_SO_SYMBOLS=$SYMBOLS_DIR/vendor/lib$USE64BIT
local ART_CMD=""
local SOLIB_SYSROOT=$SYMBOLS_DIR
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
if [ $IS_TAPAS_USER ]; then
SOLIB_SYSROOT=$TAPAS_SYMBOLS_DIR:$SOLIB_SYSROOT
SOLIB_SEARCHPATH=$TAPAS_OUT_SO_SYMBOLS:$SOLIB_SEARCHPATH
fi
echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $SOLIB_SYSROOT"
echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $SOLIB_SEARCHPATH"
local DALVIK_GDB_SCRIPT=$ROOT/development/scripts/gdb/dalvik.gdb
if [ -f $DALVIK_GDB_SCRIPT ]; then
echo >>"$OUT_ROOT/gdbclient.cmds" "source $DALVIK_GDB_SCRIPT"
ART_CMD="art-on"
else
echo "Warning: couldn't find $DALVIK_GDB_SCRIPT - ART debugging options will not be available"
fi
echo >>"$OUT_ROOT/gdbclient.cmds" "target remote :$PORT"
if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then
echo >> "$OUT_ROOT/gdbclient.cmds" $ART_CMD
fi
echo >>"$OUT_ROOT/gdbclient.cmds" ""
gdbwrapper $GDB "$OUT_ROOT/gdbclient.cmds" "$LOCAL_EXE_PATH"
}
gdbclient $*