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