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
32 if [ "$TMPDIR" ]; then
33 GDBSERVER_PID
=$
(cat $GDBSERVER_PIDFILE 2>/dev
/null
)
34 if [ "$GDBSERVER_PID" ]; then
35 log
"Killing background gdbserver process: $GDBSERVER_PID"
36 kill -9 $GDBSERVER_PID >/dev
/null
2>&1
38 if [ "$TARGET_GDBSERVER" ]; then
39 log
"Removing target gdbserver binary: $TARGET_GDBSERVER."
40 "$ADB" shell
"$COMMAND_PREFIX" rm "$TARGET_GDBSERVER" >/dev
/null
2>&1
42 log
"Cleaning up: $TMPDIR"
49 # Ensure clean exit on Ctrl-C or normal exit.
50 trap "clean_exit 1" INT HUP QUIT TERM
51 trap "clean_exit \$?" EXIT
59 if [ $?
!= 0 ]; then panic
"$@"; fi
63 if [ "$VERBOSE" -gt 0 ]; then
68 DEFAULT_PULL_LIBS_DIR
=/tmp
/$USER-adb-gdb-libs
70 # NOTE: Allow wrapper scripts to set various default through ADB_GDB_XXX
71 # environment variables. This is only for cosmetic reasons, i.e. to
74 # Allow wrapper scripts to set the default activity through
75 # the ADB_GDB_ACTIVITY variable. Users are still able to change the
76 # final activity name through --activity=<name> option.
78 # This is only for cosmetic reasons, i.e. to display the proper default
79 # in the --help output.
81 DEFAULT_ACTIVITY
=${ADB_GDB_ACTIVITY:-".Main"}
83 # Allow wrapper scripts to set the program name through ADB_GDB_PROGNAME
84 PROGNAME
=${ADB_GDB_PROGNAME:-$(basename "$0")}
86 ACTIVITY
=$DEFAULT_ACTIVITY
89 # Note: Ignore BUILDTYPE variable, because the Ninja build doesn't use it.
102 PROGRAM_NAME
="activity"
115 optarg
=$
(expr "x$opt" : 'x[^=]*=\(.*\)')
155 PRIVILEGED_INDEX
=$optarg
164 PULL_LIBS_DIR
=$optarg
171 SANDBOXED_INDEX
=$optarg
186 CHROMIUM_OUT_DIR
=$optarg
198 VERBOSE
=$
(( $VERBOSE + 1 ))
207 panic
"Unknown option $OPT, see --help." >&2
210 if [ "$PACKAGE_NAME" ]; then
211 panic
"You can only provide a single package name as argument!\
219 print_help_options
() {
225 if [ "$ADB_GDB_PROGNAME" ]; then
226 # Assume wrapper scripts all provide a default package name.
228 Usage: $PROGNAME [options]
230 Attach gdb to a running Android $PROGRAM_NAME process.
233 # Assume this is a direct call to adb_gdb
235 Usage: $PROGNAME [options] [<package-name>]
237 Attach gdb to a running Android $PROGRAM_NAME process.
239 If provided, <package-name> must be the name of the Android application's
240 package name to be debugged. You can also use --package-name=<name> to
247 This script is used to debug a running $PROGRAM_NAME process.
248 This can be a regular Android application process, sandboxed (if you use the
249 --sandboxed or --sandboxed=<num> option) or a privileged (--privileged or
250 --privileged=<num>) service.
252 This script needs several things to work properly. It will try to pick
253 them up automatically for you though:
255 - target gdbserver binary
256 - host gdb client (e.g. arm-linux-androideabi-gdb)
257 - directory with symbolic version of $PROGRAM_NAME's shared libraries.
259 You can also use --ndk-dir=<path> to specify an alternative NDK installation
262 The script tries to find the most recent version of the debug version of
263 shared libraries under one of the following directories:
265 \$CHROMIUM_SRC/<out>/Release/lib/ (used by Ninja builds)
266 \$CHROMIUM_SRC/<out>/Debug/lib/ (used by Ninja builds)
267 \$CHROMIUM_SRC/<out>/Release/lib.target/ (used by Make builds)
268 \$CHROMIUM_SRC/<out>/Debug/lib.target/ (used by Make builds)
270 Where <out> is 'out' by default, unless the --out=<name> option is used or
271 the CHROMIUM_OUT_DIR environment variable is defined.
273 You can restrict this search by using --release or --debug to specify the
274 build type, or simply use --symbol-dir=<path> to specify the file manually.
276 The script tries to extract the target architecture from your target device,
277 but if this fails, will default to 'arm'. Use --target-arch=<name> to force
280 Otherwise, the script will complain, but you can use the --gdbserver,
281 --gdb and --symbol-lib options to specify everything manually.
283 An alternative to --gdb=<file> is to use --toollchain=<path> to specify
284 the path to the host target-specific cross-toolchain.
286 You will also need the 'adb' tool in your path. Otherwise, use the --adb
287 option. The script will complain if there is more than one device connected
288 and ANDROID_SERIAL is not defined.
290 The first time you use it on a device, the script will pull many system
291 libraries required by the process into a temporary directory. This
292 is done to strongly improve the debugging experience, like allowing
293 readable thread stacks and more. The libraries are copied to the following
294 directory by default:
296 $DEFAULT_PULL_LIBS_DIR/
298 But you can use the --pull-libs-dir=<path> option to specify an
299 alternative. The script can detect when you change the connected device,
300 and will re-pull the libraries only in this case. You can however force it
301 with the --pull-libs option.
303 Any local .gdbinit script will be ignored, but it is possible to pass a
304 gdb command script with the --script=<file> option. Note that its commands
305 will be passed to gdb after the remote connection and library symbol
306 loading have completed.
309 --help|-h|-? Print this message.
310 --verbose Increase verbosity.
312 --sandboxed Debug first sandboxed process we find.
313 --sandboxed=<num> Debug specific sandboxed process.
314 --symbol-dir=<path> Specify directory with symbol shared libraries.
315 --out-dir=<path> Specify the out directory.
316 --package-name=<name> Specify package name (alternative to 1st argument).
317 --privileged Debug first privileged process we find.
318 --privileged=<num> Debug specific privileged process.
319 --program-name=<name> Specify program name (cosmetic only).
320 --pid=<pid> Specify application process pid.
321 --force Kill any previous debugging session, if any.
322 --start Start package's activity on device.
323 --ui Use gdbtui instead of gdb
324 --activity=<name> Activity name for --start [$DEFAULT_ACTIVITY].
325 --annotate=<num> Enable gdb annotation.
326 --script=<file> Specify extra GDB init script.
328 --gdbserver=<file> Specify target gdbserver binary.
329 --gdb=<file> Specify host gdb client binary.
330 --target-arch=<name> Specify NDK target arch.
331 --adb=<file> Specify host ADB binary.
333 --su-prefix=<prefix> Prepend <prefix> to 'adb shell' commands that are
334 run by this script. This can be useful to use
335 the 'su' program on rooted production devices.
336 e.g. --su-prefix="su -c"
338 --pull-libs Force system libraries extraction.
339 --no-pull-libs Do not extract any system library.
340 --libs-dir=<path> Specify system libraries extraction directory.
342 --debug Use libraries under out/Debug.
343 --release Use libraries under out/Release.
349 if [ -z "$PACKAGE_NAME" ]; then
350 panic
"Please specify a package name on the command line. See --help."
353 if [ -z "$NDK_DIR" ]; then
354 ANDROID_NDK_ROOT
=$
(PYTHONPATH
=$CHROMIUM_SRC/build
/android python
-c \
355 'from pylib.constants import ANDROID_NDK_ROOT; print ANDROID_NDK_ROOT,')
357 if [ ! -d "$NDK_DIR" ]; then
358 panic
"Invalid directory: $NDK_DIR"
360 if [ ! -f "$NDK_DIR/ndk-build" ]; then
361 panic
"Not a valid NDK directory: $NDK_DIR"
363 ANDROID_NDK_ROOT
=$NDK_DIR
366 if [ "$GDBINIT" -a ! -f "$GDBINIT" ]; then
367 panic
"Unknown --script file: $GDBINIT"
370 # Check that ADB is in our path
371 if [ -z "$ADB" ]; then
372 ADB
=$
(which adb
2>/dev
/null
)
373 if [ -z "$ADB" ]; then
374 panic
"Can't find 'adb' tool in your path. Install it or use \
377 log
"Auto-config: --adb=$ADB"
380 # Check that it works minimally
381 ADB_VERSION
=$
($ADB version
2>/dev
/null
)
382 echo "$ADB_VERSION" | fgrep
-q -e "Android Debug Bridge"
384 panic
"Your 'adb' tool seems invalid, use --adb=<file> to specify a \
388 # If there are more than one device connected, and ANDROID_SERIAL is not
389 # defined, print an error message.
390 NUM_DEVICES_PLUS2
=$
($ADB devices
2>/dev
/null |
wc -l)
391 if [ "$NUM_DEVICES_PLUS2" -lt 3 -a -z "$ANDROID_SERIAL" ]; then
392 echo "ERROR: There is more than one Android device connected to ADB."
393 echo "Please define ANDROID_SERIAL to specify which one to use."
397 # Run a command through adb shell, strip the extra \r from the output
398 # and return the correct status code to detect failures. This assumes
399 # that the adb shell command prints a final \n to stdout.
400 # $1+: command to run
401 # Out: command's stdout
402 # Return: command's status
403 # Note: the command's stderr is lost
405 local TMPOUT
="$(mktemp)"
407 local ADB
=${ADB:-adb}
409 # The weird sed rule is to strip the final \r on each output line
410 # Since 'adb shell' never returns the command's proper exit/status code,
411 # we force it to print it as '%%<status>' in the temporary output file,
412 # which we will later strip from it.
413 $ADB shell $@
";" echo "%%\$?" 2>/dev
/null | \
414 sed -e 's![[:cntrl:]]!!g' > $TMPOUT
415 # Get last line in log, which contains the exit code from the command
416 LASTLINE
=$
(sed -e '$!d' $TMPOUT)
417 # Extract the status code from the end of the line, which must
419 RET
=$
(echo "$LASTLINE" | \
420 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,RSTART+2); } }')
421 # Remove the status code from the last line. Note that this may result
423 LASTLINE
=$
(echo "$LASTLINE" | \
424 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,1,RSTART-1); } }')
425 # The output itself: all lines except the status code.
426 sed -e '$d' $TMPOUT && printf "%s" "$LASTLINE"
429 # Exit with the appropriate status.
433 # Find the target architecture from the target device.
434 # This returns an NDK-compatible architecture name.
435 # out: NDK Architecture name, or empty string.
436 get_gyp_target_arch
() {
437 local ARCH
=$
(adb_shell getprop ro.product.cpu.abi
)
439 mips|x86|x86_64
) echo "$ARCH";;
440 arm64
*) echo "arm64";;
446 if [ -z "$TARGET_ARCH" ]; then
447 TARGET_ARCH
=$
(get_gyp_target_arch
)
448 if [ -z "$TARGET_ARCH" ]; then
452 # Nit: accept Chromium's 'ia32' as a valid target architecture. This
453 # script prefers the NDK 'x86' name instead because it uses it to find
454 # NDK-specific files (host gdb) with it.
455 if [ "$TARGET_ARCH" = "ia32" ]; then
457 log
"Auto-config: --arch=$TARGET_ARCH (equivalent to ia32)"
461 # Detect the NDK system name, i.e. the name used to identify the host.
462 # out: NDK system name (e.g. 'linux' or 'darwin')
463 get_ndk_host_system
() {
465 if [ -z "$NDK_HOST_SYSTEM" ]; then
468 Linux
) NDK_HOST_SYSTEM
=linux
;;
469 Darwin
) NDK_HOST_SYSTEM
=darwin
;;
470 *) panic
"You can't run this script on this system: $HOST_OS";;
473 echo "$NDK_HOST_SYSTEM"
476 # Detect the NDK host architecture name.
477 # out: NDK arch name (e.g. 'x86' or 'x86_64')
478 get_ndk_host_arch
() {
479 local HOST_ARCH HOST_OS
480 if [ -z "$NDK_HOST_ARCH" ]; then
481 HOST_OS
=$
(get_ndk_host_system
)
482 HOST_ARCH
=$
(uname
-p)
484 i?
86) NDK_HOST_ARCH
=x86
;;
485 x86_64|amd64
) NDK_HOST_ARCH
=x86_64
;;
486 *) panic
"You can't run this script on this host architecture: $HOST_ARCH";;
488 # Darwin trick: "uname -p" always returns i386 on 64-bit installations.
489 if [ "$HOST_OS" = darwin
-a "$NDK_HOST_ARCH" = "x86" ]; then
490 # Use '/usr/bin/file', not just 'file' to avoid buggy MacPorts
491 # implementations of the tool. See http://b.android.com/53769
492 HOST_64BITS
=$
(/usr
/bin
/file -L "$SHELL" |
grep -e "x86[_-]64")
493 if [ "$HOST_64BITS" ]; then
498 echo "$NDK_HOST_ARCH"
501 # Convert an NDK architecture name into a GNU configure triplet.
502 # $1: NDK architecture name (e.g. 'arm')
503 # Out: Android GNU configure triplet (e.g. 'arm-linux-androideabi')
504 get_arch_gnu_config
() {
507 echo "arm-linux-androideabi"
510 echo "aarch64-linux-android"
513 echo "i686-linux-android"
516 echo "x86_64-linux-android"
519 echo "mipsel-linux-android"
522 echo "$ARCH-linux-android"
527 # Convert an NDK architecture name into a toolchain name prefix
528 # $1: NDK architecture name (e.g. 'arm')
529 # Out: NDK toolchain name prefix (e.g. 'arm-linux-androideabi')
530 get_arch_toolchain_prefix
() {
531 # Return the configure triplet, except for x86!
532 if [ "$1" = "x86" ]; then
535 get_arch_gnu_config
$1
539 # Find a NDK toolchain prebuilt file or sub-directory.
540 # This will probe the various arch-specific toolchain directories
541 # in the NDK for the needed file.
542 # $1: NDK install path
543 # $2: NDK architecture name
544 # $3: prebuilt sub-path to look for.
545 # Out: file path, or empty if none is found.
546 get_ndk_toolchain_prebuilt
() {
547 local NDK_DIR
="${1%/}"
550 local NAME
="$(get_arch_toolchain_prefix $ARCH)"
552 FILE
=$NDK_DIR/toolchains
/$NAME-4.9
/prebuilt
/$SUBPATH
553 if [ ! -f "$FILE" ]; then
554 FILE
=$NDK_DIR/toolchains
/$NAME-4.8
/prebuilt
/$SUBPATH
555 if [ ! -f "$FILE" ]; then
562 # Find the path to an NDK's toolchain full prefix for a given architecture
563 # $1: NDK install path
564 # $2: NDK target architecture name
565 # Out: install path + binary prefix (e.g.
566 # ".../path/to/bin/arm-linux-androideabi-")
567 get_ndk_toolchain_fullprefix
() {
570 local TARGET NAME HOST_OS HOST_ARCH GCC CONFIG
572 # NOTE: This will need to be updated if the NDK changes the names or moves
573 # the location of its prebuilt toolchains.
576 HOST_OS
=$
(get_ndk_host_system
)
577 HOST_ARCH
=$
(get_ndk_host_arch
)
578 CONFIG
=$
(get_arch_gnu_config
$ARCH)
579 GCC
=$
(get_ndk_toolchain_prebuilt \
580 "$NDK_DIR" "$ARCH" "$HOST_OS-$HOST_ARCH/bin/$CONFIG-gcc")
581 if [ -z "$GCC" -a "$HOST_ARCH" = "x86_64" ]; then
582 GCC
=$
(get_ndk_toolchain_prebuilt \
583 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/$CONFIG-gcc")
585 if [ ! -f "$GCC" -a "$ARCH" = "x86" ]; then
586 # Special case, the x86 toolchain used to be incorrectly
587 # named i686-android-linux-gcc!
588 GCC
=$
(get_ndk_toolchain_prebuilt \
589 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/i686-android-linux-gcc")
591 if [ -z "$GCC" ]; then
592 panic
"Cannot find Android NDK toolchain for '$ARCH' architecture. \
593 Please verify your NDK installation!"
598 # $1: NDK install path
599 # $2: target architecture.
600 get_ndk_gdbserver
() {
605 # The location has moved after NDK r8
606 BINARY
=$NDK_DIR/prebuilt
/android-
$ARCH/gdbserver
/gdbserver
607 if [ ! -f "$BINARY" ]; then
608 BINARY
=$
(get_ndk_toolchain_prebuilt
"$NDK_DIR" "$ARCH" gdbserver
)
613 # Check/probe the path to the Android toolchain installation. Always
614 # use the NDK versions of gdb and gdbserver. They must match to avoid
615 # issues when both binaries do not speak the same wire protocol.
617 if [ -z "$TOOLCHAIN" ]; then
618 ANDROID_TOOLCHAIN
=$
(get_ndk_toolchain_fullprefix \
619 "$ANDROID_NDK_ROOT" "$TARGET_ARCH")
620 ANDROID_TOOLCHAIN
=$
(dirname "$ANDROID_TOOLCHAIN")
621 log
"Auto-config: --toolchain=$ANDROID_TOOLCHAIN"
623 # Be flexible, allow one to specify either the install path or the bin
624 # sub-directory in --toolchain:
626 if [ -d "$TOOLCHAIN/bin" ]; then
627 TOOLCHAIN
=$TOOLCHAIN/bin
629 ANDROID_TOOLCHAIN
=$TOOLCHAIN
632 # Cosmetic: Remove trailing directory separator.
633 ANDROID_TOOLCHAIN
=${ANDROID_TOOLCHAIN%/}
635 # Find host GDB client binary
636 if [ -z "$GDB" ]; then
637 GDB
=$
(which $ANDROID_TOOLCHAIN/*-$GDBEXEPOSTFIX 2>/dev
/null |
head -1)
638 if [ -z "$GDB" ]; then
639 panic
"Can't find Android gdb client in your path, check your \
640 --toolchain or --gdb path."
642 log
"Host gdb client: $GDB"
645 # Find gdbserver binary, we will later push it to /data/local/tmp
646 # This ensures that both gdbserver and $GDB talk the same binary protocol,
647 # otherwise weird problems will appear.
649 if [ -z "$GDBSERVER" ]; then
650 GDBSERVER
=$
(get_ndk_gdbserver
"$ANDROID_NDK_ROOT" "$TARGET_ARCH")
651 if [ -z "$GDBSERVER" ]; then
652 panic
"Can't find NDK gdbserver binary. use --gdbserver to specify \
655 log
"Auto-config: --gdbserver=$GDBSERVER"
658 # A unique ID for this script's session. This needs to be the same in all
659 # sub-shell commands we're going to launch, so take the PID of the launcher
663 # Temporary directory, will get cleaned up on exit.
664 TMPDIR
=/tmp
/$USER-adb-gdb-tmp-$TMP_ID
665 mkdir
-p "$TMPDIR" && rm -rf "$TMPDIR"/*
667 GDBSERVER_PIDFILE
="$TMPDIR"/gdbserver-
$TMP_ID.pid
669 # If --force is specified, try to kill any gdbserver process started by the
670 # same user on the device. Normally, these are killed automatically by the
671 # script on exit, but there are a few corner cases where this would still
673 if [ "$FORCE" ]; then
674 GDBSERVER_PIDS
=$
(adb_shell ps |
awk '$9 ~ /gdbserver/ { print $2; }')
675 for GDB_PID
in $GDBSERVER_PIDS; do
676 log
"Killing previous gdbserver (PID=$GDB_PID)"
677 adb_shell
kill -9 $GDB_PID
681 if [ "$START" ]; then
682 log
"Starting $PROGRAM_NAME on device."
683 adb_shell am start
-n $PACKAGE_NAME/$ACTIVITY 2>/dev
/null
684 adb_shell ps |
grep -q $PACKAGE_NAME
685 fail_panic
"Could not start $PROGRAM_NAME on device. Are you sure the \
686 package is installed?"
689 # Return the timestamp of a given time, as number of seconds since epoch.
691 # Out: file timestamp
692 get_file_timestamp
() {
693 stat
-c %Y
"$1" 2>/dev
/null
696 # Detect the build type and symbol directory. This is done by finding
697 # the most recent sub-directory containing debug shared libraries under
698 # $CHROMIUM_SRC/$CHROMIUM_OUT_DIR/
700 # $1: $BUILDTYPE value, can be empty
701 # Out: nothing, but this sets SYMBOL_DIR
703 detect_symbol_dir
() {
704 local SUBDIRS SUBDIR LIST DIR DIR_LIBS TSTAMP
705 # Note: Ninja places debug libraries under out/$BUILDTYPE/lib/, while
706 # Make places then under out/$BUILDTYPE/lib.target.
708 SUBDIRS
="$1/lib $1/lib.target"
710 SUBDIRS
="Release/lib Debug/lib Release/lib.target Debug/lib.target"
712 LIST
=$TMPDIR/scan-subdirs-$$.txt
714 for SUBDIR
in $SUBDIRS; do
715 DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
716 if [ -d "$DIR" ]; then
717 # Ignore build directories that don't contain symbol versions
718 # of the shared libraries.
719 DIR_LIBS
=$
(ls "$DIR"/lib
*.so
2>/dev
/null
)
720 if [ -z "$DIR_LIBS" ]; then
721 echo "No shared libs: $DIR"
724 TSTAMP
=$
(get_file_timestamp
"$DIR")
725 printf "%s %s\n" "$TSTAMP" "$SUBDIR" >> "$LIST"
728 SUBDIR
=$
(cat $LIST |
sort -r |
head -1 | cut
-d" " -f2)
731 if [ -z "$SUBDIR" ]; then
733 panic
"Could not find any build directory under \
734 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Please build the program first!"
736 panic
"Could not find any $1 directory under \
737 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Check your build type!"
741 SYMBOL_DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
742 log
"Auto-config: --symbol-dir=$SYMBOL_DIR"
745 if [ -z "$SYMBOL_DIR" ]; then
746 detect_symbol_dir
"$BUILDTYPE"
749 # Allow several concurrent debugging sessions
750 TARGET_GDBSERVER
=/data
/data
/$PACKAGE_NAME/gdbserver-adb-gdb-
$TMP_ID
751 TMP_TARGET_GDBSERVER
=/data
/local
/tmp
/gdbserver-adb-gdb-
$TMP_ID
753 # Return the build fingerprint contained in a build.prop file.
754 # $1: path to build.prop file
755 get_build_fingerprint_from
() {
756 cat "$1" |
grep -e '^ro.build.fingerprint=' | cut
-d= -f2
760 ORG_PULL_LIBS_DIR
=$PULL_LIBS_DIR
761 PULL_LIBS_DIR
=${PULL_LIBS_DIR:-$DEFAULT_PULL_LIBS_DIR}
764 DEVICE_FINGERPRINT
=$
(adb_shell getprop ro.build.fingerprint
)
765 log
"Device build fingerprint: $DEVICE_FINGERPRINT"
767 # If --pull-libs-dir is not specified, and this is a platform build, look
768 # if we can use the symbolic libraries under $ANDROID_PRODUCT_OUT/symbols/
769 # directly, if the build fingerprint matches the device.
770 if [ -z "$ORG_PULL_LIBS_DIR" -a \
771 "$ANDROID_PRODUCT_OUT" -a \
772 -f "$ANDROID_PRODUCT_OUT/system/build.prop" ]; then
773 ANDROID_FINGERPRINT
=$
(get_build_fingerprint_from \
774 "$ANDROID_PRODUCT_OUT"/system
/build.prop
)
775 log
"Android build fingerprint: $ANDROID_FINGERPRINT"
776 if [ "$ANDROID_FINGERPRINT" = "$DEVICE_FINGERPRINT" ]; then
778 PULL_LIBS_DIR
=$ANDROID_PRODUCT_OUT/symbols
779 HOST_FINGERPRINT
=$ANDROID_FINGERPRINT
780 if [ "$PULL_LIBS" ]; then
781 log
"Ignoring --pull-libs since the device and platform build \
788 # If neither --pull-libs an --no-pull-libs were specified, check the build
789 # fingerprints of the device, and the cached system libraries on the host.
791 if [ -z "$NO_PULL_LIBS" -a -z "$PULL_LIBS" ]; then
792 if [ ! -f "$PULL_LIBS_DIR/build.prop" ]; then
793 log
"Auto-config: --pull-libs (no cached libraries)"
796 HOST_FINGERPRINT
=$
(get_build_fingerprint_from
"$PULL_LIBS_DIR/build.prop")
797 log
"Host build fingerprint: $HOST_FINGERPRINT"
798 if [ "$HOST_FINGERPRINT" == "$DEVICE_FINGERPRINT" ]; then
799 log
"Auto-config: --no-pull-libs (fingerprint match)"
802 log
"Auto-config: --pull-libs (fingerprint mismatch)"
808 # Extract the system libraries from the device if necessary.
809 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
810 echo "Extracting system libraries into: $PULL_LIBS_DIR"
813 mkdir
-p "$PULL_LIBS_DIR"
814 fail_panic
"Can't create --libs-dir directory: $PULL_LIBS_DIR"
816 # If requested, work for M-x gdb. The gdb indirections make it
817 # difficult to pass --annotate=3 to the gdb binary itself.
819 if [ "$ANNOTATE" ]; then
820 GDB_ARGS
=$GDB_ARGS" --annotate=$ANNOTATE"
823 # Get the PID from the first argument or else find the PID of the
825 if [ -z "$PID" ]; then
826 PROCESSNAME
=$PACKAGE_NAME
827 if [ "$SANDBOXED_INDEX" ]; then
828 PROCESSNAME
=$PROCESSNAME:sandboxed_process
$SANDBOXED_INDEX
829 elif [ "$SANDBOXED" ]; then
830 PROCESSNAME
=$PROCESSNAME:sandboxed_process
831 PID
=$
(adb_shell ps | \
832 awk '$9 ~ /^'$PROCESSNAME'/ { print $2; }' |
head -1)
833 elif [ "$PRIVILEGED_INDEX" ]; then
834 PROCESSNAME
=$PROCESSNAME:privileged_process
$PRIVILEGED_INDEX
835 elif [ "$PRIVILEGED" ]; then
836 PROCESSNAME
=$PROCESSNAME:privileged_process
837 PID
=$
(adb_shell ps | \
838 awk '$9 ~ /^'$PROCESSNAME'/ { print $2; }' |
head -1)
840 if [ -z "$PID" ]; then
841 PID
=$
(adb_shell ps | \
842 awk '$9 == "'$PROCESSNAME'" { print $2; }' |
head -1)
844 if [ -z "$PID" ]; then
845 if [ "$START" ]; then
846 panic
"Can't find application process PID, did it crash?"
848 panic
"Can't find application process PID, are you sure it is \
849 running? Try using --start."
852 log
"Found process PID: $PID"
853 elif [ "$SANDBOXED" ]; then
854 echo "WARNING: --sandboxed option ignored due to use of --pid."
855 elif [ "$PRIVILEGED" ]; then
856 echo "WARNING: --privileged option ignored due to use of --pid."
859 # Determine if 'adb shell' runs as root or not.
860 # If so, we can launch gdbserver directly, otherwise, we have to
861 # use run-as $PACKAGE_NAME ..., which requires the package to be debuggable.
863 if [ "$SU_PREFIX" ]; then
864 # Need to check that this works properly.
865 SU_PREFIX_TEST_LOG
=$TMPDIR/su-prefix.log
866 adb_shell
$SU_PREFIX \"echo "foo"\" > $SU_PREFIX_TEST_LOG 2>&1
867 if [ $?
!= 0 -o "$(cat $SU_PREFIX_TEST_LOG)" != "foo" ]; then
868 echo "ERROR: Cannot use '$SU_PREFIX' as a valid su prefix:"
869 echo "$ adb shell $SU_PREFIX \"echo foo\""
870 cat $SU_PREFIX_TEST_LOG
873 COMMAND_PREFIX
="$SU_PREFIX \""
876 SHELL_UID
=$
(adb shell
cat /proc
/self
/status | \
877 awk '$1 == "Uid:" { print $2; }')
878 log
"Shell UID: $SHELL_UID"
879 if [ "$SHELL_UID" != 0 -o -n "$NO_ROOT" ]; then
880 COMMAND_PREFIX
="run-as $PACKAGE_NAME"
887 log
"Command prefix: '$COMMAND_PREFIX'"
888 log
"Command suffix: '$COMMAND_SUFFIX'"
890 # Pull device's system libraries that are mapped by our process.
891 # Pulling all system libraries is too long, so determine which ones
892 # we need by looking at /proc/$PID/maps instead
893 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
894 echo "Extracting system libraries into: $PULL_LIBS_DIR"
895 rm -f $PULL_LIBS_DIR/build.prop
896 MAPPINGS
=$
(adb_shell
$COMMAND_PREFIX cat /proc
/$PID/maps
$COMMAND_SUFFIX)
898 echo "ERROR: Could not list process's memory mappings."
899 if [ "$SU_PREFIX" ]; then
900 panic
"Are you sure your --su-prefix is correct?"
902 panic
"Use --su-prefix if the application is not debuggable."
905 SYSTEM_LIBS
=$
(echo "$MAPPINGS" | \
906 awk '$6 ~ /\/system\/.*\.so$/ { print $6; }' |
sort -u)
907 for SYSLIB
in /system
/bin
/linker
$SYSTEM_LIBS; do
908 echo "Pulling from device: $SYSLIB"
909 DST_FILE
=$PULL_LIBS_DIR$SYSLIB
910 DST_DIR
=$
(dirname "$DST_FILE")
911 mkdir
-p "$DST_DIR" && adb pull
$SYSLIB "$DST_FILE" 2>/dev
/null
912 fail_panic
"Could not pull $SYSLIB from device !?"
914 echo "Pulling device build.prop"
915 adb pull
/system
/build.prop
$PULL_LIBS_DIR/build.prop
916 fail_panic
"Could not pull device build.prop !?"
919 # Find all the sub-directories of $PULL_LIBS_DIR, up to depth 4
920 # so we can add them to solib-search-path later.
921 SOLIB_DIRS
=$
(find $PULL_LIBS_DIR -mindepth 1 -maxdepth 4 -type d | \
922 grep -v "^$" |
tr '\n' ':')
924 # This is a re-implementation of gdbclient, where we use compatible
925 # versions of gdbserver and $GDBNAME to ensure that everything works
929 # Push gdbserver to the device
930 log
"Pushing gdbserver $GDBSERVER to $TARGET_GDBSERVER"
931 adb push
$GDBSERVER $TMP_TARGET_GDBSERVER &>/dev
/null
932 adb shell
$COMMAND_PREFIX cp $TMP_TARGET_GDBSERVER $TARGET_GDBSERVER
933 adb shell
rm $TMP_TARGET_GDBSERVER
934 fail_panic
"Could not copy gdbserver to the device!"
940 # Select correct app_process for architecture.
942 arm|x86|mips
) GDBEXEC
=app_process
;;
943 arm64|x86_64
) GDBEXEC
=app_process64
;;
944 *) fail_panic
"Unknown app_process for architecture!";;
947 # Detect AddressSanitizer setup on the device. In that case app_process is a
948 # script, and the real executable is app_process.real.
949 GDBEXEC_ASAN
=app_process.real
950 adb_shell
ls /system
/bin
/$GDBEXEC_ASAN
952 GDBEXEC
=$GDBEXEC_ASAN
955 # Pull the app_process binary from the device.
956 log
"Pulling $GDBEXEC from device"
957 adb pull
/system
/bin
/$GDBEXEC "$TMPDIR"/$GDBEXEC &>/dev
/null
958 fail_panic
"Could not retrieve $GDBEXEC from the device!"
960 # Setup network redirection
961 log
"Setting network redirection (host:$HOST_PORT -> device:$TARGET_PORT)"
962 adb forward tcp
:$HOST_PORT tcp
:$TARGET_PORT
963 fail_panic
"Could not setup network redirection from \
964 host:localhost:$HOST_PORT to device:localhost:$TARGET_PORT!"
966 # Start gdbserver in the background
967 # Note that using run-as requires the package to be debuggable.
969 # If not, this will fail horribly. The alternative is to run the
970 # program as root, which requires of course root privileges.
971 # Maybe we should add a --root option to enable this?
973 log
"Starting gdbserver in the background:"
974 GDBSERVER_LOG
=$TMPDIR/gdbserver-
$TMP_ID.log
975 log
"adb shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
976 --attach $PID $COMMAND_SUFFIX"
977 ("$ADB" shell
$COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
978 --attach $PID $COMMAND_SUFFIX > $GDBSERVER_LOG 2>&1) &
980 echo "$GDBSERVER_PID" > $GDBSERVER_PIDFILE
981 log
"background job pid: $GDBSERVER_PID"
983 # Check that it is still running after a few seconds. If not, this means we
984 # could not properly attach to it
986 log
"Job control: $(jobs -l)"
987 STATE
=$
(jobs -l |
awk '$2 == "'$GDBSERVER_PID'" { print $3; }')
988 if [ "$STATE" != "Running" ]; then
989 echo "ERROR: GDBServer could not attach to PID $PID!"
990 if [ $
(adb_shell su
-c getenforce
) != "Permissive" ]; then
991 echo "Device mode is Enforcing. Changing Device mode to Permissive "
992 $
(adb_shell su
-c setenforce
0)
993 if [ $
(adb_shell su
-c getenforce
) != "Permissive" ]; then
994 echo "ERROR: Failed to Change Device mode to Permissive"
995 echo "Failure log (use --verbose for more information):"
1000 echo "Failure log (use --verbose for more information):"
1006 # Generate a file containing useful GDB initialization commands
1007 readonly COMMANDS
=$TMPDIR/gdb.init
1008 log
"Generating GDB initialization commands file: $COMMANDS"
1009 echo -n "" > $COMMANDS
1010 echo "set print pretty 1" >> $COMMANDS
1011 echo "python" >> $COMMANDS
1012 echo "import sys" >> $COMMANDS
1013 echo "sys.path.insert(0, '$CHROMIUM_SRC/tools/gdb/')" >> $COMMANDS
1014 echo "try:" >> $COMMANDS
1015 echo " import gdb_chrome" >> $COMMANDS
1016 echo "finally:" >> $COMMANDS
1017 echo " sys.path.pop(0)" >> $COMMANDS
1018 echo "end" >> $COMMANDS
1019 echo "file $TMPDIR/$GDBEXEC" >> $COMMANDS
1020 echo "directory $CHROMIUM_SRC" >> $COMMANDS
1021 echo "set solib-absolute-prefix $PULL_LIBS_DIR" >> $COMMANDS
1022 echo "set solib-search-path $SOLIB_DIRS:$PULL_LIBS_DIR:$SYMBOL_DIR" \
1024 echo "echo Attaching and reading symbols, this may take a while.." \
1026 echo "target remote :$HOST_PORT" >> $COMMANDS
1028 if [ "$GDBINIT" ]; then
1029 cat "$GDBINIT" >> $COMMANDS
1032 if [ "$VERBOSE" -gt 0 ]; then
1033 echo "### START $COMMANDS"
1035 echo "### END $COMMANDS"
1038 log
"Launching gdb client: $GDB $GDB_ARGS -x $COMMANDS"
1039 $GDB $GDB_ARGS -x $COMMANDS &&
1040 rm -f "$GDBSERVER_PIDFILE"