blob: 93a930df44e73e8d39c60ad80659204ba8cce88f [file] [log] [blame]
David 'Digit' Turnera08d6052010-04-16 12:45:33 -07001#!/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
38PARAMETERS=
39OPTION_HELP=no
40OPTION_PROJECT=
41OPTION_FORCE=no
42OPTION_ADB=
43OPTION_EXEC=
44
45check_parameter ()
46{
47 if [ -z "$2" ]; then
48 echo "ERROR: Missing parameter after option '$1'"
49 exit 1
50 fi
51}
52
53check_adb_flags ()
54{
55 if [ -n "$ADB_FLAGS" ] ; then
56 echo "ERROR: Only one of -e, -d or -s <serial> can be used at the same time!"
57 exit 1
58 fi
59}
60
61get_build_var ()
62{
63 if [ -z "$GNUMAKE" ] ; then
64 GNUMAKE=make
65 fi
66 $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1
67}
68
69get_build_var_for_abi ()
70{
71 if [ -z "$GNUMAKE" ] ; then
72 GNUMAKE=make
73 fi
74 $GNUMAKE --no-print-dir -f $ANDROID_NDK_ROOT/build/core/build-local.mk -C $PROJECT DUMP_$1 APP_ABI=$2
75}
76
77VERBOSE=no
78while [ -n "$1" ]; do
79 opt="$1"
80 optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
81 case "$opt" in
82 --help|-h|-\?)
83 OPTION_HELP=yes
84 ;;
85 --verbose)
86 VERBOSE=yes
87 ;;
88 -s)
89 check_parameter $1 $2
90 check_adb_flags
91 ADB_FLAGS=" -s $2"
92 shift
93 ;;
94 -s*)
95 check_adb_flags
96 optarg=`expr -- "$opt" : '-s\(.*\)'`
97 ADB_FLAGS=" -s $optarg"
98 ;;
99 -p)
100 check_parameter $1 $2
101 OPTION_PROJECT="$2"
102 shift
103 ;;
104 -p*)
105 optarg=`expr -- "$opt" : '-p\(.*\)'`
106 OPTION_PROJECT="$optarg"
107 ;;
108 --exec=*)
109 OPTION_EXEC="$optarg"
110 ;;
111 -x)
112 check_parameter $1 $2
113 OPTION_EXEC="$2"
114 shift
115 ;;
116 -x*)
117 optarg=`expr -- "$opt" : '-x\(.*\)'`
118 OPTION_EXEC="$optarg"
119 ;;
120 -e)
121 check_adb_flags
122 ADB_FLAGS=" -e"
123 ;;
124 -d)
125 check_adb_flags
126 ADB_FLAGS=" -d"
127 ;;
128 --adb=*) # specify ADB command
129 OPTION_ADB="$optarg"
130 ;;
131 --awk=*)
132 AWK_CMD="$optarg"
133 ;;
134 --project=*)
135 OPTION_PROJECT="$optarg"
136 ;;
137 --port=*)
138 DEBUG_PORT="$optarg"
139 ;;
140 --force)
141 OPTION_FORCE="yes"
142 ;;
143 -*) # unknown options
144 echo "ERROR: Unknown option '$opt', use --help for list of valid ones."
145 exit 1
146 ;;
147 *) # Simply record parameter
148 if [ -z "$PARAMETERS" ] ; then
149 PARAMETERS="$opt"
150 else
151 PARAMETERS="$PARAMETERS $opt"
152 fi
153 ;;
154 esac
155 shift
156done
157
158if [ "$OPTION_HELP" = "yes" ] ; then
159 echo "Usage: $PROGNAME [options]"
160 echo ""
161 echo "Valid options:"
162 echo ""
163 echo " --help|-h|-? Print this help"
164 echo " --verbose Enable verbose mode"
165 echo " --adb=<file> Use specific adb command [$ADB_CMD]"
166 echo " --awk=<file> Use specific awk command [$AWK_CMD]"
167 echo " --project=<path> Specify application project path"
168 echo " --port=<port> Use tcp:localhost:<port> to communicate with gdbserver [$DEBUG_PORT]"
169 echo " --force Kill existing debug session if it exists"
170 echo " -p <path> Same as --project=<path>"
171 echo " --exec=<file> Execute gdb initialization commands in <file> after connection"
172 echo " -x <file> Same as --exec=<file>"
173 echo " -e Connect to single emulator instance"
174 echo " -d Connect to single target device"
175 echo " -s <serial> Connect to specific emulator or device"
176 echo ""
177 exit 0
178fi
179
180log "Android NDK installation path: $ANDROID_NDK_ROOT"
181
182if [ -n "$OPTION_EXEC" ] ; then
183 if [ ! -f "$OPTION_EXEC" ]; then
184 echo "ERROR: Invalid initialization file: $OPTION_EXEC"
185 exit 1
186 fi
187fi
188
189# Check ADB tool version
190if [ -n "$OPTION_ADB" ] ; then
191 ADB_CMD="$OPTION_ADB"
192 log "Using specific adb command: $ADB_CMD"
193else
194 if [ -z "$ADB_CMD" ] ; then
195 echo "ERROR: The 'adb' tool is not in your path."
196 echo " You can change your PATH variable, or use"
197 echo " --adb=<executable> to point to a valid one."
198 exit 1
199 fi
200 log "Using default adb command: $ADB_CMD"
201fi
202
203ADB_VERSION=`$ADB_CMD version`
204if [ $? != 0 ] ; then
205 echo "ERROR: Could not run ADB with: $ADB_CMD"
206 exit 1
207fi
208log "ADB version found: $ADB_VERSION"
209
210ADB_CMD="${ADB_CMD}${ADB_FLAGS}"
211log "Using final ADB command: '$ADB_CMD'"
212
213
214# Check the awk tool
215AWK_SCRIPTS=$ANDROID_NDK_ROOT/build/core
216AWK_TEST=`$AWK_CMD -f $ANDROID_NDK_ROOT/build/check-awk.awk`
217if [ $? != 0 ] ; then
218 echo "ERROR: Could not run '$AWK_CMD' command. Do you have it installed properly ?"
219 exit 1
220fi
221if [ "$AWK_TEST" != "Pass" ] ; then
222 echo "ERROR: Your version of 'awk' is obsolete. Please use --awk=<file> to point to Nawk or Gawk!"
223 exit 1
224fi
225
226# Name of the manifest file
227MANIFEST=AndroidManifest.xml
228
229# Find the root of the application project.
230if [ -n "$OPTION_PROJECT" ] ; then
231 PROJECT=$OPTION_PROJECT
232 log "Using specified project path: $PROJECT"
233 if [ ! -d "$PROJECT" ] ; then
234 echo "ERROR: Your --project option does not point to a directory!"
235 exit 1
236 fi
237 if [ ! -f "$PROJECT/$MANIFEST" ] ; then
238 echo "ERROR: Your --project does not point to an Android project path!"
239 echo " It is missing a $MANIFEST file."
240 exit 1
241 fi
242else
243 # Assume we are in the project directory
244 if [ -f "$MANIFEST" ] ; then
245 PROJECT=.
246 else
247 PROJECT=
248 CURDIR=`pwd`
249 while [ "$CURDIR" != "/" ] ; do
250 if [ -f "$CURDIR/$MANIFEST" ] ; then
251 PROJECT="$CURDIR"
252 break
253 fi
254 CURDIR=`dirname $CURDIR`
255 done
256 if [ -z "$PROJECT" ] ; then
257 echo "ERROR: Launch this script from an application project directory, or use --project=<path>."
258 exit 1
259 fi
260 fi
261 log "Using auto-detected project path: $PROJECT"
262fi
263
264# Extract the package name from the manifest
265PACKAGE_NAME=`$AWK_CMD -f $AWK_SCRIPTS/extract-package-name.awk $PROJECT/$MANIFEST`
266log "Found package name: $PACKAGE_NAME"
267if [ $? != 0 -o "$PACKAGE_NAME" = "<none>" ] ; then
268 echo "ERROR: Could not extract package name from $PROJECT/$MANIFEST."
269 echo " Please check that the file is well-formed!"
270 exit 1
271fi
272
273# Check that the application is debuggable, or nothing will work
274DEBUGGABLE=`$AWK_CMD -f $AWK_SCRIPTS/extract-package-debuggable.awk $PROJECT/$MANIFEST`
275log "Found debuggable flag: $DEBUGGABLE"
276if [ $? != 0 -o "$DEBUGGABLE" != "true" ] ; then
277 echo "ERROR: Package $PACKAGE_NAME is not debuggable ! Please fix your manifest,"
278 echo " rebuild your application and re-install it to fix this."
279 exit 1
280fi
281
282APP_ABIS=`get_build_var APP_ABI`
283log "ABIs targetted by application: $APP_ABIS"
284
285# Check the ADB command, and that we can connect to the device/emulator
286ADB_TEST=`$ADB_CMD shell ls`
287if [ $? != 0 ] ; then
288 echo "ERROR: Could not connect to device or emulator!"
289 echo " Please check that an emulator is running or a device is connected"
290 echo " through USB to this machine. You can use the -e, -d and -s <serial>"
291 echo " in case of multiple ones."
292 exit 1
293fi
294
295# Get the target device's supported ABI(s)
296# And check that they are supported by the application
297#
298COMPAT_ABI=none
299CPU_ABI=`$ADB_CMD shell getprop ro.product.cpu.abi | sed -e 's!\\r!!g'`
300echo "$APP_ABIS" | grep -q -F "$CPU_ABI"
301if [ $? = 0 ] ; then
302 COMPAT_ABI=$CPU_ABI
303fi
304
305CPU_ABI2=`$ADB_CMD shell getprop ro.product.cpu.abi2 | sed -e 's!\\r!!g'`
306if [ -z "$CPU_ABI2" ] ; then
307 log "Device CPU ABI: $CPU_ABI"
308else
309 log "Device CPU ABIs: $CPU_ABI $CPU_ABI2"
310 echo "$APP_ABIS" | grep -q -F "$CPU_ABI2"
311 if [ $? = 0 ] ; then
312 COMPAT_ABI=$CPU_ABI2
313 fi
314fi
315if [ "$COMPAT_ABI" = none ] ; then
316 echo "ERROR: The device does not support the application's targetted CPU ABIs!"
317 if [ "$CPU_ABI2" = "$CPU_ABI" ] ; then
318 CPU_ABI2=
319 fi
320 echo " Device supports: $CPU_ABI $CPU_ABI2"
321 echo " Package supports: $APP_ABIS"
322 exit 1
323fi
324log "Compatible device ABI: $COMPAT_ABI"
325
326# Get information from the build system
327GDBSETUP_INIT=`get_build_var_for_abi NDK_APP_GDBSETUP $COMPAT_ABI`
328log "Using gdb setup init: $GDBSETUP_INIT"
329
330TOOLCHAIN_PREFIX=`get_build_var_for_abi TOOLCHAIN_PREFIX $COMPAT_ABI`
331log "Using toolchain prefix: $TOOLCHAIN_PREFIX"
332
333APP_OUT=`get_build_var_for_abi TARGET_OUT $COMPAT_ABI`
334log "Using app out directory: $APP_OUT"
335
336# Find the <dataDir> of the package on the device
337DATA_DIR=`$ADB_CMD shell run-as $PACKAGE_NAME /system/bin/sh -c pwd`
338# mmm, a rogue \r at the end, get rid of it.
339DATA_DIR=`echo "$DATA_DIR" | sed -e 's!\\r!!g'`
340log "Found data directory: '$DATA_DIR'"
341if [ $? != 0 ] ; then
342 echo "ERROR: Could not extract package's data directory. Are you sure that"
343 echo " your installed application is debuggable ?"
344 exit 1
345fi
346
347# Find the PID of the application being run
348PID=`$ADB_CMD shell ps | $AWK_CMD -f $AWK_SCRIPTS/extract-package-pid.awk -v PACKAGE=$PACKAGE_NAME`
349log "Found running PID: $PID"
350if [ $? != 0 -o "$PID" = "0" ] ; then
351 echo "ERROR: Could not extract PID of application on device/emulator."
352 echo " Are you sure the application is already started ?"
353 exit 1
354fi
355
356# Check that there is no other instance of gdbserver running
357GDBSERVER_PS=`$ADB_CMD shell ps | grep lib/gdbserver`
358if [ -n "$GDBSERVER_PS" ] ; then
359 if [ "$OPTION_FORCE" = "no" ] ; then
360 echo "ERROR: Another debug session running, Use --force to kill it."
361 exit 1
362 fi
363 log "Killing existing debugging session"
364 GDBSERVER_PID=`echo $GDBSERVER_PS | $AWK_CMD -f $AWK_SCRIPTS/extract-package-pid.awk -v PACKAGE=lib/gdbserver`
365 if [ $GDBSERVER_PID != 0 ] ; then
366 run $ADB_CMD shell kill -9 $GDBSERVER_PID
367 fi
368fi
369
370# Launch gdbserver now
371DEBUG_SOCKET=debug-socket
372run $ADB_CMD shell run-as $PACKAGE_NAME lib/gdbserver +$DEBUG_SOCKET --attach $PID &
373if [ $? != 0 ] ; then
374 echo "ERROR: Could not launch gdbserver on the device ?"
375 exit 1
376fi
377log "Launched gdbserver succesfully."
378
379# Setup network redirection
380log "Setup network redirection"
381run $ADB_CMD forward tcp:$DEBUG_PORT localfilesystem:$DATA_DIR/$DEBUG_SOCKET
382if [ $? != 0 ] ; then
383 echo "ERROR: Could not setup network redirection to gdbserver ?"
384 echo " Maybe using --port=<port> to use a different TCP port might help ?"
385 exit 1
386fi
387
388# Get the app_server binary from the device
389APP_PROCESS=$APP_OUT/app_process
390run adb pull /system/bin/app_process $APP_PROCESS
391log "Pulled $APP_BINARY from device/emulator."
392
393# Now launch the appropriate gdb client with the right init commands
394#
395GDBCLIENT=${TOOLCHAIN_PREFIX}gdb
396GDBSETUP=$APP_OUT/gdb.setup
397cp -f $GDBSETUP_INIT $GDBSETUP
398echo "target remote :$DEBUG_PORT" >> $GDBSETUP
399if [ -n "$OPTION_EXEC" ] ; then
400 cat $OPTION_EXEC >> $GDBSETUP
401fi
402$GDBCLIENT -x $GDBSETUP -e $APP_PROCESS