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