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 run-as
"$PACKAGE_NAME" 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 target device,
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
=$CHROMIUM_SRC/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 # Check that ADB is in our path
358 if [ -z "$ADB" ]; then
359 ADB
=$
(which adb
2>/dev
/null
)
360 if [ -z "$ADB" ]; then
361 panic
"Can't find 'adb' tool in your path. Install it or use \
364 log
"Auto-config: --adb=$ADB"
367 # Check that it works minimally
368 ADB_VERSION
=$
($ADB version
2>/dev
/null
)
369 echo "$ADB_VERSION" | fgrep
-q -e "Android Debug Bridge"
371 panic
"Your 'adb' tool seems invalid, use --adb=<file> to specify a \
375 # If there are more than one device connected, and ANDROID_SERIAL is not
376 # defined, print an error message.
377 NUM_DEVICES_PLUS2
=$
($ADB devices
2>/dev
/null |
wc -l)
378 if [ "$NUM_DEVICES_PLUS2" -lt 3 -a -z "$ANDROID_SERIAL" ]; then
379 echo "ERROR: There is more than one Android device connected to ADB."
380 echo "Please define ANDROID_SERIAL to specify which one to use."
384 # Run a command through adb shell, strip the extra \r from the output
385 # and return the correct status code to detect failures. This assumes
386 # that the adb shell command prints a final \n to stdout.
387 # $1+: command to run
388 # Out: command's stdout
389 # Return: command's status
390 # Note: the command's stderr is lost
392 local TMPOUT
="$(mktemp)"
394 local ADB
=${ADB:-adb}
396 # The weird sed rule is to strip the final \r on each output line
397 # Since 'adb shell' never returns the command's proper exit/status code,
398 # we force it to print it as '%%<status>' in the temporary output file,
399 # which we will later strip from it.
400 $ADB shell $@
";" echo "%%\$?" 2>/dev
/null | \
401 sed -e 's![[:cntrl:]]!!g' > $TMPOUT
402 # Get last line in log, which contains the exit code from the command
403 LASTLINE
=$
(sed -e '$!d' $TMPOUT)
404 # Extract the status code from the end of the line, which must
406 RET
=$
(echo "$LASTLINE" | \
407 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,RSTART+2); } }')
408 # Remove the status code from the last line. Note that this may result
410 LASTLINE
=$
(echo "$LASTLINE" | \
411 awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,1,RSTART-1); } }')
412 # The output itself: all lines except the status code.
413 sed -e '$d' $TMPOUT && printf "%s" "$LASTLINE"
416 # Exit with the appropriate status.
420 # Find the target architecture from the target device.
421 # This returns an NDK-compatible architecture name.
422 # out: NDK Architecture name, or empty string.
423 get_gyp_target_arch
() {
424 local ARCH
=$
(adb_shell getprop ro.product.cpu.abi
)
426 mips|x86|x86_64
) echo "$ARCH";;
427 arm64
*) echo "arm64";;
433 if [ -z "$TARGET_ARCH" ]; then
434 TARGET_ARCH
=$
(get_gyp_target_arch
)
435 if [ -z "$TARGET_ARCH" ]; then
439 # Nit: accept Chromium's 'ia32' as a valid target architecture. This
440 # script prefers the NDK 'x86' name instead because it uses it to find
441 # NDK-specific files (host gdb) with it.
442 if [ "$TARGET_ARCH" = "ia32" ]; then
444 log
"Auto-config: --arch=$TARGET_ARCH (equivalent to ia32)"
448 # Detect the NDK system name, i.e. the name used to identify the host.
449 # out: NDK system name (e.g. 'linux' or 'darwin')
450 get_ndk_host_system
() {
452 if [ -z "$NDK_HOST_SYSTEM" ]; then
455 Linux
) NDK_HOST_SYSTEM
=linux
;;
456 Darwin
) NDK_HOST_SYSTEM
=darwin
;;
457 *) panic
"You can't run this script on this system: $HOST_OS";;
460 echo "$NDK_HOST_SYSTEM"
463 # Detect the NDK host architecture name.
464 # out: NDK arch name (e.g. 'x86' or 'x86_64')
465 get_ndk_host_arch
() {
466 local HOST_ARCH HOST_OS
467 if [ -z "$NDK_HOST_ARCH" ]; then
468 HOST_OS
=$
(get_ndk_host_system
)
469 HOST_ARCH
=$
(uname
-p)
471 i?
86) NDK_HOST_ARCH
=x86
;;
472 x86_64|amd64
) NDK_HOST_ARCH
=x86_64
;;
473 *) panic
"You can't run this script on this host architecture: $HOST_ARCH";;
475 # Darwin trick: "uname -p" always returns i386 on 64-bit installations.
476 if [ "$HOST_OS" = darwin
-a "$NDK_HOST_ARCH" = "x86" ]; then
477 # Use '/usr/bin/file', not just 'file' to avoid buggy MacPorts
478 # implementations of the tool. See http://b.android.com/53769
479 HOST_64BITS
=$
(/usr
/bin
/file -L "$SHELL" |
grep -e "x86[_-]64")
480 if [ "$HOST_64BITS" ]; then
485 echo "$NDK_HOST_ARCH"
488 # Convert an NDK architecture name into a GNU configure triplet.
489 # $1: NDK architecture name (e.g. 'arm')
490 # Out: Android GNU configure triplet (e.g. 'arm-linux-androideabi')
491 get_arch_gnu_config
() {
494 echo "arm-linux-androideabi"
497 echo "aarch64-linux-android"
500 echo "i686-linux-android"
503 echo "x86_64-linux-android"
506 echo "mipsel-linux-android"
509 echo "$ARCH-linux-android"
514 # Convert an NDK architecture name into a toolchain name prefix
515 # $1: NDK architecture name (e.g. 'arm')
516 # Out: NDK toolchain name prefix (e.g. 'arm-linux-androideabi')
517 get_arch_toolchain_prefix
() {
518 # Return the configure triplet, except for x86!
519 if [ "$1" = "x86" ]; then
522 get_arch_gnu_config
$1
526 # Find a NDK toolchain prebuilt file or sub-directory.
527 # This will probe the various arch-specific toolchain directories
528 # in the NDK for the needed file.
529 # $1: NDK install path
530 # $2: NDK architecture name
531 # $3: prebuilt sub-path to look for.
532 # Out: file path, or empty if none is found.
533 get_ndk_toolchain_prebuilt
() {
534 local NDK_DIR
="${1%/}"
537 local NAME
="$(get_arch_toolchain_prefix $ARCH)"
539 FILE
=$NDK_DIR/toolchains
/$NAME-4.9
/prebuilt
/$SUBPATH
540 if [ ! -f "$FILE" ]; then
541 FILE
=$NDK_DIR/toolchains
/$NAME-4.8
/prebuilt
/$SUBPATH
542 if [ ! -f "$FILE" ]; then
549 # Find the path to an NDK's toolchain full prefix for a given architecture
550 # $1: NDK install path
551 # $2: NDK target architecture name
552 # Out: install path + binary prefix (e.g.
553 # ".../path/to/bin/arm-linux-androideabi-")
554 get_ndk_toolchain_fullprefix
() {
557 local TARGET NAME HOST_OS HOST_ARCH GCC CONFIG
559 # NOTE: This will need to be updated if the NDK changes the names or moves
560 # the location of its prebuilt toolchains.
563 HOST_OS
=$
(get_ndk_host_system
)
564 HOST_ARCH
=$
(get_ndk_host_arch
)
565 CONFIG
=$
(get_arch_gnu_config
$ARCH)
566 GCC
=$
(get_ndk_toolchain_prebuilt \
567 "$NDK_DIR" "$ARCH" "$HOST_OS-$HOST_ARCH/bin/$CONFIG-gcc")
568 if [ -z "$GCC" -a "$HOST_ARCH" = "x86_64" ]; then
569 GCC
=$
(get_ndk_toolchain_prebuilt \
570 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/$CONFIG-gcc")
572 if [ ! -f "$GCC" -a "$ARCH" = "x86" ]; then
573 # Special case, the x86 toolchain used to be incorrectly
574 # named i686-android-linux-gcc!
575 GCC
=$
(get_ndk_toolchain_prebuilt \
576 "$NDK_DIR" "$ARCH" "$HOST_OS-x86/bin/i686-android-linux-gcc")
578 if [ -z "$GCC" ]; then
579 panic
"Cannot find Android NDK toolchain for '$ARCH' architecture. \
580 Please verify your NDK installation!"
585 # $1: NDK install path
586 # $2: target architecture.
587 get_ndk_gdbserver
() {
592 # The location has moved after NDK r8
593 BINARY
=$NDK_DIR/prebuilt
/android-
$ARCH/gdbserver
/gdbserver
594 if [ ! -f "$BINARY" ]; then
595 BINARY
=$
(get_ndk_toolchain_prebuilt
"$NDK_DIR" "$ARCH" gdbserver
)
600 # Check/probe the path to the Android toolchain installation. Always
601 # use the NDK versions of gdb and gdbserver. They must match to avoid
602 # issues when both binaries do not speak the same wire protocol.
604 if [ -z "$TOOLCHAIN" ]; then
605 ANDROID_TOOLCHAIN
=$
(get_ndk_toolchain_fullprefix \
606 "$ANDROID_NDK_ROOT" "$TARGET_ARCH")
607 ANDROID_TOOLCHAIN
=$
(dirname "$ANDROID_TOOLCHAIN")
608 log
"Auto-config: --toolchain=$ANDROID_TOOLCHAIN"
610 # Be flexible, allow one to specify either the install path or the bin
611 # sub-directory in --toolchain:
613 if [ -d "$TOOLCHAIN/bin" ]; then
614 TOOLCHAIN
=$TOOLCHAIN/bin
616 ANDROID_TOOLCHAIN
=$TOOLCHAIN
619 # Cosmetic: Remove trailing directory separator.
620 ANDROID_TOOLCHAIN
=${ANDROID_TOOLCHAIN%/}
622 # Find host GDB client binary
623 if [ -z "$GDB" ]; then
624 GDB
=$
(which $ANDROID_TOOLCHAIN/*-$GDBEXEPOSTFIX 2>/dev
/null |
head -1)
625 if [ -z "$GDB" ]; then
626 panic
"Can't find Android gdb client in your path, check your \
627 --toolchain or --gdb path."
629 log
"Host gdb client: $GDB"
632 # Find gdbserver binary, we will later push it to /data/local/tmp
633 # This ensures that both gdbserver and $GDB talk the same binary protocol,
634 # otherwise weird problems will appear.
636 if [ -z "$GDBSERVER" ]; then
637 GDBSERVER
=$
(get_ndk_gdbserver
"$ANDROID_NDK_ROOT" "$TARGET_ARCH")
638 if [ -z "$GDBSERVER" ]; then
639 panic
"Can't find NDK gdbserver binary. use --gdbserver to specify \
642 log
"Auto-config: --gdbserver=$GDBSERVER"
645 # A unique ID for this script's session. This needs to be the same in all
646 # sub-shell commands we're going to launch, so take the PID of the launcher
650 # Temporary directory, will get cleaned up on exit.
651 TMPDIR
=/tmp
/$USER-adb-gdb-tmp-$TMP_ID
652 mkdir
-p "$TMPDIR" && rm -rf "$TMPDIR"/*
654 GDBSERVER_PIDFILE
="$TMPDIR"/gdbserver-
$TMP_ID.pid
656 # If --force is specified, try to kill any gdbserver process started by the
657 # same user on the device. Normally, these are killed automatically by the
658 # script on exit, but there are a few corner cases where this would still
660 if [ "$FORCE" ]; then
661 GDBSERVER_PIDS
=$
(adb_shell ps |
awk '$9 ~ /gdbserver/ { print $2; }')
662 for GDB_PID
in $GDBSERVER_PIDS; do
663 log
"Killing previous gdbserver (PID=$GDB_PID)"
664 adb_shell
kill -9 $GDB_PID
668 if [ "$START" ]; then
669 log
"Starting $PROGRAM_NAME on device."
670 adb_shell am start
-n $PACKAGE_NAME/$ACTIVITY 2>/dev
/null
671 adb_shell ps |
grep -q $PACKAGE_NAME
672 fail_panic
"Could not start $PROGRAM_NAME on device. Are you sure the \
673 package is installed?"
676 # Return the timestamp of a given time, as number of seconds since epoch.
678 # Out: file timestamp
679 get_file_timestamp
() {
680 stat
-c %Y
"$1" 2>/dev
/null
683 # Detect the build type and symbol directory. This is done by finding
684 # the most recent sub-directory containing debug shared libraries under
685 # $CHROMIUM_SRC/$CHROMIUM_OUT_DIR/
687 # $1: $BUILDTYPE value, can be empty
688 # Out: nothing, but this sets SYMBOL_DIR
690 detect_symbol_dir
() {
691 local SUBDIRS SUBDIR LIST DIR DIR_LIBS TSTAMP
692 # Note: Ninja places debug libraries under out/$BUILDTYPE/lib/, while
693 # Make places then under out/$BUILDTYPE/lib.target.
695 SUBDIRS
="$1/lib $1/lib.target"
697 SUBDIRS
="Release/lib Debug/lib Release/lib.target Debug/lib.target"
699 LIST
=$TMPDIR/scan-subdirs-$$.txt
701 for SUBDIR
in $SUBDIRS; do
702 DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
703 if [ -d "$DIR" ]; then
704 # Ignore build directories that don't contain symbol versions
705 # of the shared libraries.
706 DIR_LIBS
=$
(ls "$DIR"/lib
*.so
2>/dev
/null
)
707 if [ -z "$DIR_LIBS" ]; then
708 echo "No shared libs: $DIR"
711 TSTAMP
=$
(get_file_timestamp
"$DIR")
712 printf "%s %s\n" "$TSTAMP" "$SUBDIR" >> "$LIST"
715 SUBDIR
=$
(cat $LIST |
sort -r |
head -1 | cut
-d" " -f2)
718 if [ -z "$SUBDIR" ]; then
720 panic
"Could not find any build directory under \
721 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Please build the program first!"
723 panic
"Could not find any $1 directory under \
724 $CHROMIUM_SRC/$CHROMIUM_OUT_DIR. Check your build type!"
728 SYMBOL_DIR
=$CHROMIUM_SRC/$CHROMIUM_OUT_DIR/$SUBDIR
729 log
"Auto-config: --symbol-dir=$SYMBOL_DIR"
732 if [ -z "$SYMBOL_DIR" ]; then
733 detect_symbol_dir
"$BUILDTYPE"
736 # Allow several concurrent debugging sessions
737 TARGET_GDBSERVER
=/data
/data
/$PACKAGE_NAME/gdbserver-adb-gdb-
$TMP_ID
738 TMP_TARGET_GDBSERVER
=/data
/local
/tmp
/gdbserver-adb-gdb-
$TMP_ID
740 # Return the build fingerprint contained in a build.prop file.
741 # $1: path to build.prop file
742 get_build_fingerprint_from
() {
743 cat "$1" |
grep -e '^ro.build.fingerprint=' | cut
-d= -f2
747 ORG_PULL_LIBS_DIR
=$PULL_LIBS_DIR
748 PULL_LIBS_DIR
=${PULL_LIBS_DIR:-$DEFAULT_PULL_LIBS_DIR}
751 DEVICE_FINGERPRINT
=$
(adb_shell getprop ro.build.fingerprint
)
752 log
"Device build fingerprint: $DEVICE_FINGERPRINT"
754 # If --pull-libs-dir is not specified, and this is a platform build, look
755 # if we can use the symbolic libraries under $ANDROID_PRODUCT_OUT/symbols/
756 # directly, if the build fingerprint matches the device.
757 if [ -z "$ORG_PULL_LIBS_DIR" -a \
758 "$ANDROID_PRODUCT_OUT" -a \
759 -f "$ANDROID_PRODUCT_OUT/system/build.prop" ]; then
760 ANDROID_FINGERPRINT
=$
(get_build_fingerprint_from \
761 "$ANDROID_PRODUCT_OUT"/system
/build.prop
)
762 log
"Android build fingerprint: $ANDROID_FINGERPRINT"
763 if [ "$ANDROID_FINGERPRINT" = "$DEVICE_FINGERPRINT" ]; then
765 PULL_LIBS_DIR
=$ANDROID_PRODUCT_OUT/symbols
766 HOST_FINGERPRINT
=$ANDROID_FINGERPRINT
767 if [ "$PULL_LIBS" ]; then
768 log
"Ignoring --pull-libs since the device and platform build \
775 # If neither --pull-libs an --no-pull-libs were specified, check the build
776 # fingerprints of the device, and the cached system libraries on the host.
778 if [ -z "$NO_PULL_LIBS" -a -z "$PULL_LIBS" ]; then
779 if [ ! -f "$PULL_LIBS_DIR/build.prop" ]; then
780 log
"Auto-config: --pull-libs (no cached libraries)"
783 HOST_FINGERPRINT
=$
(get_build_fingerprint_from
"$PULL_LIBS_DIR/build.prop")
784 log
"Host build fingerprint: $HOST_FINGERPRINT"
785 if [ "$HOST_FINGERPRINT" == "$DEVICE_FINGERPRINT" ]; then
786 log
"Auto-config: --no-pull-libs (fingerprint match)"
789 log
"Auto-config: --pull-libs (fingerprint mismatch)"
795 # Extract the system libraries from the device if necessary.
796 if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then
797 echo "Extracting system libraries into: $PULL_LIBS_DIR"
800 mkdir
-p "$PULL_LIBS_DIR"
801 fail_panic
"Can't create --libs-dir directory: $PULL_LIBS_DIR"
803 # If requested, work for M-x gdb. The gdb indirections make it
804 # difficult to pass --annotate=3 to the gdb binary itself.
806 if [ "$ANNOTATE" ]; then
807 GDB_ARGS
=$GDB_ARGS" --annotate=$ANNOTATE"
810 # Get the PID from the first argument or else find the PID of the
812 if [ -z "$PID" ]; then
813 PROCESSNAME
=$PACKAGE_NAME
814 if [ "$SANDBOXED_INDEX" ]; then
815 PROCESSNAME
=$PROCESSNAME:sandboxed_process
$SANDBOXED_INDEX
816 elif [ "$SANDBOXED" ]; then
817 PROCESSNAME
=$PROCESSNAME:sandboxed_process
818 PID
=$
(adb_shell ps | \
819 awk '$9 ~ /^'$PROCESSNAME'/ { print $2; }' |
head -1)
821 if [ -z "$PID" ]; then
822 PID
=$
(adb_shell ps | \
823 awk '$9 == "'$PROCESSNAME'" { print $2; }' |
head -1)
825 if [ -z "$PID" ]; then
826 if [ "$START" ]; then
827 panic
"Can't find application process PID, did it crash?"
829 panic
"Can't find application process PID, are you sure it is \
830 running? Try using --start."
833 log
"Found process PID: $PID"
834 elif [ "$SANDBOXED" ]; then
835 echo "WARNING: --sandboxed option ignored due to use of --pid."
838 # Determine if 'adb shell' runs as root or not.
839 # If so, we can launch gdbserver directly, otherwise, we have to
840 # use run-as $PACKAGE_NAME ..., which requires the package to be debuggable.
842 if [ "$SU_PREFIX" ]; then
843 # Need to check that this works properly.
844 SU_PREFIX_TEST_LOG
=$TMPDIR/su-prefix.log
845 adb_shell
$SU_PREFIX \"echo "foo"\" > $SU_PREFIX_TEST_LOG 2>&1
846 if [ $?
!= 0 -o "$(cat $SU_PREFIX_TEST_LOG)" != "foo" ]; then
847 echo "ERROR: Cannot use '$SU_PREFIX' as a valid su prefix:"
848 echo "$ adb shell $SU_PREFIX \"echo foo\""
849 cat $SU_PREFIX_TEST_LOG
852 COMMAND_PREFIX
="$SU_PREFIX \""
855 SHELL_UID
=$
(adb shell
cat /proc
/self
/status | \
856 awk '$1 == "Uid:" { print $2; }')
857 log
"Shell UID: $SHELL_UID"
858 if [ "$SHELL_UID" != 0 -o -n "$NO_ROOT" ]; then
859 COMMAND_PREFIX
="run-as $PACKAGE_NAME"
866 log
"Command prefix: '$COMMAND_PREFIX'"
867 log
"Command suffix: '$COMMAND_SUFFIX'"
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
$COMMAND_SUFFIX)
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 $TMP_TARGET_GDBSERVER &>/dev
/null
911 adb shell run-as
$PACKAGE_NAME cp $TMP_TARGET_GDBSERVER .
912 adb shell
rm $TMP_TARGET_GDBSERVER
913 fail_panic
"Could not copy gdbserver to the device!"
919 # Select correct app_process for architecture.
921 arm|x86|mips
) GDBEXEC
=app_process
;;
922 arm64|x86_64
) GDBEXEC
=app_process64
;;
923 *) fail_panic
"Unknown app_process for architecture!";;
926 # Detect AddressSanitizer setup on the device. In that case app_process is a
927 # script, and the real executable is app_process.real.
928 GDBEXEC_ASAN
=app_process.real
929 adb_shell
ls /system
/bin
/$GDBEXEC_ASAN
931 GDBEXEC
=$GDBEXEC_ASAN
934 # Pull the app_process binary from the device.
935 log
"Pulling $GDBEXEC from device"
936 adb pull
/system
/bin
/$GDBEXEC "$TMPDIR"/$GDBEXEC &>/dev
/null
937 fail_panic
"Could not retrieve $GDBEXEC from the device!"
939 # Setup network redirection
940 log
"Setting network redirection (host:$HOST_PORT -> device:$TARGET_PORT)"
941 adb forward tcp
:$HOST_PORT tcp
:$TARGET_PORT
942 fail_panic
"Could not setup network redirection from \
943 host:localhost:$HOST_PORT to device:localhost:$TARGET_PORT!"
945 # Start gdbserver in the background
946 # Note that using run-as requires the package to be debuggable.
948 # If not, this will fail horribly. The alternative is to run the
949 # program as root, which requires of course root privileges.
950 # Maybe we should add a --root option to enable this?
952 log
"Starting gdbserver in the background:"
953 GDBSERVER_LOG
=$TMPDIR/gdbserver-
$TMP_ID.log
954 log
"adb shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
955 --attach $PID $COMMAND_SUFFIX"
956 ("$ADB" shell
$COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \
957 --attach $PID $COMMAND_SUFFIX > $GDBSERVER_LOG 2>&1) &
959 echo "$GDBSERVER_PID" > $GDBSERVER_PIDFILE
960 log
"background job pid: $GDBSERVER_PID"
962 # Check that it is still running after a few seconds. If not, this means we
963 # could not properly attach to it
965 log
"Job control: $(jobs -l)"
966 STATE
=$
(jobs -l |
awk '$2 == "'$GDBSERVER_PID'" { print $3; }')
967 if [ "$STATE" != "Running" ]; then
968 echo "ERROR: GDBServer could not attach to PID $PID!"
969 if [ $
(adb_shell su
-c getenforce
) != "Permissive" ]; then
970 echo "Device mode is Enforcing. Changing Device mode to Permissive "
971 $
(adb_shell su
-c setenforce
0)
972 if [ $
(adb_shell su
-c getenforce
) != "Permissive" ]; then
973 echo "ERROR: Failed to Change Device mode to Permissive"
974 echo "Failure log (use --verbose for more information):"
979 echo "Failure log (use --verbose for more information):"
985 # Generate a file containing useful GDB initialization commands
986 readonly COMMANDS
=$TMPDIR/gdb.init
987 log
"Generating GDB initialization commands file: $COMMANDS"
988 echo -n "" > $COMMANDS
989 echo "set print pretty 1" >> $COMMANDS
990 echo "python" >> $COMMANDS
991 echo "import sys" >> $COMMANDS
992 echo "sys.path.insert(0, '$CHROMIUM_SRC/tools/gdb/')" >> $COMMANDS
993 echo "try:" >> $COMMANDS
994 echo " import gdb_chrome" >> $COMMANDS
995 echo "finally:" >> $COMMANDS
996 echo " sys.path.pop(0)" >> $COMMANDS
997 echo "end" >> $COMMANDS
998 echo "file $TMPDIR/$GDBEXEC" >> $COMMANDS
999 echo "directory $CHROMIUM_SRC" >> $COMMANDS
1000 echo "set solib-absolute-prefix $PULL_LIBS_DIR" >> $COMMANDS
1001 echo "set solib-search-path $SOLIB_DIRS:$PULL_LIBS_DIR:$SYMBOL_DIR" \
1003 echo "echo Attaching and reading symbols, this may take a while.." \
1005 echo "target remote :$HOST_PORT" >> $COMMANDS
1007 if [ "$GDBINIT" ]; then
1008 cat "$GDBINIT" >> $COMMANDS
1011 if [ "$VERBOSE" -gt 0 ]; then
1012 echo "### START $COMMANDS"
1014 echo "### END $COMMANDS"
1017 log
"Launching gdb client: $GDB $GDB_ARGS -x $COMMANDS"
1018 $GDB $GDB_ARGS -x $COMMANDS &&
1019 rm -f "$GDBSERVER_PIDFILE"