Home | History | Annotate | Download | only in ndk
      1 #!/bin/sh
      2 #
      3 # Copyright (C) 2010 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 # This wrapper script is used to launch a native debugging session
     19 # on a given NDK application. The application must be debuggable, i.e.
     20 # its android:debuggable attribute must be set to 'true' in the
     21 # <application> element of its manifest.
     22 #
     23 # See docs/NDK-GDB.TXT for usage description. Essentially, you just
     24 # need to launch ndk-gdb from your application project directory
     25 # after doing ndk-build && ant install && <start-application-on-device>
     26 #
     27 . `dirname $0`/build/core/ndk-common.sh
     28 
     29 force_32bit_binaries
     30 
     31 # Find if a given shell program is available.
     32 # We need to take care of the fact that the 'which <foo>' command
     33 # may return either an empty string (Linux) or something like
     34 # "no <foo> in ..." (Darwin). Also, we need to redirect stderr
     35 # to /dev/null for Cygwin
     36 #
     37 # $1: program name
     38 # Out: program path, or empty string
     39 # Return: 0 on success, != 0 on error
     40 #
     41 find_program ()
     42 {
     43     local PROG RET
     44     PROG=$(which "$1" 2>/dev/null)
     45     RET=$?
     46     if [ $RET != 0 ]; then
     47         PROG=
     48     fi
     49     echo "$PROG"
     50     return $RET
     51 }
     52 
     53 quote_spaces ()
     54 {
     55     echo "$@" | sed -e 's! !\ !g'
     56 }
     57 
     58 # If ADB_CMD is not defined, try to find a program named 'adb'
     59 # in our path.
     60 ADB_CMD=${ADB_CMD:-$(find_program adb)}
     61 ADB_FLAGS=${ADB_FLAGS:-}
     62 
     63 AWK_CMD=${AWK_CMD:-$(find_program awk)}
     64 
     65 DEBUG_PORT=5039
     66 
     67 # Delay in seconds between launching the activity and attaching gdbserver on it.
     68 # This is needed because there is no way to know when the activity has really
     69 # started, and sometimes this takes a few seconds.
     70 DELAY=2
     71 
     72 PARAMETERS=
     73 OPTION_HELP=no
     74 OPTION_PROJECT=
     75 OPTION_FORCE=no
     76 OPTION_ADB=
     77 OPTION_EXEC=
     78 OPTION_START=no
     79 OPTION_LAUNCH=
     80 OPTION_LAUNCH_LIST=no
     81 OPTION_DELAY=
     82 
     83 check_parameter ()
     84 {
     85     if [ -z "$2" ]; then
     86         echo "ERROR: Missing parameter after option '$1'"
     87         exit 1
     88     fi
     89 }
     90 
     91 check_adb_flags ()
     92 {
     93     if [ -n "$ADB_FLAGS" ] ; then
     94         echo "ERROR: Only one of -e, -d or -s <serial> can be used at the same time!"
     95         exit 1
     96     fi
     97 }
     98 
     99 get_build_var ()
    100 {
    101     if [ -z "$GNUMAKE" ] ; then
    102         GNUMAKE=make
    103     fi
    104     $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1
    105 }
    106 
    107 get_build_var_for_abi ()
    108 {
    109     if [ -z "$GNUMAKE" ] ; then
    110         GNUMAKE=make
    111     fi
    112     $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1 APP_ABI=$2
    113 }
    114 
    115 # Used to run an awk script on the manifest
    116 run_awk_manifest_script ()
    117 {
    118     $AWK_CMD -f $AWK_SCRIPTS/$1 $PROJECT/$MANIFEST
    119 }
    120 
    121 if [ "$HOST_OS" = "cygwin" ] ; then
    122 # Return native path representation from cygwin one
    123 # $1: a cygwin-compatible path (e.g. /cygdrive/c/some/thing)
    124 # Return: path in host windows representation, e.g. C:/some/thing
    125 #
    126 # We use mixed mode (i.e. / as the directory separator) because
    127 # all the tools we use recognize it properly, and it avoids lots
    128 # of escaping nonsense associated with "\"
    129 #
    130 native_path ()
    131 {
    132     cygpath -m $1
    133 }
    134 else # HOST_OS != windows
    135 native_path ()
    136 {
    137     echo "$1"
    138 }
    139 fi # HOST_OS != windows
    140 
    141 # We need to ensure the ANDROID_NDK_ROOT is absolute, otherwise calls
    142 # to get_build_var, get_build_var_for_abi and run_awk_manifest_script
    143 # might fail, e.g. when invoked with:
    144 #
    145 #   cd $NDKROOT
    146 #   ./ndk-gdb --project=/path/to/project
    147 #
    148 path_is_absolute ()
    149 {
    150     local P P2
    151     P=$1       # copy path
    152     P2=${P#/}  # remove / prefix, if any
    153     [ "$P" != "$P2" ]
    154 }
    155 
    156 if ! path_is_absolute "$ANDROID_NDK_ROOT"; then
    157     ANDROID_NDK_ROOT=$(pwd)/$ANDROID_NDK_ROOT
    158 fi
    159 
    160 
    161 VERBOSE=no
    162 while [ -n "$1" ]; do
    163     opt="$1"
    164     optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
    165     case "$opt" in
    166         --help|-h|-\?)
    167             OPTION_HELP=yes
    168             ;;
    169         --verbose)
    170             VERBOSE=yes
    171             ;;
    172         -s)
    173             check_parameter $1 $2
    174             check_adb_flags
    175             ADB_FLAGS=" -s $2"
    176             shift
    177             ;;
    178         -s*)
    179             check_adb_flags
    180             optarg=`expr -- "$opt" : '-s\(.*\)'`
    181             ADB_FLAGS=" -s $optarg"
    182             ;;
    183         -p)
    184             check_parameter $1 $2
    185             OPTION_PROJECT="$2"
    186             shift
    187             ;;
    188         -p*)
    189             optarg=`expr -- "$opt" : '-p\(.*\)'`
    190             OPTION_PROJECT="$optarg"
    191             ;;
    192         --exec=*)
    193             OPTION_EXEC="$optarg"
    194             ;;
    195         -x)
    196             check_parameter $1 $2
    197             OPTION_EXEC="$2"
    198             shift
    199             ;;
    200         -x*)
    201             optarg=`expr -- "$opt" : '-x\(.*\)'`
    202             OPTION_EXEC="$optarg"
    203             ;;
    204         -e)
    205             check_adb_flags
    206             ADB_FLAGS=" -e"
    207             ;;
    208         -d)
    209             check_adb_flags
    210             ADB_FLAGS=" -d"
    211             ;;
    212         --adb=*) # specify ADB command
    213             OPTION_ADB="$optarg"
    214             ;;
    215         --awk=*)
    216             AWK_CMD="$optarg"
    217             ;;
    218         --project=*)
    219             OPTION_PROJECT="$optarg"
    220             ;;
    221         --port=*)
    222             DEBUG_PORT="$optarg"
    223             ;;
    224         --force)
    225             OPTION_FORCE="yes"
    226             ;;
    227         --launch-list)
    228             OPTION_LAUNCH_LIST="yes"
    229             ;;
    230         --launch=*)
    231             OPTION_LAUNCH="$optarg"
    232             ;;
    233         --start)
    234             OPTION_START=yes
    235             ;;
    236         --delay=*)
    237             OPTION_DELAY="$optarg"
    238             ;;
    239         -*) # unknown options
    240             echo "ERROR: Unknown option '$opt', use --help for list of valid ones."
    241             exit 1
    242         ;;
    243         *)  # Simply record parameter
    244             if [ -z "$PARAMETERS" ] ; then
    245                 PARAMETERS="$opt"
    246             else
    247                 PARAMETERS="$PARAMETERS $opt"
    248             fi
    249             ;;
    250     esac
    251     shift
    252 done
    253 
    254 if [ "$OPTION_HELP" = "yes" ] ; then
    255     echo "Usage: $PROGNAME [options]"
    256     echo ""
    257     echo "Setup a gdb debugging session for your Android NDK application."
    258     echo "Read $$NDK/docs/NDK-GDB.TXT for complete usage instructions."
    259     echo ""
    260     echo "Valid options:"
    261     echo ""
    262     echo "    --help|-h|-?      Print this help"
    263     echo "    --verbose         Enable verbose mode"
    264     echo "    --force           Kill existing debug session if it exists"
    265     echo "    --start           Launch application instead of attaching to existing one"
    266     echo "    --launch=<name>   Same as --start, but specify activity name (see below)"
    267     echo "    --launch-list     List all launchable activity names from manifest"
    268     echo "    --delay=<secs>    Delay in seconds between activity start and gdbserver attach."
    269     echo "    --project=<path>  Specify application project path"
    270     echo "    -p <path>         Same as --project=<path>"
    271     echo "    --port=<port>     Use tcp:localhost:<port> to communicate with gdbserver [$DEBUG_PORT]"
    272     echo "    --exec=<file>     Execute gdb initialization commands in <file> after connection"
    273     echo "    -x <file>         Same as --exec=<file>"
    274     echo "    --adb=<file>      Use specific adb command [$ADB_CMD]"
    275     echo "    --awk=<file>      Use specific awk command [$AWK_CMD]"
    276     echo "    -e                Connect to single emulator instance"
    277     echo "    -d                Connect to single target device"
    278     echo "    -s <serial>       Connect to specific emulator or device"
    279     echo ""
    280     exit 0
    281 fi
    282 
    283 log "Android NDK installation path: $ANDROID_NDK_ROOT"
    284 
    285 if [ -n "$OPTION_EXEC" ] ; then
    286     if [ ! -f "$OPTION_EXEC" ]; then
    287         echo "ERROR: Invalid initialization file: $OPTION_EXEC"
    288         exit 1
    289     fi
    290 fi
    291 
    292 if [ -n "$OPTION_DELAY" ] ; then
    293     DELAY="$OPTION_DELAY"
    294 fi
    295 
    296 # Check ADB tool version
    297 if [ -n "$OPTION_ADB" ] ; then
    298     ADB_CMD=$OPTION_ADB
    299     log "Using specific adb command: $ADB_CMD"
    300 else
    301     if [ -z "$ADB_CMD" ] ; then
    302         echo "ERROR: The 'adb' tool is not in your path."
    303         echo "       You can change your PATH variable, or use"
    304         echo "       --adb=<executable> to point to a valid one."
    305         exit 1
    306     fi
    307     log "Using default adb command: $ADB_CMD"
    308 fi
    309 
    310 ADB_CMD=$(quote_spaces $ADB_CMD)
    311 ADB_VERSION=$("$ADB_CMD" version 2>/dev/null)
    312 if [ $? != 0 ] ; then
    313     echo "ERROR: Could not run ADB with: $ADB_CMD"
    314     exit 1
    315 fi
    316 log "ADB version found: $ADB_VERSION"
    317 
    318 log "Using ADB flags: $ADB_FLAGS"
    319 
    320 
    321 # Used internally by adb_var_shell and adb_var_shell2.
    322 # $1: 1 to redirect stderr to $1, 0 otherwise.
    323 # $2: Variable name that will contain the result
    324 # $3+: Command options
    325 _adb_var_shell ()
    326 {
    327     # We need a temporary file to store the output of our command
    328     local CMD_OUT RET OUTPUT VARNAME REDIRECT_STDERR
    329     REDIRECT_STDERR=$1
    330     VARNAME=$2
    331     shift; shift;
    332     CMD_OUT=`mktemp /tmp/ndk-gdb-cmdout-XXXXXX`
    333     # Run the command, while storing the standard output to CMD_OUT
    334     # and appending the exit code as the last line.
    335     if [ "$REDIRECT_STDERR" != 0 ]; then
    336         "$ADB_CMD" $ADB_FLAGS shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1
    337     else
    338         "$ADB_CMD" $ADB_FLAGS shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT
    339     fi
    340     # Get last line in log, which contains the exit code from the command
    341     RET=`sed -e '$!d' $CMD_OUT`
    342     # Get output, which corresponds to everything except the last line
    343     OUT=`sed -e '$d' $CMD_OUT`
    344     rm -f $CMD_OUT
    345     eval $VARNAME=\"\$OUT\"
    346     return $RET
    347 }
    348 
    349 # Run a command through 'adb shell' and captures its standard output
    350 # into a variable. The function's exit code is the same than the command's.
    351 #
    352 # This is required because there is a bug where "adb shell" always returns
    353 # 0 on the host, even if the command fails on the device.
    354 #
    355 # $1: Variable name (e.g. FOO)
    356 # On exit, $FOO is set to the command's standard output
    357 #
    358 # The return status will be 0 (success) if the command succeeded
    359 # or 1 (failure) otherwise.
    360 adb_var_shell ()
    361 {
    362     _adb_var_shell 0 "$@"
    363 }
    364 
    365 # A variant of adb_var_shell that stores both stdout and stderr in the output
    366 # $1: Variable name
    367 adb_var_shell2 ()
    368 {
    369     _adb_var_shell 1 "$@"
    370 }
    371 
    372 # Return the PID of a given package or program, or 0 if it doesn't run
    373 # $1: Package name ("com.example.hellojni") or program name ("/lib/gdbserver")
    374 # Out: PID number, or 0 if not running
    375 get_pid_of ()
    376 {
    377     "$ADB_CMD" shell ps | $AWK_CMD -f $AWK_SCRIPTS/extract-pid.awk -v PACKAGE="$1"
    378 }
    379 
    380 # Check the awk tool
    381 AWK_SCRIPTS=$ANDROID_NDK_ROOT/build/awk
    382 AWK_TEST=`$AWK_CMD -f $AWK_SCRIPTS/check-awk.awk`
    383 if [ $? != 0 ] ; then
    384     echo "ERROR: Could not run '$AWK_CMD' command. Do you have it installed properly?"
    385     exit 1
    386 fi
    387 if [ "$AWK_TEST" != "Pass" ] ; then
    388     echo "ERROR: Your version of 'awk' is obsolete. Please use --awk=<file> to point to Nawk or Gawk!"
    389     exit 1
    390 fi
    391 
    392 # Name of the manifest file
    393 MANIFEST=AndroidManifest.xml
    394 
    395 # Find the root of the application project.
    396 if [ -n "$OPTION_PROJECT" ] ; then
    397     PROJECT=$OPTION_PROJECT
    398     log "Using specified project path: $PROJECT"
    399     if [ ! -d "$PROJECT" ] ; then
    400         echo "ERROR: Your --project option does not point to a directory!"
    401         exit 1
    402     fi
    403     if [ ! -f "$PROJECT/$MANIFEST" ] ; then
    404         echo "ERROR: Your --project does not point to an Android project path!"
    405         echo "       It is missing a $MANIFEST file."
    406         exit 1
    407     fi
    408 else
    409     # Assume we are in the project directory
    410     if [ -f "$MANIFEST" ] ; then
    411         PROJECT=.
    412     else
    413         PROJECT=
    414         CURDIR=`pwd`
    415         while [ "$CURDIR" != "/" ] ; do
    416             if [ -f "$CURDIR/$MANIFEST" ] ; then
    417                 PROJECT="$CURDIR"
    418                 break
    419             fi
    420             CURDIR=`dirname $CURDIR`
    421         done
    422         if [ -z "$PROJECT" ] ; then
    423             echo "ERROR: Launch this script from an application project directory, or use --project=<path>."
    424             exit 1
    425         fi
    426     fi
    427     log "Using auto-detected project path: $PROJECT"
    428 fi
    429 
    430 # Extract the package name from the manifest
    431 PACKAGE_NAME=`run_awk_manifest_script extract-package-name.awk`
    432 log "Found package name: $PACKAGE_NAME"
    433 if [ $? != 0 -o "$PACKAGE_NAME" = "<none>" ] ; then
    434     echo "ERROR: Could not extract package name from $PROJECT/$MANIFEST."
    435     echo "       Please check that the file is well-formed!"
    436     exit 1
    437 fi
    438 
    439 # If --launch-list is used, list all launchable activities, and be done with it
    440 if [ "$OPTION_LAUNCH_LIST" = "yes" ] ; then
    441     log "Extracting list of launchable activities from manifest:"
    442     run_awk_manifest_script extract-launchable.awk
    443     exit 0
    444 fi
    445 
    446 APP_ABIS=`get_build_var APP_ABI`
    447 log "ABIs targetted by application: $APP_ABIS"
    448 
    449 # Check the ADB command, and that we can connect to the device/emulator
    450 ADB_TEST=`"$ADB_CMD" shell ls`
    451 if [ $? != 0 ] ; then
    452     echo "ERROR: Could not connect to device or emulator!"
    453     echo "       Please check that an emulator is running or a device is connected"
    454     echo "       through USB to this machine. You can use -e, -d and -s <serial>"
    455     echo "       in case of multiple ones."
    456     exit 1
    457 fi
    458 
    459 # Check that the device is running Froyo (API Level 8) or higher
    460 #
    461 adb_var_shell API_LEVEL getprop ro.build.version.sdk
    462 if [ $? != 0 -o -z "$API_LEVEL" ] ; then
    463     echo "ERROR: Could not find target device's supported API level!"
    464     echo "ndk-gdb will only work if your device is running Android 2.2 or higher."
    465     exit 1
    466 fi
    467 log "Device API Level: $API_LEVEL"
    468 if [ "$API_LEVEL" -lt "8" ] ; then
    469     echo "ERROR: ndk-gdb requires a target device running Android 2.2 (API level 8) or higher."
    470     echo "The target device is running API level $API_LEVEL!"
    471     exit 1
    472 fi
    473 
    474 # Get the target device's supported ABI(s)
    475 # And check that they are supported by the application
    476 #
    477 COMPAT_ABI=none
    478 adb_var_shell CPU_ABI getprop ro.product.cpu.abi
    479 for ABI in $APP_ABIS; do
    480     if [ "$ABI" = "$CPU_ABI" ] ; then
    481         COMPAT_ABI=$CPU_ABI
    482         break
    483     fi
    484 done
    485 
    486 adb_var_shell CPU_ABI2 getprop ro.product.cpu.abi2
    487 if [ $? != 0 -o -z "$CPU_ABI2" ] ; then
    488     CPU_ABI2=
    489     log "Device CPU ABI: $CPU_ABI"
    490 else
    491     log "Device CPU ABIs: $CPU_ABI $CPU_ABI2"
    492     if [ "$COMPAT_ABI" = "none" ] ; then
    493         for ABI in $APP_ABIS; do
    494             if [ "$ABI" = "$CPU_ABI2" ] ; then
    495                 COMPAT_ABI=$CPU_ABI2
    496                 break
    497             fi
    498         done
    499     fi
    500 fi
    501 if [ "$COMPAT_ABI" = none ] ; then
    502     echo "ERROR: The device does not support the application's targetted CPU ABIs!"
    503     if [ "$CPU_ABI2" = "$CPU_ABI" ] ; then
    504         CPU_ABI2=
    505     fi
    506     echo "       Device supports:  $CPU_ABI $CPU_ABI2"
    507     echo "       Package supports: $APP_ABIS"
    508     exit 1
    509 fi
    510 log "Compatible device ABI: $COMPAT_ABI"
    511 
    512 # Get information from the build system
    513 GDBSETUP_INIT=`get_build_var_for_abi NDK_APP_GDBSETUP $COMPAT_ABI`
    514 log "Using gdb setup init: $GDBSETUP_INIT"
    515 
    516 TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $COMPAT_ABI`
    517 log "Using toolchain prefix: $TOOLCHAIN_PREFIX"
    518 
    519 APP_OUT=`get_build_var_for_abi TARGET_OUT $COMPAT_ABI`
    520 log "Using app out directory: $APP_OUT"
    521 
    522 # Check that the application is debuggable, or nothing will work
    523 DEBUGGABLE=`run_awk_manifest_script extract-debuggable.awk`
    524 log "Found debuggable flag: $DEBUGGABLE"
    525 if [ $? != 0 -o "$DEBUGGABLE" != "true" ] ; then
    526     # If gdbserver exists, then we built with 'ndk-build NDK_DEBUG=1' and it's
    527     # ok to not have android:debuggable set to true in the original manifest.
    528     # However, if this is not the case, then complain!!
    529     if [ -f $PROJECT/libs/$COMPAT_ABI/gdbserver ] ; then
    530         log "Found gdbserver under libs/$COMPAT_ABI, assuming app was built with NDK_DEBUG=1"
    531     else
    532         echo "ERROR: Package $PACKAGE_NAME is not debuggable ! You can fix that in two ways:"
    533         echo ""
    534         echo "  - Rebuilt with the NDK_DEBUG=1 option when calling 'ndk-build'."
    535         echo ""
    536         echo "  - Modify your manifest to set android:debuggable attribute to \"true\","
    537         echo "    then rebuild normally."
    538         echo ""
    539         echo "After one of these, re-install to the device!"
    540         exit 1
    541     fi
    542 else
    543     # DEBUGGABLE is true in the manifest. Let's check that the user didn't change the
    544     # debuggable flag in the manifest without calling ndk-build afterwards.
    545     if [ ! -f $PROJECT/libs/$COMPAT_ABI/gdbserver ] ; then
    546         echo "ERROR: Could not find gdbserver binary under $PROJECT/libs/$COMPAT_ABI"
    547         echo "       This usually means you modified your AndroidManifest.xml to set"
    548         echo "       the android:debuggable flag to 'true' but did not rebuild the"
    549         echo "       native binaries. Please call 'ndk-build' to do so,"
    550         echo "       *then* re-install to the device!"
    551         exit 1
    552     fi
    553 fi
    554 
    555 # Let's check that 'gdbserver' is properly installed on the device too. If this
    556 # is not the case, the user didn't install the proper package after rebuilding.
    557 #
    558 adb_var_shell2 DEVICE_GDBSERVER ls /data/data/$PACKAGE_NAME/lib/gdbserver
    559 if [ $? != 0 ]; then
    560     echo "ERROR: Non-debuggable application installed on the target device."
    561     echo "       Please re-install the debuggable version!"
    562     exit 1
    563 fi
    564 log "Found device gdbserver: $DEVICE_GDBSERVER"
    565 
    566 # Find the <dataDir> of the package on the device
    567 adb_var_shell2 DATA_DIR run-as $PACKAGE_NAME /system/bin/sh -c pwd
    568 if [ $? != 0 -o -z "$DATA_DIR" ] ; then
    569     echo "ERROR: Could not extract package's data directory. Are you sure that"
    570     echo "       your installed application is debuggable?"
    571     exit 1
    572 fi
    573 log "Found data directory: '$DATA_DIR'"
    574 
    575 # Launch the activity if needed
    576 if [ "$OPTION_START" = "yes" ] ; then
    577     # If --launch is used, ignore --start, otherwise extract the first
    578     # launchable activity name from the manifest and use it as if --launch=<name>
    579     # was used instead.
    580     #
    581     if [ -z "$OPTION_LAUNCH" ] ; then
    582         OPTION_LAUNCH=`run_awk_manifest_script extract-launchable.awk | sed 2q`
    583         if [ $? != 0 ] ; then
    584             echo "ERROR: Could not extract name of launchable activity from manifest!"
    585             echo "       Try to use --launch=<name> directly instead as a work-around."
    586             exit 1
    587         fi
    588         log "Found first launchable activity: $OPTION_LAUNCH"
    589         if [ -z "$OPTION_LAUNCH" ] ; then
    590             echo "ERROR: It seems that your Application does not have any launchable activity!"
    591             echo "       Please fix your manifest file and rebuild/re-install your application."
    592             exit 1
    593         fi
    594     fi
    595 fi
    596 
    597 if [ -n "$OPTION_LAUNCH" ] ; then
    598     log "Launching activity: $PACKAGE_NAME/$OPTION_LAUNCH"
    599     run "$ADB_CMD" shell am start -n $PACKAGE_NAME/$OPTION_LAUNCH
    600     if [ $? != 0 ] ; then
    601         echo "ERROR: Could not launch specified activity: $OPTION_LAUNCH"
    602         echo "       Use --launch-list to dump a list of valid values."
    603         exit 1
    604     fi
    605     # Sleep a bit, it sometimes take one second to start properly
    606     # Note that we use the 'sleep' command on the device here.
    607     run "$ADB_CMD" shell sleep $DELAY
    608 fi
    609 
    610 # Find the PID of the application being run
    611 PID=$(get_pid_of "$PACKAGE_NAME")
    612 log "Found running PID: $PID"
    613 if [ $? != 0 -o "$PID" = "0" ] ; then
    614     echo "ERROR: Could not extract PID of application on device/emulator."
    615     if [ -n "$OPTION_LAUNCH" ] ; then
    616         echo "       Weird, this probably means one of these:"
    617         echo ""
    618         echo "         - The installed package does not match your current manifest."
    619         echo "         - The application process was terminated."
    620         echo ""
    621         echo "       Try using the --verbose option and look at its output for details."
    622     else
    623         echo "       Are you sure the application is already started?"
    624         echo "       Consider using --start or --launch=<name> if not."
    625     fi
    626     exit 1
    627 fi
    628 
    629 # Check that there is no other instance of gdbserver running
    630 GDBSERVER_PID=$(get_pid_of lib/gdbserver)
    631 if [ "$GDBSERVER_PID" != "0" ]; then
    632     if [ "$OPTION_FORCE" = "no" ] ; then
    633         echo "ERROR: Another debug session running, Use --force to kill it."
    634         exit 1
    635     fi
    636     log "Killing existing debugging session"
    637     run "$ADB_CMD" shell kill -9 $GDBSERVER_PID
    638 fi
    639 
    640 # Launch gdbserver now
    641 DEBUG_SOCKET=debug-socket
    642 run "$ADB_CMD" shell run-as $PACKAGE_NAME lib/gdbserver +$DEBUG_SOCKET --attach $PID &
    643 if [ $? != 0 ] ; then
    644     echo "ERROR: Could not launch gdbserver on the device?"
    645     exit 1
    646 fi
    647 log "Launched gdbserver succesfully."
    648 
    649 # Setup network redirection
    650 log "Setup network redirection"
    651 run "$ADB_CMD" forward tcp:$DEBUG_PORT localfilesystem:$DATA_DIR/$DEBUG_SOCKET
    652 if [ $? != 0 ] ; then
    653     echo "ERROR: Could not setup network redirection to gdbserver?"
    654     echo "       Maybe using --port=<port> to use a different TCP port might help?"
    655     exit 1
    656 fi
    657 
    658 # Get the app_server binary from the device
    659 APP_PROCESS=$APP_OUT/app_process
    660 run "$ADB_CMD" pull /system/bin/app_process `native_path $APP_PROCESS`
    661 log "Pulled app_process from device/emulator."
    662 
    663 run "$ADB_CMD" pull /system/lib/libc.so `native_path $APP_OUT/libc.so`
    664 log "Pulled libc.so from device/emulator."
    665 
    666 # Now launch the appropriate gdb client with the right init commands
    667 #
    668 GDBCLIENT=${TOOLCHAIN_PREFIX}gdb
    669 GDBSETUP=$APP_OUT/gdb.setup
    670 cp -f $GDBSETUP_INIT $GDBSETUP
    671 #uncomment the following to debug the remote connection only
    672 #echo "set debug remote 1" >> $GDBSETUP
    673 echo "file `native_path $APP_PROCESS`" >> $GDBSETUP
    674 echo "target remote :$DEBUG_PORT" >> $GDBSETUP
    675 if [ -n "$OPTION_EXEC" ] ; then
    676     cat $OPTION_EXEC >> $GDBSETUP
    677 fi
    678 $GDBCLIENT -x `native_path $GDBSETUP`
    679