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