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.
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
12 # Use --help to print full usage instructions.
15 PROGNAME
=$
(basename "$0")
16 PROGDIR
=$
(dirname "$0")
18 # Location of Chromium-top-level sources.
19 CHROMIUM_SRC
=$
(cd "$PROGDIR"/..
/..
>/dev
/null
&& pwd 2>/dev
/null
)
21 # Location of Chromium out/ directory.
22 if [ -z "$CHROMIUM_OUT_DIR" ]; then
31 if [ "$TMPDIR" ]; then
32 GDBSERVER_PID
=$
(cat $GDBSERVER_PIDFILE 2>/dev
/null
)
33 if [ "$GDBSERVER_PID" ]; then
34 log
"Killing background gdbserver process: $GDBSERVER_PID"
35 kill -9 $GDBSERVER_PID >/dev
/null
2>&1
37 if [ "$TARGET_GDBSERVER" ]; then
38 log
"Removing target gdbserver binary: $TARGET_GDBSERVER."
39 "$ADB" shell
rm "$TARGET_GDBSERVER" >/dev
/null
2>&1
41 log
"Cleaning up: $TMPDIR"
48 # Ensure clean exit on Ctrl-C or normal exit.
49 trap "clean_exit 1" INT HUP QUIT TERM
50 trap "clean_exit \$?" EXIT
58 if [ $?
!= 0 ]; then panic
"$@"; fi
62 if [ "$VERBOSE" -gt 0 ]; then
67 DEFAULT_PULL_LIBS_DIR
=/tmp
/$USER-adb-gdb-libs
69 # NOTE: Allow wrapper scripts to set various default through ADB_GDB_XXX
70 # environment variables. This is only for cosmetic reasons, i.e. to
73 # Allow wrapper scripts to set the default activity through
74 # the ADB_GDB_ACTIVITY variable. Users are still able to change the
75 # final activity name through --activity=<name> option.
77 # This is only for cosmetic reasons, i.e. to display the proper default
78 # in the --help output.
80 DEFAULT_ACTIVITY
=${ADB_GDB_ACTIVITY:-".Main"}
82 # Allow wrapper scripts to set the program name through ADB_GDB_PROGNAME
83 PROGNAME
=${ADB_GDB_PROGNAME:-$(basename "$0")}
85 ACTIVITY
=$DEFAULT_ACTIVITY
88 # Note: Ignore BUILDTYPE variable, because the Ninja build doesn't use it.
99 PROGRAM_NAME
="activity"
112 optarg
=$
(expr "x$opt" : 'x[^=]*=\(.*\)')
154 PULL_LIBS_DIR
=$optarg
161 SANDBOXED_INDEX
=$optarg
176 CHROMIUM_OUT_DIR
=$optarg
188 VERBOSE
=$
(( $VERBOSE + 1 ))
197 panic
"Unknown option $OPT, see --help." >&2
200 if [ "$PACKAGE_NAME" ]; then
201 panic
"You can only provide a single package name as argument!\
209 print_help_options
() {
215 if [ "$ADB_GDB_PROGNAME" ]; then
216 # Assume wrapper scripts all provide a default package name.
218 Usage: $PROGNAME [options]
220 Attach gdb to a running Android $PROGRAM_NAME process.
223 # Assume this is a direct call to adb_gdb
225 Usage: $PROGNAME [options] [<package-name>]
227 Attach gdb to a running Android $PROGRAM_NAME process.
229 If provided, <package-name> must be the name of the Android application's
230 package name to be debugged. You can also use --package-name=<name> to
237 This script is used to debug a running $PROGRAM_NAME process.
238 This can be a regular Android application process, or a sandboxed
239 service, if you use the --sandboxed or --sandboxed=<num> option.
241 This script needs several things to work properly. It will try to pick
242 them up automatically for you though:
244 - target gdbserver binary
245 - host gdb client (e.g. arm-linux-androideabi-gdb)
246 - directory with symbolic version of $PROGRAM_NAME's shared libraries.
248 You can also use --ndk-dir=<path> to specify an alternative NDK installation
251 The script tries to find the most recent version of the debug version of
252 shared libraries under one of the following directories:
254 \$CHROMIUM_SRC/<out>/Release/lib/ (used by Ninja builds)
255 \$CHROMIUM_SRC/<out>/Debug/lib/ (used by Ninja builds)
256 \$CHROMIUM_SRC/<out>/Release/lib.target/ (used by Make builds)
257 \$CHROMIUM_SRC/<out>/Debug/lib.target/ (used by Make builds)
259 Where <out> is 'out' by default, unless the --out=<name> option is used or
260 the CHROMIUM_OUT_DIR environment variable is defined.
262 You can restrict this search by using --release or --debug to specify the
263 build type, or simply use --symbol-dir=<path> to specify the file manually.
265 The script tries to extract the target architecture from your GYP_DEFINES,
266 but if this fails, will default to 'arm'. Use --target-arch=<name> to force
269 Otherwise, the script will complain, but you can use the --gdbserver,
270 --gdb and --symbol-lib options to specify everything manually.
272 An alternative to --gdb=<file> is to use --toollchain=<path> to specify
273 the path to the host target-specific cross-toolchain.
275 You will also need the 'adb' tool in your path. Otherwise, use the --adb
276 option. The script will complain if there is more than one device connected
277 and ANDROID_SERIAL is not defined.
279 The first time you use it on a device, the script will pull many system
280 libraries required by the process into a temporary directory. This
281 is done to strongly improve the debugging experience, like allowing
282 readable thread stacks and more. The libraries are copied to the following
283 directory by default:
285 $DEFAULT_PULL_LIBS_DIR/
287 But you can use the --pull-libs-dir=<path> option to specify an
288 alternative. The script can detect when you change the connected device,
289 and will re-pull the libraries only in this case. You can however force it
290 with the --pull-libs option.
292 Any local .gdbinit script will be ignored, but it is possible to pass a
293 gdb command script with the --script=<file> option. Note that its commands
294 will be passed to gdb after the remote connection and library symbol
295 loading have completed.
298 --help|-h|-? Print this message.
299 --verbose Increase verbosity.
301 --sandboxed Debug first sandboxed process we find.
302 --sandboxed=<num> Debug specific sandboxed process.
303 --symbol-dir=<path> Specify directory with symbol shared libraries.
304 --out-dir=<path> Specify the out directory.
305 --package-name=<name> Specify package name (alternative to 1st argument).
306 --program-name=<name> Specify program name (cosmetic only).
307 --pid=<pid> Specify application process pid.
308 --force Kill any previous debugging session, if any.
309 --start Start package's activity on device.
310 --ui Use gdbtui instead of gdb
311 --activity=<name> Activity name for --start [$DEFAULT_ACTIVITY].
312 --annotate=<num> Enable gdb annotation.
313 --script=<file> Specify extra GDB init script.
315 --gdbserver=<file> Specify target gdbserver binary.
316 --gdb=<file> Specify host gdb client binary.
317 --target-arch=<name> Specify NDK target arch.
318 --adb=<file> Specify host ADB binary.
320 --su-prefix=<prefix> Prepend <prefix> to 'adb shell' commands that are
321 run by this script. This can be useful to use
322 the 'su' program on rooted production devices.
323 e.g. --su-prefix="su -c"
325 --pull-libs Force system libraries extraction.
326 --no-pull-libs Do not extract any system library.
327 --libs-dir=<path> Specify system libraries extraction directory.
329 --debug Use libraries under out/Debug.
330 --release Use libraries under out/Release.
336 if [ -z "$PACKAGE_NAME" ]; then
337 panic
"Please specify a package name on the command line. See --help."
340 if [ -z "$NDK_DIR" ]; then
341 ANDROID_NDK_ROOT
=$
(PYTHONPATH
=build
/android python
-c \
342 'from pylib.constants import ANDROID_NDK_ROOT; print ANDROID_NDK_ROOT,')
344 if [ ! -d "$NDK_DIR" ]; then
345 panic
"Invalid directory: $NDK_DIR"
347 if [ ! -f "$NDK_DIR/ndk-build" ]; then
348 panic
"Not a valid NDK directory: $NDK_DIR"
350 ANDROID_NDK_ROOT
=$NDK_DIR
353 if [ "$GDBINIT" -a ! -f "$GDBINIT" ]; then
354 panic
"Unknown --script file: $GDBINIT"
357 # Find the target architecture from our $GYP_DEFINES
358 # This returns an NDK-compatible architecture name.
359 # out: NDK Architecture name, or empty string.
360 get_gyp_target_arch
() {
361 local ARCH
=$
(echo $GYP_DEFINES |
tr ' ' '\n' |
grep '^target_arch=' |\
364 ia32|i?
86|x86
) echo "x86";;
365 mips|arm|arm64|x86_64
) echo "$ARCH";;
370 if [ -z "$TARGET_ARCH" ]; then
371 TARGET_ARCH
=$
(get_gyp_target_arch
)
372 if [ -z "$TARGET_ARCH" ]; then
376 # Nit: accept Chromium's 'ia32' as a valid target architecture. This
377 # script prefers the NDK 'x86' name instead because it uses it to find
378 # NDK-specific files (host gdb) with it.
379 if [ "$TARGET_ARCH" = "ia32" ]; then
381 log
"Auto-config: --arch=$TARGET_ARCH (equivalent to ia32)"
385 # Detect the NDK system name, i.e. the name used to identify the host.
386 # out: NDK system name (e.g. 'linux' or 'darwin')
387 get_ndk_host_system
() {
389 if [ -z "$NDK_HOST_SYSTEM" ]; then
392 Linux
) NDK_HOST_SYSTEM
=linux
;;
393 Darwin
) NDK_HOST_SYSTEM
=darwin
;;
394 *) panic
"You can't run this script on this system: $HOST_OS";;
397 echo "$NDK_HOST_SYSTEM"
400 # Detect the NDK host architecture name.
401 # out: NDK arch name (e.g. 'x86' or 'x86_64')
402 get_ndk_host_arch
() {
403 local HOST_ARCH HOST_OS
404 if [ -z "$NDK_HOST_ARCH" ]; then
405 HOST_OS
=$
(get_ndk_host_system
)
406 HOST_ARCH
=$
(uname
-p)
408 i?
86) NDK_HOST_ARCH
=x86
;;
409 x86_64|amd64
) NDK_HOST_ARCH
=x86_64
;;
410 *) panic
"You can't run this script on this host architecture: $HOST_ARCH";;
412 # Darwin trick: "uname -p" always returns i386 on 64-bit installations.
413 if [ "$HOST_OS" = darwin
-a "$NDK_HOST_ARCH" = "x86" ]; then
414 # Use '/usr/bin/file', not just 'file' to avoid buggy MacPorts
415 # implementations of the tool. See http://b.android.com/53769
416 HOST_64BITS
=$
(/usr
/bin
/file -L "$SHELL" |
grep -e "x86[_-]64")
417 if [ "$HOST_64BITS" ]; then
422 echo "$NDK_HOST_ARCH"
425 # Convert an NDK architecture name into a GNU configure triplet.
426 # $1: NDK architecture name (e.g. 'arm')
427 # Out: Android GNU configure triplet (e.g. 'arm-linux-androideabi')
428 get_arch_gnu_config
() {
431 echo "arm-linux-androideabi"
434 echo "aarch64-linux-android"
437 echo "i686-linux-android"
440 echo "x86_64-linux-android"
443 echo "mipsel-linux-android"
446 echo "$ARCH-linux-android"
451 # Convert an NDK architecture name into a toolchain name prefix
452 # $1: NDK architecture name (e.g. 'arm')
453 # Out: NDK toolchain name prefix (e.g. 'arm-linux-androideabi')
454 get_arch_toolchain_prefix
() {
455 # Return the configure triplet, except for x86!
456 if [ "$1" = "x86" ]; then
459 get_arch_gnu_config
$1
463 # Find a NDK toolchain prebuilt file or sub-directory.
464 # This will probe the various arch-specific toolchain directories
465 # in the NDK for the needed file.
466 # $1: NDK install path
467 # $2: NDK architecture name
468 # $3: prebuilt sub-path to look for.
469 # Out: file path, or empty if none is found.
470 get_ndk_toolchain_prebuilt
() {
471 local NDK_DIR
="${1%/}"
474 local NAME
="$(get_arch_toolchain_prefix $ARCH)"
476 FILE
=$NDK_DIR/toolchains
/$NAME-4.8
/prebuilt
/$SUBPATH
477 if [ ! -f "$FILE" ]; then
478 FILE
=$NDK_DIR/toolchains
/$NAME-4.9
/prebuilt
/$SUBPATH
479 if [ ! -f "$FILE" ]; then
480 FILE
=$NDK_DIR/toolchains
/$NAME-4.6
/prebuilt
/$SUBPATH
481 if [ ! -f "$FILE" ]; then
489 # Find the path to an NDK's toolchain full prefix for a given architecture
490 # $1: NDK install path
491 # $2: NDK target architecture name
492 # Out: install path + binary prefix (e.g.
493 # ".../path/to/bin/arm-linux-androideabi-")
494 get_ndk_toolchain_fullprefix
() {
497 local TARGET NAME HOST_OS HOST_ARCH GCC CONFIG
499 # NOTE: This will need to be updated if the NDK changes the names or moves
500 # the location of its prebuilt toolchains.
503 HOST_OS
=$
(get_ndk_host_system
)
504 HOST_ARCH
=$
(get_ndk_host_arch
)
505 CONFIG
=$
(get_arch_gnu_config
$ARCH)
506 GCC
=$
(get_ndk_toolchain_prebuilt \
507 "$NDK_DIR" "$ARCH" "$HOST_OS-$HOST_ARCH/bin/$CONFIG-gcc")
508 if [ -z "$GCC" -a "$HOST_ARCH" = "x86_64" ]; then
509 GCC
=$
(get_ndk_toolchain_prebuilt \
510 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/$CONFIG-gcc")
512 if [ ! -f "$GCC" -a "$ARCH" = "x86" ]; then
513 # Special case, the x86 toolchain used to be incorrectly
514 # named i686-android-linux-gcc!
515 GCC
=$
(get_ndk_toolchain_prebuilt \
516 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/i686-android-linux-gcc")
518 if [ -z "$GCC" ]; then
519 panic
"Cannot find Android NDK toolchain for '$ARCH' architecture. \
520 Please verify your NDK installation!"
525 # $1: NDK install path
526 # $2: target architecture.
527 get_ndk_gdbserver
() {
532 # The location has moved after NDK r8
533 BINARY
=$NDK_DIR/prebuilt
/android-
$ARCH/gdbserver
/gdbserver
534 if [ ! -f "$BINARY" ]; then
535 BINARY
=$
(get_ndk_toolchain_prebuilt
"$NDK_DIR" "$ARCH" gdbserver
)
540 # Check/probe the path to the Android toolchain installation. Always
541 # use the NDK versions of gdb and gdbserver. They must match to avoid
542 # issues when both binaries do not speak the same wire protocol.
544 if [ -z "$TOOLCHAIN" ]; then
545 ANDROID_TOOLCHAIN
=$
(get_ndk_toolchain_fullprefix \
546 "$ANDROID_NDK_ROOT" "$TARGET_ARCH")
547 ANDROID_TOOLCHAIN
=$
(dirname "$ANDROID_TOOLCHAIN")
548 log
"Auto-config: --toolchain=$ANDROID_TOOLCHAIN"
550 # Be flexible, allow one to specify either the install path or the bin
551 # sub-directory in --toolchain:
553 if [ -d "$TOOLCHAIN/bin" ]; then
554 TOOLCHAIN
=$TOOLCHAIN/bin
556 ANDROID_TOOLCHAIN
=$TOOLCHAIN
559 # Cosmetic: Remove trailing directory separator.
560 ANDROID_TOOLCHAIN
=${ANDROID_TOOLCHAIN%/}
562 # Find host GDB client binary
563 if [ -z "$GDB" ]; then
564 GDB
=$
(which $ANDROID_TOOLCHAIN/*-$GDBEXEPOSTFIX 2>/dev
/null |
head -1)
565 if [ -z "$GDB" ]; then
566 panic
"Can't find Android gdb client in your path, check your \
567 --toolchain or --gdb path."
569 log
"Host gdb client: $GDB"
572 # Find gdbserver binary, we will later push it to /data/local/tmp
573 # This ensures that both gdbserver and $GDB talk the same binary protocol,
574 # otherwise weird problems will appear.
576 if [ -z "$GDBSERVER" ]; then
577 GDBSERVER
=$
(get_ndk_gdbserver
"$ANDROID_NDK_ROOT" "$TARGET_ARCH")
578 if [ -z "$GDBSERVER" ]; then
579 panic
"Can't find NDK gdbserver binary. use --gdbserver to specify \
582 log
"Auto-config: --gdbserver=$GDBSERVER"
587 # Check that ADB is in our path
588 if [ -z "$ADB" ]; then
589 ADB
=$
(which adb
2>/dev
/null
)
590 if [ -z "$ADB" ]; then
591 panic
"Can't find 'adb' tool in your path. Install it or use \
594 log
"Auto-config: --adb=$ADB"
597 # Check that it works minimally
598 ADB_VERSION
=$
($ADB version
2>/dev
/null
)
599 echo "$ADB_VERSION" | fgrep
-q -e "Android Debug Bridge"
601 panic
"Your 'adb' tool seems invalid, use --adb=<file> to specify a \
605 # If there are more than one device connected, and ANDROID_SERIAL is not
606 # defined, print an error message.
607 NUM_DEVICES_PLUS2
=$
($ADB devices
2>/dev
/null |
wc -l)
608 if [ "$NUM_DEVICES_PLUS2" -lt 3 -a -z "$ANDROID_SERIAL" ]; then
609 echo "ERROR: There is more than one Android device connected to ADB."
610 echo "Please define ANDROID_SERIAL to specify which one to use."
614 # A unique ID for this script's session. This needs to be the same in all
615 # sub-shell commands we're going to launch, so take the PID of the launcher
619 # Temporary directory, will get cleaned up on exit.
620 TMPDIR
=/tmp
/$USER-adb-gdb-tmp-$TMP_ID
621 mkdir
-p "$TMPDIR" && rm -rf "$TMPDIR"/*
623 GDBSERVER_PIDFILE
="$TMPDIR"/gdbserver-
$TMP_ID.pid
625 # Run a command through adb shell, strip the extra \r from the output
626 # and return the correct status code to detect failures. This assumes
627 # that the adb shell command prints a final \n to stdout.
628 # $1+: command to run
629 # Out: command's stdout
630 # Return: command's status
631 # Note: the command's stderr is lost
633 local TMPOUT
="$(mktemp)"
635 local ADB
=${ADB:-adb}
637 # The weird sed rule is to strip the final \r on each output line
638 # Since 'adb shell' never returns the command's proper exit/status code,
639 # we force it to print it as '%%<status>' in the temporary output file,
640 # which we will later strip from it.
641 $ADB shell $@
";" echo "%%\$?" 2>/dev
/null | \
642 sed -e 's![[:cntrl:]]!!g' > $TMPOUT
643 # Get last line in log, which contains the exit code from the command
644 LASTLINE
=$
(sed -e '$!d' $TMPOUT)
645 # Extract the status code from the end of the line, which must
647 RET
=$
(echo "$LASTLINE" | \
648 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,RSTART+2); } }')
649 # Remove the status code from the last line. Note that this may result
651 LASTLINE
=$
(echo "$LASTLINE" | \
652 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,1,RSTART-1); } }')
653 # The output itself: all lines except the status code.
654 sed -e '$d' $TMPOUT && printf "%s" "$LASTLINE"
657 # Exit with the appropriate status.
661 # If --force is specified, try to kill any gdbserver process started by the
662 # same user on the device. Normally, these are killed automatically by the
663 # script on exit, but there are a few corner cases where this would still
665 if [ "$FORCE" ]; then
666 GDBSERVER_PIDS
=$
(adb_shell ps |
awk '$9 ~ /gdbserver/ { print $2; }')
667 for GDB_PID
in $GDBSERVER_PIDS; do
668 log
"Killing previous gdbserver (PID=$GDB_PID)"
669 adb_shell
kill -9 $GDB_PID
673 if [ "$START" ]; then
674 log
"Starting $PROGRAM_NAME on device."
675 adb_shell am start
-n $PACKAGE_NAME/$ACTIVITY 2>/dev
/null
676 adb_shell ps |
grep -q $PACKAGE_NAME
677 fail_panic
"Could not start $PROGRAM_NAME on device. Are you sure the \
678 package is installed?"
681 # Return the timestamp of a given time, as number of seconds since epoch.
683 # Out: file timestamp
684 get_file_timestamp
() {
685 stat
-c %Y
"$1" 2>/dev
/null
688 # Detect the build type and symbol directory. This is done by finding
689 # the most recent sub-directory containing debug shared libraries under
690 # $CHROMIUM_SRC/$CHROMIUM_OUT_DIR/
692 # $1: $BUILDTYPE value, can be empty
693 # Out: nothing, but this sets SYMBOL_DIR
695 detect_symbol_dir
() {
696 local SUBDIRS SUBDIR LIST DIR DIR_LIBS TSTAMP
697 # Note: Ninja places debug libraries under out/$BUILDTYPE/lib/, while
698 # Make places then under out/$BUILDTYPE/lib.target.
700 SUBDIRS
="$1/lib $1/lib.target"
702 SUBDIRS
="Release/lib Debug/lib Release/lib.target Debug/lib.target"
704 LIST
=$TMPDIR/scan-subdirs-$$.txt
706 for SUBDIR
in $SUBDIRS; do
707 DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
708 if [ -d "$DIR" ]; then
709 # Ignore build directories that don't contain symbol versions
710 # of the shared libraries.
711 DIR_LIBS
=$
(ls "$DIR"/lib
*.so
2>/dev
/null
)
712 if [ -z "$DIR_LIBS" ]; then
713 echo "No shared libs: $DIR"
716 TSTAMP
=$
(get_file_timestamp
"$DIR")
717 printf "%s %s\n" "$TSTAMP" "$SUBDIR" >> "$LIST"
720 SUBDIR
=$
(cat $LIST |
sort -r |
head -1 | cut
-d" " -f2)
723 if [ -z "$SUBDIR" ]; then
725 panic
"Could not find any build directory under \
726 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Please build the program first!"
728 panic
"Could not find any $1 directory under \
729 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Check your build type!"
733 SYMBOL_DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
734 log
"Auto-config: --symbol-dir=$SYMBOL_DIR"
737 if [ -z "$SYMBOL_DIR" ]; then
738 detect_symbol_dir
"$BUILDTYPE"
741 # Allow several concurrent debugging sessions
742 TARGET_GDBSERVER
=/data
/local
/tmp
/gdbserver-adb-gdb-
$TMP_ID
744 # Return the build fingerprint contained in a build.prop file.
745 # $1: path to build.prop file
746 get_build_fingerprint_from
() {
747 cat "$1" |
grep -e '^ro.build.fingerprint=' | cut
-d= -f2
751 ORG_PULL_LIBS_DIR
=$PULL_LIBS_DIR
752 PULL_LIBS_DIR
=${PULL_LIBS_DIR:-$DEFAULT_PULL_LIBS_DIR}
755 DEVICE_FINGERPRINT
=$
(adb_shell getprop ro.build.fingerprint
)
756 log
"Device build fingerprint: $DEVICE_FINGERPRINT"
758 # If --pull-libs-dir is not specified, and this is a platform build, look
759 # if we can use the symbolic libraries under $ANDROID_PRODUCT_OUT/symbols/
760 # directly, if the build fingerprint matches the device.
761 if [ -z "$ORG_PULL_LIBS_DIR" -a \
762 "$ANDROID_PRODUCT_OUT" -a \
763 -f "$ANDROID_PRODUCT_OUT/system/build.prop" ]; then
764 ANDROID_FINGERPRINT
=$
(get_build_fingerprint_from \
765 "$ANDROID_PRODUCT_OUT"/system
/build.prop
)
766 log
"Android build fingerprint: $ANDROID_FINGERPRINT"
767 if [ "$ANDROID_FINGERPRINT" = "$DEVICE_FINGERPRINT" ]; then
769 PULL_LIBS_DIR
=$ANDROID_PRODUCT_OUT/symbols
770 HOST_FINGERPRINT
=$ANDROID_FINGERPRINT
771 if [ "$PULL_LIBS" ]; then
772 log
"Ignoring --pull-libs since the device and platform build \
779 # If neither --pull-libs an --no-pull-libs were specified, check the build
780 # fingerprints of the device, and the cached system libraries on the host.
782 if [ -z "$NO_PULL_LIBS" -a -z "$PULL_LIBS" ]; then
783 if [ ! -f "$PULL_LIBS_DIR/build.prop" ]; then
784 log
"Auto-config: --pull-libs (no cached libraries)"
787 HOST_FINGERPRINT
=$
(get_build_fingerprint_from
"$PULL_LIBS_DIR/build.prop")
788 log
"Host build fingerprint: $HOST_FINGERPRINT"
789 if [ "$HOST_FINGERPRINT" == "$DEVICE_FINGERPRINT" ]; then
790 log
"Auto-config: --no-pull-libs (fingerprint match)"
793 log
"Auto-config: --pull-libs (fingerprint mismatch)"
799 # Extract the system libraries from the device if necessary.
800 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
801 echo "Extracting system libraries into: $PULL_LIBS_DIR"
804 mkdir
-p "$PULL_LIBS_DIR"
805 fail_panic
"Can't create --libs-dir directory: $PULL_LIBS_DIR"
807 # If requested, work for M-x gdb. The gdb indirections make it
808 # difficult to pass --annotate=3 to the gdb binary itself.
810 if [ "$ANNOTATE" ]; then
811 GDB_ARGS
=$GDB_ARGS" --annotate=$ANNOTATE"
814 # Get the PID from the first argument or else find the PID of the
816 if [ -z "$PID" ]; then
817 PROCESSNAME
=$PACKAGE_NAME
818 if [ "$SANDBOXED_INDEX" ]; then
819 PROCESSNAME
=$PROCESSNAME:sandboxed_process
$SANDBOXED_INDEX
820 elif [ "$SANDBOXED" ]; then
821 PROCESSNAME
=$PROCESSNAME:sandboxed_process
822 PID
=$
(adb_shell ps | \
823 awk '$9 ~ /^'$PROCESSNAME'/ { print $2; }' |
head -1)
825 if [ -z "$PID" ]; then
826 PID
=$
(adb_shell ps | \
827 awk '$9 == "'$PROCESSNAME'" { print $2; }' |
head -1)
829 if [ -z "$PID" ]; then
830 if [ "$START" ]; then
831 panic
"Can't find application process PID, did it crash?"
833 panic
"Can't find application process PID, are you sure it is \
834 running? Try using --start."
837 log
"Found process PID: $PID"
838 elif [ "$SANDBOXED" ]; then
839 echo "WARNING: --sandboxed option ignored due to use of --pid."
842 # Determine if 'adb shell' runs as root or not.
843 # If so, we can launch gdbserver directly, otherwise, we have to
844 # use run-as $PACKAGE_NAME ..., which requires the package to be debuggable.
846 if [ "$SU_PREFIX" ]; then
847 # Need to check that this works properly.
848 SU_PREFIX_TEST_LOG
=$TMPDIR/su-prefix.log
849 adb_shell
$SU_PREFIX echo "foo" > $SU_PREFIX_TEST_LOG 2>&1
850 if [ $?
!= 0 -o "$(cat $SU_PREFIX_TEST_LOG)" != "foo" ]; then
851 echo "ERROR: Cannot use '$SU_PREFIX' as a valid su prefix:"
852 echo "$ adb shell $SU_PREFIX echo foo"
853 cat $SU_PREFIX_TEST_LOG
856 COMMAND_PREFIX
="$SU_PREFIX"
858 SHELL_UID
=$
(adb shell
cat /proc
/self
/status | \
859 awk '$1 == "Uid:" { print $2; }')
860 log
"Shell UID: $SHELL_UID"
861 if [ "$SHELL_UID" != 0 -o -n "$NO_ROOT" ]; then
862 COMMAND_PREFIX
="run-as $PACKAGE_NAME"
867 log
"Command prefix: '$COMMAND_PREFIX'"
869 # Pull device's system libraries that are mapped by our process.
870 # Pulling all system libraries is too long, so determine which ones
871 # we need by looking at /proc/$PID/maps instead
872 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
873 echo "Extracting system libraries into: $PULL_LIBS_DIR"
874 rm -f $PULL_LIBS_DIR/build.prop
875 MAPPINGS
=$
(adb_shell
$COMMAND_PREFIX cat /proc
/$PID/maps
)
877 echo "ERROR: Could not list process's memory mappings."
878 if [ "$SU_PREFIX" ]; then
879 panic
"Are you sure your --su-prefix is correct?"
881 panic
"Use --su-prefix if the application is not debuggable."
884 SYSTEM_LIBS
=$
(echo "$MAPPINGS" | \
885 awk '$6 ~ /\/system\/.*\.so$/ { print $6; }' |
sort -u)
886 for SYSLIB
in /system
/bin
/linker
$SYSTEM_LIBS; do
887 echo "Pulling from device: $SYSLIB"
888 DST_FILE
=$PULL_LIBS_DIR$SYSLIB
889 DST_DIR
=$
(dirname "$DST_FILE")
890 mkdir
-p "$DST_DIR" && adb pull
$SYSLIB "$DST_FILE" 2>/dev
/null
891 fail_panic
"Could not pull $SYSLIB from device !?"
893 echo "Pulling device build.prop"
894 adb pull
/system
/build.prop
$PULL_LIBS_DIR/build.prop
895 fail_panic
"Could not pull device build.prop !?"
898 # Find all the sub-directories of $PULL_LIBS_DIR, up to depth 4
899 # so we can add them to solib-search-path later.
900 SOLIB_DIRS
=$
(find $PULL_LIBS_DIR -mindepth 1 -maxdepth 4 -type d | \
901 grep -v "^$" |
tr '\n' ':')
903 # This is a re-implementation of gdbclient, where we use compatible
904 # versions of gdbserver and $GDBNAME to ensure that everything works
908 # Push gdbserver to the device
909 log
"Pushing gdbserver $GDBSERVER to $TARGET_GDBSERVER"
910 adb push
$GDBSERVER $TARGET_GDBSERVER &>/dev
/null
911 fail_panic
"Could not copy gdbserver to the device!"
917 # Select correct app_process for architecture.
919 arm|x86|mips
) GDBEXEC
=app_process
;;
920 arm64|x86_64
) GDBEXEC
=app_process64
;;
921 *) fail_panic
"Unknown app_process for architecture!";;
924 # Detect AddressSanitizer setup on the device. In that case app_process is a
925 # script, and the real executable is app_process.real.
926 GDBEXEC_ASAN
=app_process.real
927 adb_shell
ls /system
/bin
/$GDBEXEC_ASAN
929 GDBEXEC
=$GDBEXEC_ASAN
932 # Pull the app_process binary from the device.
933 log
"Pulling $GDBEXEC from device"
934 adb pull
/system
/bin
/$GDBEXEC "$TMPDIR"/$GDBEXEC &>/dev
/null
935 fail_panic
"Could not retrieve $GDBEXEC from the device!"
937 # Setup network redirection
938 log
"Setting network redirection (host:$HOST_PORT -> device:$TARGET_PORT)"
939 adb forward tcp
:$HOST_PORT tcp
:$TARGET_PORT
940 fail_panic
"Could not setup network redirection from \
941 host:localhost:$HOST_PORT to device:localhost:$TARGET_PORT!"
943 # Start gdbserver in the background
944 # Note that using run-as requires the package to be debuggable.
946 # If not, this will fail horribly. The alternative is to run the
947 # program as root, which requires of course root privileges.
948 # Maybe we should add a --root option to enable this?
950 log
"Starting gdbserver in the background:"
951 GDBSERVER_LOG
=$TMPDIR/gdbserver-
$TMP_ID.log
952 log
"adb shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
954 ("$ADB" shell
$COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
955 --attach $PID > $GDBSERVER_LOG 2>&1) &
957 echo "$GDBSERVER_PID" > $GDBSERVER_PIDFILE
958 log
"background job pid: $GDBSERVER_PID"
960 # Check that it is still running after a few seconds. If not, this means we
961 # could not properly attach to it
963 log
"Job control: $(jobs -l)"
964 STATE
=$
(jobs -l |
awk '$2 == "'$GDBSERVER_PID'" { print $3; }')
965 if [ "$STATE" != "Running" ]; then
966 echo "ERROR: GDBServer could not attach to PID $PID!"
967 echo "Failure log (use --verbose for more information):"
972 # Generate a file containing useful GDB initialization commands
973 readonly COMMANDS
=$TMPDIR/gdb.init
974 log
"Generating GDB initialization commands file: $COMMANDS"
975 echo -n "" > $COMMANDS
976 echo "file $TMPDIR/$GDBEXEC" >> $COMMANDS
977 echo "directory $CHROMIUM_SRC" >> $COMMANDS
978 echo "set solib-absolute-prefix $PULL_LIBS_DIR" >> $COMMANDS
979 echo "set solib-search-path $SOLIB_DIRS:$PULL_LIBS_DIR:$SYMBOL_DIR" \
981 echo "echo Attaching and reading symbols, this may take a while.." \
983 echo "target remote :$HOST_PORT" >> $COMMANDS
985 if [ "$GDBINIT" ]; then
986 cat "$GDBINIT" >> $COMMANDS
989 if [ "$VERBOSE" -gt 0 ]; then
990 echo "### START $COMMANDS"
992 echo "### END $COMMANDS"
995 log
"Launching gdb client: $GDB $GDB_ARGS -x $COMMANDS"
996 $GDB $GDB_ARGS -x $COMMANDS &&
997 rm -f "$GDBSERVER_PIDFILE"