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