Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1087)

Side by Side Diff: build/android/adb_gdb

Issue 11187027: Android: Add new debugging scripts (adb_gdb_xxx) (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | build/android/adb_gdb_chromium_test_shell » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/bin/bash
2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 #
7
8 # A generic script used to attach to a running Chromium process and
9 # debug it. Most users should not use this directly, but one of the
10 # wrapper scripts like adb_gdb_content_shell, or adb_gdb_drt
11 #
12 # Use --help to print full usage instructions.
13 #
14
15 PROGNAME=$(basename "$0")
16 PROGDIR=$(dirname "$0")
17
18 # Location of Chromium-top-level sources.
19 CHROMIUM_SRC=$(cd "$PROGDIR"/../.. && pwd 2>/dev/null)
20
21 TMPDIR=
22 GDBSERVER_PIDFILE=
23 TARGET_GDBSERVER=
24
25 clean_exit () {
26 if [ "$TMPDIR" ]; then
27 GDBSERVER_PID=$(cat $GDBSERVER_PIDFILE 2>/dev/null)
28 if [ "$GDBSERVER_PID" ]; then
29 log "Killing background gdbserver process: $GDBSERVER_PID"
30 kill -9 $GDBSERVER_PID >/dev/null 2>&1
31 fi
32 if [ "$TARGET_GDBSERVER" ]; then
33 log "Removing target gdbserver binary: $TARGET_GDBSERVER."
34 "$ADB" shell rm "$TARGET_GDBSERVER" >/dev/null 2>&1
35 fi
36 log "Cleaning up: $TMPDIR"
37 rm -rf "$TMPDIR"
38 fi
39 exit $1
40 }
41
42 # Ensure clean exit on Ctrl-C.
43 trap "clean_exit 1" INT
44
45 panic () {
46 echo "ERROR: $@" >&2
47 clean_exit 1
48 }
49
50 fail_panic () {
51 if [ $? != 0 ]; then panic "$@"; fi
52 }
53
54 log () {
55 if [ "$VERBOSE" -gt 0 ]; then
56 echo "$@"
57 fi
58 }
59
60 DEFAULT_PULL_LIBS_DIR=/tmp/$USER-adb-gdb-libs
61
62 # NOTE: Allow wrapper scripts to set various default through ADB_GDB_XXX
63 # environment variables. This is only for cosmetic reasons, i.e. to
64 # display proper
65
66 # Allow wrapper scripts to set the default activity through
67 # the ADB_GDB_ACTIVITY variable. Users are still able to change the
68 # final activity name through --activity=<name> option.
69 #
70 # This is only for cosmetic reasons, i.e. to display the proper default
71 # in the --help output.
72 #
73 DEFAULT_ACTIVITY=${ADB_GDB_ACTIVITY:-".Main"}
74
75 # Allow wrapper scripts to set the program name through ADB_GDB_PROGNAME
76 PROGNAME=${ADB_GDB_PROGNAME:-$(basename "$0")}
77
78 ACTIVITY=$DEFAULT_ACTIVITY
79 ADB=
80 ANNOTATE=
81 # Note: Ignore BUILDTYPE variable, because the Ninja build doesn't use it.
82 BUILDTYPE=
83 FORCE=
84 GDBINIT=
85 GDBSERVER=
86 HELP=
87 NDK_DIR=
88 NO_PULL_LIBS=
89 PACKAGE_NAME=
90 PID=
91 PROGRAM_NAME="activity"
92 PULL_LIBS=
93 PULL_LIBS_DIR=
94 SANDBOXED=
95 SANDBOXED_INDEX=
96 START=
97 SYMBOL_DIR=
98 TARGET_ARCH=
99 TOOLCHAIN=
100 VERBOSE=0
101
102 for opt; do
103 optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
104 case $opt in
105 --adb=*)
106 ADB=$optarg
107 ;;
108 --activity=*)
109 ACTIVITY=$optarg
110 ;;
111 --annotate=3)
112 ANNOTATE=$optarg
113 ;;
114 --force)
115 FORCE=true
116 ;;
117 --gdbserver=*)
118 GDBSERVER=$optarg
119 ;;
120 --help|-h|-?)
121 HELP=true
122 ;;
123 --ndk-dir=*)
124 NDK_DIR=$optarg
125 ;;
126 --no-pull-libs)
127 NO_PULL_LIBS=true
128 ;;
129 --package-name=*)
130 PACKAGE_NAME=$optarg
131 ;;
132 --pid=*)
133 PID=$optarg
134 ;;
135 --program-name=*)
136 PROGRAM_NAME=$optarg
137 ;;
138 --pull-libs)
139 PULL_LIBS=true
140 ;;
141 --pull-libs-dir=*)
142 PULL_LIBS_DIR=$optarg
143 ;;
144 --sandboxed)
145 SANDBOXED=true
146 ;;
147 --sandboxed=*)
148 SANDBOXED=true
149 SANDBOXED_INDEX=$optarg
150 ;;
151 --script=*)
152 GDBINIT=$optarg
153 ;;
154 --start)
155 START=true
156 ;;
157 --symbol-dir=*)
158 SYMBOL_DIR=$optarg
159 ;;
160 --target-arch=*)
161 TARGET_ARCH=$optarg
162 ;;
163 --toolchain=*)
164 TOOLCHAIN=$optarg
165 ;;
166 --verbose)
167 VERBOSE=$(( $VERBOSE + 1 ))
168 ;;
169 --debug)
170 BUILDTYPE=Debug
171 ;;
172 --release)
173 BUILDTYPE=Release
174 ;;
175 -*)
176 panic "Unknown option $OPT, see --help." >&2
177 ;;
178 *)
179 if [ "$PACKAGE_NAME" ]; then
180 panic "You can only provide a single package name as argument!\
181 See --help."
182 fi
183 PACKAGE_NAME=$opt
184 ;;
185 esac
186 done
187
188 print_help_options () {
189 cat <<EOF
190 EOF
191 }
192
193 if [ "$HELP" ]; then
194 if [ "$ADB_GDB_PROGNAME" ]; then
195 # Assume wrapper scripts all provide a default package name.
196 cat <<EOF
197 Usage: $PROGNAME [options]
198
199 Attach gdb to a running Android $PROGRAM_NAME process.
200 EOF
201 else
202 # Assume this is a direct call to adb_gdb
203 cat <<EOF
204 Usage: $PROGNAME [options] [<package-name>]
205
206 Attach gdb to a running Android $PROGRAM_NAME process.
207
208 If provided, <package-name> must be the name of the Android application's
209 package name to be debugged. You can also use --package-name=<name> to
210 specify it.
211 EOF
212 fi
213
214 cat <<EOF
215
216 This script is used to debug a running $PROGRAM_NAME process.
217 This can be a regular Android application process, or a sandboxed
218 service, if you use the --sandboxed or --sandboxed=<num> option.
219
220 This script needs several things to work properly. It will try to pick
221 them up automatically for you though:
222
223 - target gdbserver binary
224 - host gdb client (e.g. arm-linux-androideabi-gdb)
225 - directory with symbolic version of $PROGRAM_NAME's shared libraries.
226
227 If you have sourced Chromium's build/android/envsetup.sh, this script will
228 find all of them automatically. This is the recommended way to use it.
229
230 Otherwise, if you have ANDROID_NDK_ROOT defined in your environment,
231 the script will use it to find the gdb and gdbserver binaries. You can
232 also use --ndk-dir=<path> to specify an alternative NDK installation
233 directory.
234
235 The script tries to find the most recent version of the debug version of
236 shared libraries under one of the following directories:
237
238 \$CHROMIUM_SRC/out/Release/lib/ (used by Ninja builds)
239 \$CHROMIUM_SRC/out/Debug/lib/ (used by Ninja builds)
240 \$CHROMIUM_SRC/out/Release/lib.target/ (used by Make builds)
241 \$CHROMIUM_SRC/out/Debug/lib.target/ (used by Make builds)
242
243 You can restrict this search by using --release or --debug to specify the
244 build type, or simply use --symbol-dir=<path> to specify the file manually.
245
246 The script tries to extract the target architecture from your GYP_DEFINES,
247 but if this fails, will default to 'arm'. Use --target-arch=<name> to force
248 its value.
249
250 Otherwise, the script will complain, but you can use the --gdbserver,
251 --gdb and --symbol-lib options to specify everything manually.
252
253 An alternative to --gdb=<file> is to use --toollchain=<path> to specify
254 the path to the host target-specific cross-toolchain.
255
256 You will also need the 'adb' tool in your path. Otherwise, use the --adb
257 option. The script will complain if there is more than one device connected
258 and ANDROID_SERIAL is not defined.
259
260 The first time you use it on a device, the script will pull many system
261 libraries required by the process into a temporary directory. This
262 is done to strongly improve the debugging experience, like allowing
263 readable thread stacks and more. The libraries are copied to the following
264 directory by default:
265
266 $DEFAULT_PULL_LIBS_DIR/
267
268 But you can use the --pull-libs-dir=<path> option to specify an
269 alternative. The script can detect when you change the connected device,
270 and will re-pull the libraries only in this case. You can however force it
271 with the --pull-libs option.
272
273 Any local .gdbinit script will be ignored, but it is possible to pass a
274 gdb command script with the --script=<file> option. Note that its commands
275 will be passed to gdb after the remote connection and library symbol
276 loading have completed.
277
278 Valid options:
279 --help|-h|-? Print this message.
280 --verbose Increase verbosity.
281
282 --sandboxed Debug first sandboxed process we find.
283 --sandboxed=<num> Debug specific sandboxed process.
284 --symbol-dir=<path> Specify directory with symbol shared libraries.
285 --package-name=<name> Specify package name (alternative to 1st argument).
286 --program-name=<name> Specify program name (cosmetic only).
287 --pid=<pid> Specify application process pid.
288 --force Kill any previous debugging session, if any.
289 --start Start package's activity on device.
290 --activity=<name> Activity name for --start [$DEFAULT_ACTIVITY].
291 --annotate=<num> Enable gdb annotation.
292 --script=<file> Specify extra GDB init script.
293
294 --gdbserver=<file> Specify targer gdbserver binary.
295 --gdb=<program> Specify host gdb client binary.
296 --target-arch=<name> Specify NDK target arch.
297 --adb=<program> Specify host ADB binary.
298
299 --pull-libs Force system libraries extraction.
300 --no-pull-libs Do not extract any system library.
301 --libs-dir=<path> Specify system libraries extraction directory.
302
303 --debug Use libraries under out/Debug.
304 --release Use libraries under out/Release.
305
306 EOF
307 exit 0
308 fi
309
310 if [ -z "$PACKAGE_NAME" ]; then
311 panic "Please specify a package name on the command line. See --help."
312 fi
313
314 if [ -z "$NDK_DIR" ]; then
315 if [ -z "$ANDROID_NDK_ROOT" ]; then
316 panic "Can't find NDK directory, please source \
317 build/android/envsetup.sh!"
318 fi
319 else
320 if [ ! -d "$NDK_DIR" ]; then
321 panic "Invalid directory: $NDK_DIR"
322 fi
323 if [ ! -f "$NDK_DIR/ndk-build" ]; then
324 panic "Not a valid NDK directory: $NDK_DIR"
325 fi
326 ANDROID_NDK_ROOT=$NDK_DIR
327 fi
328
329 if [ "$GDBINIT" -a ! -f "$GDBINIT" ]; then
330 panic "Unknown --script file: $GDBINIT"
331 fi
332
333 # Find the target architecture from our $GYP_DEFINES
334 # This returns an NDK-compatible architecture name.
335 # out: NDK Architecture name, or empty string.
336 get_gyp_target_arch () {
337 local ARCH=$(echo $GYP_DEFINES | tr ' ' '\n' | grep '^target_arch=' |\
338 cut -d= -f2)
339 case $ARCH in
340 ia32|i?86|x86) echo "x86";;
341 mips|arm) echo "$ARCH";;
342 *) echo "";
343 esac
344 }
345
346 if [ -z "$TARGET_ARCH" ]; then
347 TARGET_ARCH=$(get_gyp_target_arch)
348 if [ -z "$TARGET_ARCH" ]; then
349 TARGET_ARCH=arm
350 fi
351 else
352 # Nit: accept Chromium's 'ia32' as a valid target architecture. This
353 # script prefers the NDK 'x86' name instead because it uses it to find
354 # NDK-specific files (host gdb) with it.
355 if [ "$TARGET_ARCH" = "ia32" ]; then
356 TARGET_ARCH=x86
357 log "Auto-config: --arch=$TARGET_ARCH (equivalent to ia32)"
358 fi
359 fi
360
361 # Detect the NDK system tag, i.e. the name used to identify the host.
362 # out: NDK system tag (e.g. 'linux-x86').
363 get_ndk_host_tag () {
364 if [ -z "$NDK_HOST_TAG" ]; then
365 case $(uname -s) in
366 Linux) NDK_HOST_TAG=linux-x86;;
367 Darwin) NDK_HOST_TAG=darwin-x86;;
368 *) panic "You can't run this script on this system: $uname -a";;
369 esac
370 fi
371 echo "$NDK_HOST_TAG"
372 }
373
374 # Convert an NDK architecture name into a GNU configure triplet.
375 # $1: NDK architecture name (e.g. 'arm')
376 # Out: Android GNU configure triplet (e.g. 'arm-linux-androideabi')
377 get_arch_gnu_config () {
378 case $1 in
379 arm)
380 echo "arm-linux-androideabi"
381 ;;
382 x86)
383 echo "i686-linux-android"
384 ;;
385 mips)
386 echo "mipsel-linux-android"
387 ;;
388 *)
389 echo "$ARCH-linux-android"
390 ;;
391 esac
392 }
393
394 # Convert an NDK architecture name into a toolchain name prefix
395 # $1: NDK architecture name (e.g. 'arm')
396 # Out: NDK toolchain name prefix (e.g. 'arm-linux-androideabi')
397 get_arch_toolchain_prefix () {
398 # Return the configure triplet, except for x86!
399 if [ "$1" = "x86" ]; then
400 echo "$1"
401 else
402 get_arch_gnu_config $1
403 fi
404 }
405
406 # Find a NDK toolchain prebuilt file or sub-directory.
407 # This will probe the various arch-specific toolchain directories
408 # in the NDK for the needed file.
409 # $1: NDK install path
410 # $2: NDK architecture name
411 # $3: prebuilt sub-path to look for.
412 # Out: file path, or empty if none is found.
413 get_ndk_toolchain_prebuilt () {
414 local NDK_DIR="${1%/}"
415 local ARCH="$2"
416 local SUBPATH="$3"
417 local NAME="$(get_arch_toolchain_prefix $ARCH)"
418 local FILE TARGET
419 FILE=$NDK_DIR/toolchains/$NAME-4.6/prebuilt/$SUBPATH
420 if [ ! -f "$FILE" ]; then
421 FILE=$NDK_DIR/toolchains/$NAME-4.4.3/prebuilt/$SUBPATH
422 if [ ! -f "$FILE" ]; then
423 FILE=
424 fi
425 fi
426 echo "$FILE"
427 }
428
429 # Find the path to an NDK's toolchain full prefix for a given architecture
430 # $1: NDK install path
431 # $2: NDK architecture name
432 # Out: install path + binary prefix (e.g.
433 # ".../path/to/bin/arm-linux-androideabi-")
434 get_ndk_toolchain_fullprefix () {
435 local NDK_DIR="$1"
436 local ARCH="$2"
437 local TARGET NAME HOST GCC CONFIG
438
439 # NOTE: This will need to be updated if the NDK changes the names or moves
440 # the location of its prebuilt toolchains.
441 #
442 GCC=
443 HOST=$(get_ndk_host_tag)
444 CONFIG=$(get_arch_gnu_config $ARCH)
445 GCC=$(get_ndk_toolchain_prebuilt \
446 "$NDK_DIR" "$ARCH" "$HOST/bin/$CONFIG-gcc")
447 if [ ! -f "$GCC" -a "$ARCH" = "x86" ]; then
448 # Special case, the x86 toolchain used to be incorrectly
449 # named i686-android-linux-gcc!
450 GCC=$(get_ndk_toolchain_prebuilt \
451 "$NDK_DIR" "$ARCH" "$HOST/bin/i686-android-linux-gcc")
452 fi
453 if [ -z "$GCC" ]; then
454 panic "Cannot find Android NDK toolchain for '$ARCH' architecture. \
455 Please verify your NDK installation!"
456 fi
457 echo "${GCC%%gcc}"
458 }
459
460 # $1: NDK install path
461 # $2: target architecture.
462 get_ndk_gdbserver () {
463 local NDK_DIR="$1"
464 local ARCH=$2
465 local HOST=$(get_ndk_host_tag)
466 local BINARY
467
468 # The location has moved after NDK r8
469 BINARY=$NDK_DIR/prebuilt/android-$ARCH/gdbserver/gdbserver
470 if [ ! -f "$BINARY" ]; then
471 BINARY=$(get_ndk_toolchain_prebuilt "$NDK_DIR" "$ARCH" gdbserver)
472 fi
473 echo "$BINARY"
474 }
475
476 # Check/probe the path to the Android toolchain installation. Always
477 # use the NDK versions of gdb and gdbserver. They must match to avoid
478 # issues when both binaries do not speak the same wire protocol.
479 #
480 if [ -z "$TOOLCHAIN" ]; then
481 ANDROID_TOOLCHAIN=$(get_ndk_toolchain_fullprefix \
482 "$ANDROID_NDK_ROOT" "$TARGET_ARCH")
483 ANDROID_TOOLCHAIN=$(dirname "$ANDROID_TOOLCHAIN")
484 log "Auto-config: --toolchain=$ANDROID_TOOLCHAIN"
485 else
486 # Be flexible, allow one to specify either the install path or the bin
487 # sub-directory in --toolchain:
488 #
489 if [ -d "$TOOLCHAIN/bin" ]; then
490 TOOLCHAIN=$TOOLCHAIN/bin
491 fi
492 ANDROID_TOOLCHAIN=$TOOLCHAIN
493 fi
494
495 # Cosmetic: Remove trailing directory separator.
496 ANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN%/}
497
498 # Find host GDB client binary
499 GDB=$(which $ANDROID_TOOLCHAIN/*-gdb 2>/dev/null | head -1)
500 if [ -z "$GDB" ]; then
501 panic "Can't find Android gdb client in your path, check your \
502 --toolchain path."
503 fi
504 log "Host gdb client: $GDB"
505
506 # Find gdbserver binary, we will later push it to /data/local/tmp
507 # This ensures that both gdbserver and $GDB talk the same binary protocol,
508 # otherwise weird problems will appear.
509 #
510 if [ -z "$GDBSERVER" ]; then
511 GDBSERVER=$(get_ndk_gdbserver "$ANDROID_NDK_ROOT" "$TARGET_ARCH")
512 if [ -z "$GDBSERVER" ]; then
513 panic "Can't find NDK gdbserver binary. use --gdbserver to specify \
514 valid one!"
515 fi
516 log "Auto-config: --gdbserver=$GDBSERVER"
517 fi
518
519
520
521 # Check that ADB is in our path
522 if [ -z "$ADB" ]; then
523 ADB=$(which adb 2>/dev/null)
524 if [ -z "$ADB" ]; then
525 panic "Can't find 'adb' tool in your path. Install it or use \
526 --adb=<file>"
527 fi
528 log "Auto-config: --adb=$ADB"
529 fi
530
531 # Check that it works minimally
532 ADB_VERSION=$($ADB version 2>/dev/null)
533 echo "$ADB_VERSION" | fgrep -q -e "Android Debug Bridge"
534 if [ $? != 0 ]; then
535 panic "Your 'adb' tool seems invalid, use --adb=<file> to specify a \
536 different one: $ADB"
537 fi
538
539 # If there are more than one device connected, and ANDROID_SERIAL is not
540 # defined, print an error message.
541 NUM_DEVICES_PLUS2=$($ADB devices 2>/dev/null | wc -l)
542 if [ "$NUM_DEVICES_PLUS2" -lt 3 -a -z "$ANDROID_SERIAL" ]; then
543 echo "ERROR: There is more than one Android device connected to ADB."
544 echo "Please define ANDROID_SERIAL to specify which one to use."
545 exit 1
546 fi
547
548 # A unique ID for this script's session. This needs to be the same in all
549 # sub-shell commands we're going to launch, so take the PID of the launcher
550 # process.
551 TMP_ID=$$
552
553 # Temporary directory, will get cleaned up on exit.
554 TMPDIR=/tmp/$USER-adb-gdb-tmp-$TMP_ID
555 mkdir -p "$TMPDIR" && rm -rf "$TMPDIR"/*
556
557 GDBSERVER_PIDFILE="$TMPDIR"/gdbserver-$TMP_ID.pid
558
559 # Run a command through adb shell, strip the extra \r from the output
560 # and return the correct status code to detect failures. This assumes
561 # that the adb shell command prints a final \n to stdout.
562 # $1+: command to run
563 # Out: command's stdout
564 # Return: command's status
565 # Note: the command's stderr is lost
566 adb_shell () {
567 local TMPOUT="$(mktemp)"
568 local LASTLINE RET
569 local ADB=${ADB:-adb}
570
571 # The weird sed rule is to strip the final \r on each output line
572 # Since 'adb shell' never returns the command's proper exit/status code,
573 # we force it to print it as '%%<status>' in the temporary output file,
574 # which we will later strip from it.
575 $ADB shell $@ ";" echo "%%\$?" 2>/dev/null | \
576 sed -e 's![[:cntrl:]]!!g' > $TMPOUT
577 # Get last line in log, which contains the exit code from the command
578 LASTLINE=$(sed -e '$!d' $TMPOUT)
579 # Extract the status code from the end of the line, which must
580 # be '%%<code>'.
581 RET=$(echo "$LASTLINE" | \
582 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,RSTART+2); } }')
583 # Remove the status code from the last line. Note that this may result
584 # in an empty line.
585 LASTLINE=$(echo "$LASTLINE" | \
586 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,1,RSTART-1); } }')
587 # The output itself: all lines except the status code.
588 sed -e '$d' $TMPOUT && printf "%s" "$LASTLINE"
589 # Remove temp file.
590 rm -f $TMPOUT
591 # Exit with the appropriate status.
592 return $RET
593 }
594
595 # If --force is specified, try to kill any gdbserver process started by the
596 # same user on the device. Normally, these are killed automatically by the
597 # script on exit, but there are a few corner cases where this would still
598 # be needed.
599 if [ "$FORCE" ]; then
600 GDBSERVER_PIDS=$(adb_shell ps | awk '$9 ~ /gdbserver/ { print $2; }')
601 for GDB_PID in $GDBSERVER_PIDS; do
602 log "Killing previous gdbserver (PID=$GDB_PID)"
603 adb_shell kill -9 $GDB_PID
604 done
605 fi
606
607 if [ "$START" ]; then
608 log "Starting $PROGRAM_NAME on device."
609 adb_shell am start -n $PACKAGE_NAME/$ACTIVITY 2>/dev/null
610 adb_shell ps | grep -q $PACKAGE_NAME
611 fail_panic "Could not start $PROGRAM_NAME on device. Are you sure the \
612 package is installed?"
613 fi
614
615 # Return the timestamp of a given time, as number of seconds since epoch.
616 # $1: file path
617 # Out: file timestamp
618 get_file_timestamp () {
619 stat -c %Y "$1" 2>/dev/null
620 }
621
622 # Detect the build type and symbol directory. This is done by finding
623 # the most recent sub-directory containing debug shared libraries under
624 # $CHROMIUM_SRC/out/
625 #
626 # $1: $BUILDTYPE value, can be empty
627 # Out: nothing, but this sets SYMBOL_DIR
628 #
629 detect_symbol_dir () {
630 local SUBDIRS SUBDIR LIST DIR DIR_LIBS TSTAMP
631 # Note: Ninja places debug libraries under out/$BUILDTYPE/lib/, while
632 # Make places then under out/$BUILDTYPE/lib.target.
633 if [ "$1" ]; then
634 SUBDIRS="$1/lib $1/lib.target"
635 else
636 SUBDIRS="Release/lib Debug/lib Release/lib.target Debug/lib.target"
637 fi
638 LIST=$TMPDIR/scan-subdirs-$$.txt
639 printf "" > "$LIST"
640 for SUBDIR in $SUBDIRS; do
641 DIR=$CHROMIUM_SRC/out/$SUBDIR
642 if [ -d "$DIR" ]; then
643 # Ignore build directories that don't contain symbol versions
644 # of the shared libraries.
645 DIR_LIBS=$(ls "$DIR"/lib*.so 2>/dev/null)
646 if [ -z "$DIR_LIBS" ]; then
647 echo "No shared libs: $DIR"
648 continue
649 fi
650 TSTAMP=$(get_file_timestamp "$DIR")
651 printf "%s %s\n" "$TSTAMP" "$SUBDIR" >> "$LIST"
652 fi
653 done
654 SUBDIR=$(cat $LIST | sort -r | head -1 | cut -d" " -f2)
655 rm -f "$LIST"
656
657 if [ -z "$SUBDIR" ]; then
658 if [ -z "$1" ]; then
659 panic "Could not find any build directory under \
660 $CHROMIUM_SRC/out. Please build the program first!"
661 else
662 panic "Could not find any $1 directory under \
663 $CHROMIUM_SRC/out. Check your build type!"
664 fi
665 fi
666
667 SYMBOL_DIR=$CHROMIUM_SRC/out/$SUBDIR
668 log "Auto-config: --symbol-dir=$SYMBOL_DIR"
669 }
670
671 if [ -z "$SYMBOL_DIR" ]; then
672 detect_symbol_dir "$BUILDTYPE"
673 fi
674
675 # Allow several concurrent debugging sessions
676 TARGET_GDBSERVER=/data/local/tmp/gdbserver-adb-gdb-$TMP_ID
677
678 # Return the build fingerprint contained in a build.prop file.
679 # $1: path to build.prop file
680 get_build_fingerprint_from () {
681 cat "$1" | grep -e '^ro.build.fingerprint=' | cut -d= -f2
682 }
683
684
685 ORG_PULL_LIBS_DIR=$PULL_LIBS_DIR
686 PULL_LIBS_DIR=${PULL_LIBS_DIR:-$DEFAULT_PULL_LIBS_DIR}
687
688 HOST_FINGERPRINT=
689 DEVICE_FINGERPRINT=$(adb_shell getprop ro.build.fingerprint)
690 log "Device build fingerprint: $DEVICE_FINGERPRINT"
691
692 # If --pull-libs-dir is not specified, and this is a platform build, look
693 # if we can use the symbolic libraries under $ANDROID_PRODUCT_OUT/symbols/
694 # directly, if the build fingerprint matches the device.
695 if [ -z "$ORG_PULL_LIBS_DIR" -a \
696 "$ANDROID_PRODUCT_OUT" -a \
697 -f "$ANDROID_PRODUCT_OUT/system/build.prop" ]; then
698 ANDROID_FINGERPRINT=$(get_build_fingerprint_from \
699 "$ANDROID_PRODUCT_OUT"/system/build.prop)
700 log "Android build fingerprint: $ANDROID_FINGERPRINT"
701 if [ "$ANDROID_FINGERPRINT" = "$DEVICE_FINGERPRINT" ]; then
702 log "Perfect match!"
703 PULL_LIBS_DIR=$ANDROID_PRODUCT_OUT/symbols
704 HOST_FINGERPRINT=$ANDROID_FINGERPRINT
705 if [ "$PULL_LIBS" ]; then
706 log "Ignoring --pull-libs since the device and platform build \
707 fingerprints match."
708 NO_PULL_LIBS=true
709 fi
710 fi
711 fi
712
713 # If neither --pull-libs an --no-pull-libs were specified, check the build
714 # fingerprints of the device, and the cached system libraries on the host.
715 #
716 if [ -z "$NO_PULL_LIBS" -a -z "$PULL_LIBS" ]; then
717 if [ ! -f "$PULL_LIBS_DIR/build.prop" ]; then
718 log "Auto-config: --pull-libs (no cached libraries)"
719 PULL_LIBS=true
720 else
721 HOST_FINGERPRINT=$(get_build_fingerprint_from "$PULL_LIBS_DIR/build.prop")
722 log "Host build fingerprint: $HOST_FINGERPRINT"
723 if [ "$HOST_FINGERPRINT" == "$DEVICE_FINGERPRINT" ]; then
724 log "Auto-config: --no-pull-libs (fingerprint match)"
725 NO_PULL_LIBS=true
726 else
727 log "Auto-config: --pull-libs (fingerprint mismatch)"
728 PULL_LIBS=true
729 fi
730 fi
731 fi
732
733 # Extract the system libraries from the device if necessary.
734 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
735 echo "Extracting system libraries into: $PULL_LIBS_DIR"
736 fi
737
738 mkdir -p "$PULL_LIBS_DIR"
739 fail_panic "Can't create --libs-dir directory: $PULL_LIBS_DIR"
740
741 # If requested, work for M-x gdb. The gdb indirections make it
742 # difficult to pass --annotate=3 to the gdb binary itself.
743 GDB_ARGS=
744 if [ "$ANNOTATE" ]; then
745 GDB_ARGS=$GDB_ARGS" --annotate=$ANNOTATE"
746 fi
747
748 # Get the PID from the first argument or else find the PID of the
749 # browser process.
750 if [ -z "$PID" ]; then
751 PROCESSNAME=$PACKAGE_NAME
752 if [ "$SANDBOXED_INDEX" ]; then
753 PROCESSNAME=$PROCESSNAME:sandboxed_process$SANDBOXED_INDEX
754 elif [ "$SANDBOXED" ]; then
755 PROCESSNAME=$PROCESSNAME:sandboxed_process
756 PID=$(adb_shell ps | \
757 awk '$9 ~ /^'$PROCESSNAME'/ { print $2; }' | head -1)
758 fi
759 if [ -z "$PID" ]; then
760 PID=$(adb_shell ps | \
761 awk '$9 == "'$PROCESSNAME'" { print $2; }' | head -1)
762 fi
763 if [ -z "$PID" ]; then
764 if [ "$START" ]; then
765 panic "Can't find application process PID, did it crash?"
766 else
767 panic "Can't find application process PID, are you sure it is \
768 running? Try using --start."
769 fi
770 fi
771 log "Found process PID: $PID"
772 elif [ "$SANDBOXED" ]; then
773 echo "WARNING: --sandboxed option ignored due to use of --pid."
774 fi
775
776 # Determine if 'adb shell' runs as root or not.
777 # If so, we can launch gdbserver directly, otherwise, we have to
778 # use run-as $PACKAGE_NAME ..., which requires the package to be debuggable.
779 #
780 SHELL_UID=$(adb shell cat /proc/self/status | \
781 awk '$1 == "Uid:" { print $2; }')
782 log "Shell UID: $SHELL_UID"
783 COMMAND_PREFIX=
784 if [ "$SHELL_UID" != 0 -o -n "$NO_ROOT" ]; then
785 log "Using run-as $PACKAGE_NAME to run without root."
786 COMMAND_PREFIX="run-as $PACKAGE_NAME"
787 fi
788
789 # Pull device's system libraries that are mapped by our process.
790 # Pulling all system libraries is too long, so determine which ones
791 # we need by looking at /proc/$PID/maps instead
792 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
793 echo "Extracting system libraries into: $PULL_LIBS_DIR"
794 SYSTEM_LIBS=$(adb_shell $COMMAND_PREFIX cat /proc/$PID/maps | \
795 awk '$6 ~ /\/system\/.*\.so$/ { print $6; }' | sort -u)
796 for SYSLIB in /system/bin/linker $SYSTEM_LIBS; do
797 echo "Pulling from device: $SYSLIB"
798 DST_FILE=$PULL_LIBS_DIR$SYSLIB
799 DST_DIR=$(dirname "$DST_FILE")
800 mkdir -p "$DST_DIR" && adb pull $SYSLIB "$DST_FILE" 2>/dev/null
801 fail_panic "Could not pull $SYSLIB from device !?"
802 done
803 echo "Pulling device build.prop"
804 adb pull /system/build.prop $PULL_LIBS_DIR/build.prop
805 fail_panic "Could not pull device build.prop !?"
806 fi
807
808 # Find all the sub-directories of $PULL_LIBS_DIR, up to depth 4
809 # so we can add them to solib-search-path later.
810 SOLIB_DIRS=$(find $PULL_LIBS_DIR -mindepth 1 -maxdepth 4 -type d | \
811 grep -v "^$" | tr '\n' ':')
812
813 # This is a re-implementation of gdbclient, where we use compatible
814 # versions of gdbserver and $GDBNAME to ensure that everything works
815 # properly.
816 #
817
818 # Push gdbserver to the device
819 log "Pushing gdbserver to $TARGET_GDBSERVER"
820 adb push $GDBSERVER $TARGET_GDBSERVER &>/dev/null
821 fail_panic "Could not copy gdbserver to the device!"
822
823 PORT=5039
824 HOST_PORT=$PORT
825 TARGET_PORT=$PORT
826
827 # Pull the app_process binary from the device
828 GDBEXEC=app_process
829 log "Pulling $GDBEXEC from device"
830 adb pull /system/bin/$GDBEXEC "$TMPDIR"/$GDBEXEC &>/dev/null
831 fail_panic "Could not retrieve $GDBEXEC from the device!"
832
833 # Setup network redirection
834 log "Setting network redirection (host:$HOST_PORT -> device:$TARGET_PORT)"
835 adb forward tcp:$HOST_PORT tcp:$TARGET_PORT
836 fail_panic "Could not setup network redirection from \
837 host:localhost:$HOST_PORT to device:localhost:$TARGET_PORT!"
838
839 # Start gdbserver in the background
840 # Note that using run-as requires the package to be debuggable.
841 #
842 # If not, this will fail horribly. The alternative is to run the
843 # program as root, which requires of course root privileges.
844 # Maybe we should add a --root option to enable this?
845 #
846 log "Starting gdbserver in the background:"
847 GDBSERVER_LOG=$TMPDIR/gdbserver-$TMP_ID.log
848 log "adb shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
849 --attach $PID"
850 ("$ADB" shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
851 --attach $PID > $GDBSERVER_LOG 2>&1) &
852 GDBSERVER_PID=$!
853 echo "$GDBSERVER_PID" > $GDBSERVER_PIDFILE
854 log "background job pid: $GDBSERVER_PID"
855
856 # Check that it is still running after a few seconds. If not, this means we
857 # could not properly attach to it
858 sleep 2
859 log "Job control: $(jobs -l)"
860 STATE=$(jobs -l | awk '$2 == "'$GDBSERVER_PID'" { print $3; }')
861 if [ "$STATE" != "Running" ]; then
862 echo "ERROR: GDBServer could not attach to PID $PID!"
863 echo "Failure log (use --verbose for more information):"
864 cat $GDBSERVER_LOG
865 exit 1
866 fi
867
868 # Generate a file containing useful GDB initialization commands
869 readonly COMMANDS=$TMPDIR/gdb.init
870 log "Generating GDB initialization commands file: $COMMANDS"
871 echo -n "" > $COMMANDS
872 echo "file $TMPDIR/$GDBEXEC" >> $COMMANDS
873 echo "directory $CHROMIUM_SRC" >> $COMMANDS
874 echo "set solib-absolute-prefix $PULL_LIBS_DIR" >> $COMMANDS
875 echo "set solib-search-path $SOLIB_DIRS:$PULL_LIBS_DIR:$SYMBOL_DIR" \
876 >> $COMMANDS
877 echo "echo Attaching and reading symbols, this may take a while.." \
878 >> $COMMANDS
879 echo "target remote :$HOST_PORT" >> $COMMANDS
880
881 if [ "$GDBINIT" ]; then
882 cat "$GDBINIT" >> $COMMANDS
883 fi
884
885 if [ "$VERBOSE" -gt 0 ]; then
886 echo "### START $COMMANDS"
887 cat $COMMANDS
888 echo "### END $COMMANDS"
889 fi
890
891 log "Launching gdb client: $GDB $GDBARGS -x $COMMANDS"
892 $GDB $GDBARGS -x $COMMANDS &&
893 rm -f "$GDBSERVER_PIDFILE"
894
895 clean_exit $?
OLDNEW
« no previous file with comments | « no previous file | build/android/adb_gdb_chromium_test_shell » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698