From 909b785d07fbe2ad4ad793ab1749e81b3cccba69 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 5 Sep 2015 23:54:42 -0700 Subject: [PATCH] vanilla ndk-gdb from android-ndk-r10e --- Android/toolchain_edits/ndk-gdb | 855 ++++++++++++++++++++++++++++++++ 1 file changed, 855 insertions(+) create mode 100755 Android/toolchain_edits/ndk-gdb diff --git a/Android/toolchain_edits/ndk-gdb b/Android/toolchain_edits/ndk-gdb new file mode 100755 index 00000000..ba95931f --- /dev/null +++ b/Android/toolchain_edits/ndk-gdb @@ -0,0 +1,855 @@ +#!/bin/sh +# +# Copyright (C) 2010 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This wrapper script is used to launch a native debugging session +# on a given NDK application. The application must be debuggable, i.e. +# its android:debuggable attribute must be set to 'true' in the +# element of its manifest. +# +# See docs/NDK-GDB.TXT for usage description. Essentially, you just +# need to launch ndk-gdb from your application project directory +# after doing ndk-build && ant install && +# +PROGDIR=`dirname $0` +PROGDIR=`cd $PROGDIR && pwd -P` + +# Check if absolute NDK path contain space +# +case $PROGDIR in + *\ *) echo "ERROR: NDK path cannot contain space" + exit 1 + ;; +esac + +NDK_BUILDTOOLS_PATH=$PROGDIR/build/tools +. $PROGDIR/build/tools/prebuilt-common.sh +. $PROGDIR/build/tools/ndk-common.sh + +force_32bit_binaries + +# Find if a given shell program is available. +# We need to take care of the fact that the 'which ' command +# may return either an empty string (Linux) or something like +# "no in ..." (Darwin). Also, we need to redirect stderr +# to /dev/null for Cygwin +# +# $1: program name +# Out: program path, or empty string +# Return: 0 on success, != 0 on error +# +find_program () +{ + local PROG RET + PROG=$(which "$1" 2>/dev/null) + RET=$? + if [ $RET != 0 ]; then + PROG= + fi + echo "$PROG" + return $RET +} + +quote_spaces () +{ + echo "$@" | sed -e 's! !\ !g' +} + +# If ADB_CMD is not defined, try to find a program named 'adb' +# in our path. +ADB_CMD=${ADB_CMD:-$(find_program adb)} +ADB_FLAGS=${ADB_FLAGS:-} +DEVICE_SERIAL= + +JDB_CMD=${JDB_CMD:-$(find_program jdb)} + +AWK_CMD=${AWK_CMD:-$(find_program awk)} + +DEBUG_PORT=5039 +JDB_PORT=65534 + +UNKNOWN_ABI=$(find_ndk_unknown_archs) + +# Delay in seconds between launching the activity and attaching gdbserver on it. +# This is needed because there is no way to know when the activity has really +# started, and sometimes this takes a few seconds. +DELAY=2 + +PARAMETERS= +OPTION_HELP=no +OPTION_PROJECT= +OPTION_FORCE=no +OPTION_ADB= +OPTION_EXEC= +OPTION_START=no +OPTION_LAUNCH= +OPTION_LAUNCH_LIST=no +OPTION_DELAY= +OPTION_WAIT="-D" +OPTION_PACKAGE_NAME= + +check_parameter () +{ + if [ -z "$2" ]; then + echo "ERROR: Missing parameter after option '$1'" + exit 1 + fi +} + +check_adb_flags () +{ + if [ -n "$ADB_FLAGS" ] ; then + echo "ERROR: Only one of -e, -d or -s can be used at the same time!" + exit 1 + fi +} + +get_build_var () +{ + if [ -z "$GNUMAKE" ] ; then + GNUMAKE=make + fi + $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1 | tail -1 +} + +get_build_var_for_abi () +{ + if [ -z "$GNUMAKE" ] ; then + GNUMAKE=make + fi + $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1 APP_ABI=$2 | tail -1 +} + +# Used to run an awk script on the manifest +run_awk_manifest_script () +{ + $AWK_CMD -f $AWK_SCRIPTS/$1 $PROJECT/$MANIFEST +} + +if [ "$HOST_OS" = "cygwin" ] ; then +# Return native path representation from cygwin one +# $1: a cygwin-compatible path (e.g. /cygdrive/c/some/thing) +# Return: path in host windows representation, e.g. C:/some/thing +# +# We use mixed mode (i.e. / as the directory separator) because +# all the tools we use recognize it properly, and it avoids lots +# of escaping nonsense associated with "\" +# +native_path () +{ + cygpath -m $1 +} +else # HOST_OS != windows +native_path () +{ + echo "$1" +} +fi # HOST_OS != windows + +# We need to ensure the ANDROID_NDK_ROOT is absolute, otherwise calls +# to get_build_var, get_build_var_for_abi and run_awk_manifest_script +# might fail, e.g. when invoked with: +# +# cd $NDKROOT +# ./ndk-gdb --project=/path/to/project +# +path_is_absolute () +{ + local P P2 + P=$1 # copy path + P2=${P#/} # remove / prefix, if any + [ "$P" != "$P2" ] +} + +if ! path_is_absolute "$ANDROID_NDK_ROOT"; then + ANDROID_NDK_ROOT=$(pwd)/$ANDROID_NDK_ROOT +fi + + +VERBOSE=no +while [ -n "$1" ]; do + opt="$1" + optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` + case "$opt" in + --help|-h|-\?) + OPTION_HELP=yes + ;; + --verbose) + VERBOSE=yes + ;; + -s) + check_parameter $1 $2 + check_adb_flags + ADB_FLAGS=" -s" + DEVICE_SERIAL=$2 + shift + ;; + -s*) + check_adb_flags + optarg=`expr -- "$opt" : '-s\(.*\)'` + ADB_FLAGS=" -s" + DEVICE_SERIAL=$optarg + ;; + -p) + check_parameter $1 $2 + OPTION_PROJECT="$2" + shift + ;; + -p*) + optarg=`expr -- "$opt" : '-p\(.*\)'` + OPTION_PROJECT="$optarg" + ;; + --exec=*) + OPTION_EXEC="$optarg" + ;; + -x) + check_parameter $1 $2 + OPTION_EXEC="$2" + shift + ;; + -x*) + optarg=`expr -- "$opt" : '-x\(.*\)'` + OPTION_EXEC="$optarg" + ;; + -e) + check_adb_flags + ADB_FLAGS=" -e" + ;; + -d) + check_adb_flags + ADB_FLAGS=" -d" + ;; + --adb=*) # specify ADB command + OPTION_ADB="$optarg" + ;; + --awk=*) + AWK_CMD="$optarg" + ;; + --project=*) + OPTION_PROJECT="$optarg" + ;; + --port=*) + DEBUG_PORT="$optarg" + ;; + --force) + OPTION_FORCE="yes" + ;; + --launch-list) + OPTION_LAUNCH_LIST="yes" + ;; + --launch=*) + OPTION_LAUNCH="$optarg" + ;; + --start) + OPTION_START=yes + ;; + --delay=*) + OPTION_DELAY="$optarg" + ;; + --nowait) + JDB_PORT= + OPTION_WAIT= + ;; + --package=*) + OPTION_PACKAGE_NAME="$optarg" + ;; + -*) # unknown options + echo "ERROR: Unknown option '$opt', use --help for list of valid ones." + exit 1 + ;; + *) # Simply record parameter + if [ -z "$PARAMETERS" ] ; then + PARAMETERS="$opt" + else + PARAMETERS="$PARAMETERS $opt" + fi + ;; + esac + shift +done + +if [ -z "$JDB_CMD" ] && [ -n "$OPTION_WAIT" ]; then + echo "ERROR: 'jdb' not found; you must either install the JDK, or specify --nowait" + exit 1 +fi +if [ -n "$JDB_PORT" ] && [ "$JDB_PORT" = "$DEBUG_PORT" ]; then + echo "ERROR: --port specified cannot be $JDB_PORT without --nowait" + exit 1 +fi + +if [ "$OPTION_HELP" = "yes" ] ; then + echo "Usage: $PROGNAME [options]" + echo "" + echo "Setup a gdb debugging session for your Android NDK application." + echo "Read $$NDK/docs/NDK-GDB.TXT for complete usage instructions." + echo "" + echo "Valid options:" + echo "" + echo " --help|-h|-? Print this help" + echo " --verbose Enable verbose mode" + echo " --force Kill existing debug session if it exists" + echo " --nowait Don't have application wait for debugger to attach" + echo " (This might cause you to miss some early JNI breakpoints)" + echo " --start Launch application instead of attaching to existing one" + echo " --launch= Same as --start, but specify activity name (see below)" + echo " --launch-list List all launchable activity names from manifest" + echo " --delay= Delay in seconds between activity start and gdbserver attach." + echo " --project= Specify application project path" + echo " -p Same as --project=" + echo " --package= Specify package name" + echo " --port= Use tcp:localhost: to communicate with gdbserver [$DEBUG_PORT]" + echo " --exec= Execute gdb initialization commands in after connection" + echo " -x Same as --exec=" + echo " --adb= Use specific adb command [$ADB_CMD]" + echo " --awk= Use specific awk command [$AWK_CMD]" + echo " -e Connect to single emulator instance" + echo " -d Connect to single target device" + echo " -s Connect to specific emulator or device" + echo "" + exit 0 +fi + +log "Android NDK installation path: $ANDROID_NDK_ROOT" + +if [ -n "$OPTION_EXEC" ] ; then + if [ ! -f "$OPTION_EXEC" ]; then + echo "ERROR: Invalid initialization file: $OPTION_EXEC" + exit 1 + fi +fi + +if [ -n "$OPTION_DELAY" ] ; then + DELAY="$OPTION_DELAY" +fi + +# Check ADB tool version +if [ -n "$OPTION_ADB" ] ; then + ADB_CMD=$OPTION_ADB + log "Using specific adb command: $ADB_CMD" +else + if [ -z "$ADB_CMD" ] ; then + echo "ERROR: The 'adb' tool is not in your path." + echo " You can change your PATH variable, or use" + echo " --adb= to point to a valid one." + exit 1 + fi + log "Using default adb command: $ADB_CMD" +fi + +ADB_CMD=$(quote_spaces $ADB_CMD) +ADB_VERSION=$("$ADB_CMD" version 2>/dev/null) +if [ $? != 0 ] ; then + echo "ERROR: Could not run ADB with: $ADB_CMD" + exit 1 +fi +log "ADB version found: $ADB_VERSION" + +if [ "x$DEVICE_SERIAL" = "x" ]; then + log "Using ADB flags: $ADB_FLAGS" +else + log "Using ADB flags: $ADB_FLAGS" \"$DEVICE_SERIAL\" +fi + +JDB_CMD=$(quote_spaces $JDB_CMD) +log "Using JDB command: $JDB_CMD" + +# Run an ADB command with the right ADB flags +# $1+: adb command parameter +adb_cmd () +{ + if [ "x$DEVICE_SERIAL" = "x" ]; then + "$ADB_CMD" $ADB_FLAGS "$@" + else + # NOTE: We escape $ADB_CMD and $DEVICE_SERIAL in case they contains spaces. + "$ADB_CMD" $ADB_FLAGS "$DEVICE_SERIAL" "$@" + fi +} + +# Used internally by adb_var_shell and adb_var_shell2. +# $1: 1 to redirect stderr to $1, 0 otherwise. +# $2: Variable name that will contain the result +# $3+: Command options +_adb_var_shell () +{ + # We need a temporary file to store the output of our command + local CMD_OUT RET OUTPUT VARNAME REDIRECT_STDERR + REDIRECT_STDERR=$1 + VARNAME=$2 + shift; shift; + CMD_OUT=`mktemp /tmp/ndk-gdb-cmdout-XXXXXX` + # Run the command, while storing the standard output to CMD_OUT + # and appending the exit code as the last line. + if [ "$REDIRECT_STDERR" != 0 ]; then + adb_cmd shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1 + else + adb_cmd shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT + fi + # Get last line in log, which contains the exit code from the command + RET=`sed -e '$!d' $CMD_OUT` + # Get output, which corresponds to everything except the last line + OUT=`sed -e '$d' $CMD_OUT` + rm -f $CMD_OUT + eval $VARNAME=\"\$OUT\" + return $RET +} + +# Run a command through 'adb shell' and captures its standard output +# into a variable. The function's exit code is the same than the command's. +# +# This is required because there is a bug where "adb shell" always returns +# 0 on the host, even if the command fails on the device. +# +# $1: Variable name (e.g. FOO) +# On exit, $FOO is set to the command's standard output +# +# The return status will be 0 (success) if the command succeeded +# or 1 (failure) otherwise. +adb_var_shell () +{ + _adb_var_shell 0 "$@" +} + +# A variant of adb_var_shell that stores both stdout and stderr in the output +# $1: Variable name +adb_var_shell2 () +{ + _adb_var_shell 1 "$@" +} + +# Return the PID of a given package or program, or 0 if it doesn't run +# $1: Package name ("com.example.hellojni") or program name ("/lib/gdbserver") +# Out: PID number, or 0 if not running +get_pid_of () +{ + adb_cmd shell ps | $AWK_CMD -f $AWK_SCRIPTS/extract-pid.awk -v PACKAGE="$1" +} + +# Check the awk tool +AWK_SCRIPTS=$ANDROID_NDK_ROOT/build/awk +AWK_TEST=`$AWK_CMD -f $AWK_SCRIPTS/check-awk.awk` +if [ $? != 0 ] ; then + echo "ERROR: Could not run '$AWK_CMD' command. Do you have it installed properly?" + exit 1 +fi +if [ "$AWK_TEST" != "Pass" ] ; then + echo "ERROR: Your version of 'awk' is obsolete. Please use --awk= to point to Nawk or Gawk!" + exit 1 +fi + +# Name of the manifest file +MANIFEST=AndroidManifest.xml + +# Find the root of the application project. +if [ -n "$OPTION_PROJECT" ] ; then + PROJECT=$OPTION_PROJECT + log "Using specified project path: $PROJECT" + if [ ! -d "$PROJECT" ] ; then + echo "ERROR: Your --project option does not point to a directory!" + exit 1 + fi + if [ ! -f "$PROJECT/$MANIFEST" ] ; then + echo "ERROR: Your --project does not point to an Android project path!" + echo " It is missing a $MANIFEST file." + exit 1 + fi +else + # Assume we are in the project directory + if [ -f "$MANIFEST" ] ; then + PROJECT=. + else + PROJECT= + CURDIR=`pwd` + while [ "$CURDIR" != "/" ] ; do + if [ -f "$CURDIR/$MANIFEST" ] ; then + PROJECT="$CURDIR" + break + fi + CURDIR=`dirname $CURDIR` + done + if [ -z "$PROJECT" ] ; then + echo "ERROR: Launch this script from an application project directory, or use --project=." + exit 1 + fi + fi + log "Using auto-detected project path: $PROJECT" +fi + +if [ ! -z "$OPTION_PACKAGE_NAME" ]; then + PACKAGE_NAME="$OPTION_PACKAGE_NAME" + log "Using package name: $PACKAGE_NAME" +else + # Extract the package name from the manifest + PACKAGE_NAME=`run_awk_manifest_script extract-package-name.awk` + if [ $? != 0 -o "$PACKAGE_NAME" = "" ] ; then + echo "ERROR: Could not extract package name from $PROJECT/$MANIFEST." + echo " Please check that the file is well-formed!" + exit 1 + fi + log "Found package name: $PACKAGE_NAME" +fi + +# If --launch-list is used, list all launchable activities, and be done with it +if [ "$OPTION_LAUNCH_LIST" = "yes" ] ; then + log "Extracting list of launchable activities from manifest:" + run_awk_manifest_script extract-launchable.awk + exit 0 +fi + +APP_ABIS=`get_build_var APP_ABI` +if [ "$APP_ABIS" != "${APP_ABIS%%all*}" ] ; then +# replace first "all" with all available ABIs + ALL_ABIS=`get_build_var NDK_ALL_ABIS` + APP_ABIS_FRONT="${APP_ABIS%%all*}" + APP_ABIS_BACK="${APP_ABIS#*all}" + APP_ABIS="${APP_ABIS_FRONT}${ALL_ABIS}${APP_ABIS_BACK}" +fi +# replace "armeabi-v7a-hard" with "armeabi-v7a" +APP_ABIS=`echo $APP_ABIS | sed -e 's/armeabi-v7a-hard/armeabi-v7a/g'` +log "ABIs targetted by application: $APP_ABIS" + +# Check the ADB command, and that we can connect to the device/emulator +ADB_TEST=`adb_cmd shell ls` +if [ $? != 0 ] ; then + echo "ERROR: Could not connect to device or emulator!" + echo " Please check that an emulator is running or a device is connected" + echo " through USB to this machine. You can use -e, -d and -s " + echo " in case of multiple ones." + exit 1 +fi + +# Check that the device is running Froyo (API Level 8) or higher +# +adb_var_shell API_LEVEL getprop ro.build.version.sdk +if [ $? != 0 -o -z "$API_LEVEL" ] ; then + echo "ERROR: Could not find target device's supported API level!" + echo "ndk-gdb will only work if your device is running Android 2.2 or higher." + exit 1 +fi +log "Device API Level: $API_LEVEL" +if [ "$API_LEVEL" -lt "8" ] ; then + echo "ERROR: ndk-gdb requires a target device running Android 2.2 (API level 8) or higher." + echo "The target device is running API level $API_LEVEL!" + exit 1 +fi + +# Get the target device's supported ABI(s) +# And check that they are supported by the application +# +COMPAT_ABI=none + +# All modern Android images must support ro.product.cpu.abilist32 +# and ro.product.cpu.abilist64. Otherwise fall back to obsolete +# ro.product.cpu.abi and ro.product.cpu.abi2 +adb_var_shell CPU_ABILIST64 getprop ro.product.cpu.abilist64 +adb_var_shell CPU_ABILIST32 getprop ro.product.cpu.abilist32 +CPU_ABIS="$CPU_ABILIST64,$CPU_ABILIST32" +if [ -z "$CPU_ABILIST64" ] && [ -z "$CPU_ABILIST32" ] ; then + adb_var_shell CPU_ABI1 getprop ro.product.cpu.abi + adb_var_shell CPU_ABI2 getprop ro.product.cpu.abi2 + CPU_ABIS="$CPU_ABI1,$CPU_ABI2" +fi + +# Replace all ',' with space and add trailing space to +# ease whole-word matching of APP_ABI +CPU_ABILIST64=$(echo $CPU_ABILIST64 | tr ',' ' ') +CPU_ABILIST32=$(echo $CPU_ABILIST32 | tr ',' ' ') +CPU_ABIS=$(echo $CPU_ABIS | tr ',' ' ') +log "Device CPU ABIs: $CPU_ABIS" + +APP_ABIS=$APP_ABIS" " + +adb_var_shell BCFILES run-as $PACKAGE_NAME /system/bin/sh -c "ls lib/*.bc" +if [ $? = 0 ]; then + COMPAT_ABI="$UNKNOWN_ABI" +else + # Assume that compatible ABI is 32-bit + COMPAT_ABI_BITS=32 + # First look compatible ABI in the list of 64-bit ABIs + if [ -n "$CPU_ABILIST64" ] ; then + for CPU_ABI64 in $CPU_ABILIST64; do + if [ "$APP_ABIS" != "${APP_ABIS%$CPU_ABI64 *}" ] ; then + COMPAT_ABI=$CPU_ABI64 + COMPAT_ABI_BITS=64 + break + fi + done + fi + # If we found nothing - look among 32-bit ABIs + if [ "$COMPAT_ABI" = none ] && [ -n "$CPU_ABILIST32" ] ; then + for CPU_ABI32 in $CPU_ABILIST32; do + if [ "$APP_ABIS" != "${APP_ABIS%$CPU_ABI32 *}" ] ; then + COMPAT_ABI=$CPU_ABI32 + break + fi + done + fi + # Lastly, lets check ro.product.cpu.abi and ro.product.cpu.abi2 + if [ "$COMPAT_ABI" = none ] && [ -z "$CPU_ABILIST64" ] && [ -z "$CPU_ABILIST32" ]; then + for CPU_ABI in $CPU_ABIS; do + if [ "$APP_ABIS" != "${APP_ABIS%$CPU_ABI *}" ] ; then + COMPAT_ABI=$CPU_ABI + break + fi + done + fi +fi + +if [ "$COMPAT_ABI" = none ] ; then + echo "ERROR: The device does not support the application's targetted CPU ABIs!" + echo " Device supports: $CPU_ABIS" + echo " Package supports: $APP_ABIS" + exit 1 +fi +log "Compatible device ABI: $COMPAT_ABI" + +# Get information from the build system +GDBSETUP_INIT=`get_build_var_for_abi NDK_APP_GDBSETUP $COMPAT_ABI` +log "Using gdb setup init: $GDBSETUP_INIT" + +# Find the prefix for gdb-client +if [ "$COMPAT_ABI" != "$UNKNOWN_ABI" ]; then + TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $COMPAT_ABI` +else + TOOLCHAIN_ABI=$(echo $CPU_ABIS | awk '{print $NF}') + TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $TOOLCHAIN_ABI` +fi +log "Using toolchain prefix: $TOOLCHAIN_PREFIX" + +APP_OUT=`get_build_var_for_abi TARGET_OUT $COMPAT_ABI` +log "Using app out directory: $APP_OUT" + +# Check that the application is debuggable, or nothing will work +DEBUGGABLE=`run_awk_manifest_script extract-debuggable.awk` +RET=$? +log "Found debuggable flag: $DEBUGGABLE" +if [ "$RET" != 0 -o "$DEBUGGABLE" != "true" ] ; then + # If gdb.setup exists, then we built with 'ndk-build NDK_DEBUG=1' and it's + # ok to not have android:debuggable set to true in the original manifest. + # However, if this is not the case, then complain!! + if [ -f $PROJECT/libs/$COMPAT_ABI/gdb.setup ] ; then + log "Found gdb.setup under libs/$COMPAT_ABI, assuming app was built with NDK_DEBUG=1" + else + echo "ERROR: Package $PACKAGE_NAME is not debuggable ! You can fix that in two ways:" + echo "" + echo " - Rebuilt with the NDK_DEBUG=1 option when calling 'ndk-build'." + echo "" + echo " - Modify your manifest to set android:debuggable attribute to \"true\"," + echo " then rebuild normally." + echo "" + echo "After one of these, re-install to the device!" + exit 1 + fi +else + # DEBUGGABLE is true in the manifest. Let's check that the user didn't change the + # debuggable flag in the manifest without calling ndk-build afterwards. + if [ ! -f $PROJECT/libs/$COMPAT_ABI/gdb.setup ] ; then + echo "ERROR: Could not find gdb.setup under $PROJECT/libs/$COMPAT_ABI" + echo " This usually means you modified your AndroidManifest.xml to set" + echo " the android:debuggable flag to 'true' but did not rebuild the" + echo " native binaries. Please call 'ndk-build' to do so," + echo " *then* re-install to the device!" + exit 1 + fi +fi + +# Find the of the package on the device +adb_var_shell2 DATA_DIR run-as $PACKAGE_NAME /system/bin/sh -c pwd +if [ $? != 0 -o -z "$DATA_DIR" ] ; then + echo "ERROR: Could not extract package's data directory. Are you sure that" + echo " your installed application is debuggable?" + exit 1 +fi +log "Found data directory: '$DATA_DIR'" + +# Let's check that 'gdbserver' is properly installed on the device too. If 'gdbserver' +# is not there, push 'gdbserver' found in prebuilt. +# +DEVICE_GDBSERVER=$DATA_DIR/lib/gdbserver +adb_var_shell2 GDBSERVER_RESULT ls $DEVICE_GDBSERVER +if [ $? != 0 ]; then + + # Figure out what's the target-arch and find gdbserver in prebuilt. + TARGET_ARCH=none + + for ANDROID_ARCH in $ANDROID_NDK_ROOT/prebuilt/android-*; do + ANDROID_ARCH=${ANDROID_ARCH#$ANDROID_NDK_ROOT/prebuilt/android-} + if [ "$COMPAT_ABI" = "$ANDROID_ARCH" ]; then + TARGET_ARCH=$ANDROID_ARCH + break; + fi + done + + if [ $TARGET_ARCH != "none" ]; then + DEVICE_GDBSERVER=/data/local/tmp/gdbserver + + adb shell mkdir -p /data/local/tmp + adb push ${ANDROID_NDK_ROOT}/prebuilt/android-${TARGET_ARCH}/gdbserver/gdbserver \ + $DEVICE_GDBSERVER + log "Push gdbserver in device" + else + echo "ERROR: Non-debuggable application installed on the target device." + echo " Please re-install the debuggable version!" + exit 1 + fi +fi +log "Found device gdbserver: $DEVICE_GDBSERVER" + +# Launch the activity if needed +if [ "$OPTION_START" = "yes" ] ; then + # If --launch is used, ignore --start, otherwise extract the first + # launchable activity name from the manifest and use it as if --launch= + # was used instead. + # + if [ -z "$OPTION_LAUNCH" ] ; then + OPTION_LAUNCH=`run_awk_manifest_script extract-launchable.awk | sed 2q` + if [ $? != 0 ] ; then + echo "ERROR: Could not extract name of launchable activity from manifest!" + echo " Try to use --launch= directly instead as a work-around." + exit 1 + fi + log "Found first launchable activity: $OPTION_LAUNCH" + if [ -z "$OPTION_LAUNCH" ] ; then + echo "ERROR: It seems that your Application does not have any launchable activity!" + echo " Please fix your manifest file and rebuild/re-install your application." + exit 1 + fi + fi +fi + +if [ -n "$OPTION_LAUNCH" ] ; then + log "Launching activity: $PACKAGE_NAME/$OPTION_LAUNCH" + adb_var_shell2 DUMMY am start $OPTION_WAIT -n $PACKAGE_NAME/$OPTION_LAUNCH + if [ $? != 0 ] ; then + echo "ERROR: Could not launch specified activity: $OPTION_LAUNCH" + echo " Use --launch-list to dump a list of valid values." + exit 1 + fi + # Sleep a bit, it sometimes take one second to start properly + # Note that we use the 'sleep' command on the device here. + run adb_cmd shell sleep $DELAY +fi + +# Find the PID of the application being run +PID=$(get_pid_of "$PACKAGE_NAME") +RET=$? +log "Found running PID: $PID" +if [ "$RET" != 0 -o "$PID" = "0" ] ; then + echo "ERROR: Could not extract PID of application on device/emulator." + if [ -n "$OPTION_LAUNCH" ] ; then + echo " Weird, this probably means one of these:" + echo "" + echo " - The installed package does not match your current manifest." + echo " - The application process was terminated." + echo "" + echo " Try using the --verbose option and look at its output for details." + else + echo " Are you sure the application is already started?" + echo " Consider using --start or --launch= if not." + fi + exit 1 +fi + +# Check that there is no other instance of gdbserver running +GDBSERVER_PID=$(get_pid_of lib/gdbserver) +if [ "$GDBSERVER_PID" != "0" ]; then + if [ "$OPTION_FORCE" = "no" ] ; then + echo "ERROR: Another debug session running, Use --force to kill it." + exit 1 + fi + log "Killing existing debugging session" + run adb_cmd shell kill -9 $GDBSERVER_PID +fi + +# Launch gdbserver now +DEBUG_SOCKET=debug-socket +adb_var_shell2 DUMMY run-as $PACKAGE_NAME $DEVICE_GDBSERVER +$DEBUG_SOCKET --attach $PID & +if [ $? != 0 ] ; then + echo "ERROR: Could not launch gdbserver on the device?" + exit 1 +fi +log "Launched gdbserver succesfully." + +# Setup network redirection +log "Setup network redirection" +run adb_cmd forward tcp:$DEBUG_PORT localfilesystem:$DATA_DIR/$DEBUG_SOCKET +if [ $? != 0 ] ; then + echo "ERROR: Could not setup network redirection to gdbserver?" + echo " Maybe using --port= to use a different TCP port might help?" + exit 1 +fi + +# If we are debugging 64-bit app, then we need to pull linker64, +# app_process64 and libc.so from lib64 directory +LINKER_NAME=linker +LIBDIR_NAME=lib +APP_PROCESS_NAME=app_process32 +if [ "$COMPAT_ABI_BITS" = 64 ] ; then + LINKER_NAME=linker64 + LIBDIR_NAME=lib64 + APP_PROCESS_NAME=app_process64 +else + # Old 32-bit devices do not have app_process32. Pull + # app_process in this case + adb_var_shell2 DUMMY test -e /system/bin/$APP_PROCESS_NAME + if [ $? != 0 ] ; then + APP_PROCESS_NAME=app_process + fi +fi + +# Get the app_server binary from the device +APP_PROCESS=$APP_OUT/app_process +run adb_cmd pull /system/bin/$APP_PROCESS_NAME `native_path $APP_PROCESS` +log "Pulled $APP_PROCESS_NAME from device/emulator." + +run adb_cmd pull /system/bin/$LINKER_NAME `native_path $APP_OUT/$LINKER_NAME` +log "Pulled $LINKER_NAME from device/emulator." + +run adb_cmd pull /system/$LIBDIR_NAME/libc.so `native_path $APP_OUT/libc.so` +log "Pulled /system/$LIBDIR_NAME/libc.so from device/emulator." + +# Setup JDB connection, for --start or --launch +if [ "$OPTION_START" = "yes" ] || [ -n "$OPTION_LAUNCH" ] ; then + if [ -n "$JDB_PORT" ]; then + log "Setup JDB connection" + run adb_cmd forward tcp:$JDB_PORT jdwp:$PID + sleep 1 + $JDB_CMD -connect com.sun.jdi.SocketAttach:hostname=localhost,port=$JDB_PORT & + sleep 1 + fi +fi + +# If we are debugging UNKNOWN_ABI, download compiled *.so from device. +# +if [ "$COMPAT_ABI" = "$UNKNOWN_ABI" ]; then + for bc in $BCFILES; do + log "Pulled $(basename $bc .bc).so from device/emulator." + adb pull $DATA_DIR/lib/$(basename $bc .bc).so $PROJECT/obj/local/$UNKNOWN_ABI/ + done +fi + +# Now launch the appropriate gdb client with the right init commands +# +GDBCLIENT=${TOOLCHAIN_PREFIX}gdb +GDBSETUP=$APP_OUT/gdb.setup +cp -f $GDBSETUP_INIT $GDBSETUP +#uncomment the following to debug the remote connection only +#echo "set debug remote 1" >> $GDBSETUP +echo "file `native_path $APP_PROCESS`" >> $GDBSETUP +echo "target remote :$DEBUG_PORT" >> $GDBSETUP +if [ -n "$OPTION_EXEC" ] ; then + cat $OPTION_EXEC >> $GDBSETUP +fi +$GDBCLIENT -x `native_path $GDBSETUP`