Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
michael@0 | 1 | #!/bin/bash |
michael@0 | 2 | # |
michael@0 | 3 | # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 4 | # Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | # found in the LICENSE file. |
michael@0 | 6 | # |
michael@0 | 7 | # Attach gdb to a running android application. Similar to ndk-gdb. |
michael@0 | 8 | # Run with --annotate=3 if running under emacs (M-x gdb). |
michael@0 | 9 | # |
michael@0 | 10 | # By default it is used to debug content shell, if it is used to |
michael@0 | 11 | # debug other piceces, '-p' and '-l' options are needed. |
michael@0 | 12 | # For *unittests_apk (like base_unittests_apk), run with: |
michael@0 | 13 | # "gdb_apk -p org.chromium.native_test -l out/Release/lib.target -r" |
michael@0 | 14 | |
michael@0 | 15 | # Run a command through adb shell, strip the extra \r from the output |
michael@0 | 16 | # and return the correct status code to detect failures. This assumes |
michael@0 | 17 | # that the adb shell command prints a final \n to stdout. |
michael@0 | 18 | # args: command to run |
michael@0 | 19 | # Prints the command's stdout on stdout |
michael@0 | 20 | # Returns the command's status |
michael@0 | 21 | # Note: the command's stderr is lost |
michael@0 | 22 | adb_shell () { |
michael@0 | 23 | local TMPOUT="$(mktemp)" |
michael@0 | 24 | local LASTLINE RET |
michael@0 | 25 | local ADB=${ADB:-adb} |
michael@0 | 26 | |
michael@0 | 27 | # The weird sed rule is to strip the final \r on each output line |
michael@0 | 28 | # Since 'adb shell' never returns the command's proper exit/status code, |
michael@0 | 29 | # we force it to print it as '%%<status>' in the temporary output file, |
michael@0 | 30 | # which we will later strip from it. |
michael@0 | 31 | $ADB shell $@ ";" echo "%%\$?" 2>/dev/null | sed -e 's![[:cntrl:]]!!g' > $TMPOUT |
michael@0 | 32 | # Get last line in log, which contains the exit code from the command |
michael@0 | 33 | LASTLINE=$(sed -e '$!d' $TMPOUT) |
michael@0 | 34 | # Extract the status code from the end of the line, which must be '%%<code>' |
michael@0 | 35 | RET=$(echo "$LASTLINE" | awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,RSTART+2); } }') |
michael@0 | 36 | # Remove the status code from the last line. Note that this may result in an empty line |
michael@0 | 37 | LASTLINE=$(echo "$LASTLINE" | awk '{ if (match($0, "%%[0-9]+$")) { print substr($0,1,RSTART-1); } }') |
michael@0 | 38 | # The output itself: all lines except the status code |
michael@0 | 39 | sed -e '$d' $TMPOUT && echo -n "$LASTLINE" |
michael@0 | 40 | # Remove temp file |
michael@0 | 41 | rm -f $TMPOUT |
michael@0 | 42 | # Exit with the appropriate status |
michael@0 | 43 | return $RET |
michael@0 | 44 | } |
michael@0 | 45 | |
michael@0 | 46 | adb=$(which adb) |
michael@0 | 47 | if [[ "$adb" = "" ]] ; then |
michael@0 | 48 | echo "Need adb in your path" |
michael@0 | 49 | exit 1 |
michael@0 | 50 | fi |
michael@0 | 51 | |
michael@0 | 52 | usage() { |
michael@0 | 53 | echo "usage: ${0##*/} [-p package_name] [-l shared_lib_dir] [-g gdb] [-r]" |
michael@0 | 54 | echo "-p package_name the android APK package to be debugged" |
michael@0 | 55 | echo "-l shared_lib_dir directory containes native shared library" |
michael@0 | 56 | echo "-g gdb_args agruments for gdb, eg: -g '-n -write'" |
michael@0 | 57 | echo "-r the target device is rooted" |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | process_options() { |
michael@0 | 61 | local OPTNAME OPTIND OPTERR OPTARG |
michael@0 | 62 | while getopts ":p:l:g:r" OPTNAME; do |
michael@0 | 63 | case "$OPTNAME" in |
michael@0 | 64 | p) |
michael@0 | 65 | package_name="$OPTARG" |
michael@0 | 66 | ;; |
michael@0 | 67 | l) |
michael@0 | 68 | shared_lib_dir="$OPTARG" |
michael@0 | 69 | ;; |
michael@0 | 70 | g) |
michael@0 | 71 | gdb_args="$OPTARG" |
michael@0 | 72 | ;; |
michael@0 | 73 | r) |
michael@0 | 74 | rooted_phone=1 |
michael@0 | 75 | ;; |
michael@0 | 76 | \:) |
michael@0 | 77 | echo "'-$OPTARG' needs an argument." |
michael@0 | 78 | usage |
michael@0 | 79 | exit 1 |
michael@0 | 80 | ;; |
michael@0 | 81 | *) |
michael@0 | 82 | echo "invalid command line option: $OPTARG" |
michael@0 | 83 | usage |
michael@0 | 84 | exit 1 |
michael@0 | 85 | ;; |
michael@0 | 86 | esac |
michael@0 | 87 | done |
michael@0 | 88 | |
michael@0 | 89 | if [ $# -ge ${OPTIND} ]; then |
michael@0 | 90 | eval echo "Unexpected command line argument: \${${OPTIND}}" |
michael@0 | 91 | usage |
michael@0 | 92 | exit 1 |
michael@0 | 93 | fi |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | rooted_phone=0 |
michael@0 | 97 | |
michael@0 | 98 | root=$(dirname $0)/../.. |
michael@0 | 99 | package_name=org.chromium.content_shell |
michael@0 | 100 | shared_lib_dir=$root/out/${BUILDTYPE:-Debug}/lib.target |
michael@0 | 101 | gdb_args='' |
michael@0 | 102 | |
michael@0 | 103 | #process options |
michael@0 | 104 | process_options "$@" |
michael@0 | 105 | echo "Debug package $package_name" |
michael@0 | 106 | echo "Assume native shared library is under $shared_lib_dir" |
michael@0 | 107 | |
michael@0 | 108 | data_dir=/data/data/$package_name |
michael@0 | 109 | gdb_server_on_device=$data_dir/lib/gdbserver |
michael@0 | 110 | |
michael@0 | 111 | # Kill any running gdbserver |
michael@0 | 112 | pid=$(adb shell ps | awk '/gdbserver/ {print $2}') |
michael@0 | 113 | if [[ "$pid" != "" ]] ; then |
michael@0 | 114 | if [[ $rooted_phone -eq 1 ]] ; then |
michael@0 | 115 | adb shell kill $pid |
michael@0 | 116 | else |
michael@0 | 117 | adb shell run-as $package_name kill $pid |
michael@0 | 118 | fi |
michael@0 | 119 | fi |
michael@0 | 120 | |
michael@0 | 121 | pid=$(adb_shell ps | awk "/$package_name$/ {print \$2}") |
michael@0 | 122 | if [[ "$pid" = "" ]] ; then |
michael@0 | 123 | echo "No $package_name running?" |
michael@0 | 124 | echo "Try this: adb shell am start -a android.intent.action.VIEW " \ |
michael@0 | 125 | "-n $package_name/.SomethingActivity (Something might be ContentShell)" |
michael@0 | 126 | exit 2 |
michael@0 | 127 | fi |
michael@0 | 128 | |
michael@0 | 129 | no_gdb_server=$(adb shell ls $gdb_server_on_device | grep 'No such file') |
michael@0 | 130 | if [[ "$no_gdb_server" != "" ]] ; then |
michael@0 | 131 | echo "No gdb server on device at $gdb_server_on_device" |
michael@0 | 132 | echo "Please install a debug build." |
michael@0 | 133 | exit 3 |
michael@0 | 134 | fi |
michael@0 | 135 | |
michael@0 | 136 | if [[ $rooted_phone -eq 1 ]] ; then |
michael@0 | 137 | adb shell $gdb_server_on_device :4321 --attach $pid & |
michael@0 | 138 | adb forward tcp:4321 tcp:4321 |
michael@0 | 139 | else |
michael@0 | 140 | adb shell run-as $package_name lib/gdbserver +debug-socket --attach $pid & |
michael@0 | 141 | adb forward tcp:4321 localfilesystem:$data_dir/debug-socket |
michael@0 | 142 | fi |
michael@0 | 143 | sleep 2 |
michael@0 | 144 | |
michael@0 | 145 | # Pull app_process and C libraries from device if needed |
michael@0 | 146 | app_process=${shared_lib_dir}/app_process |
michael@0 | 147 | if [[ ! -f ${app_process} ]] ; then |
michael@0 | 148 | adb pull /system/bin/app_process ${app_process} |
michael@0 | 149 | adb pull /system/lib/libc.so ${shared_lib_dir} |
michael@0 | 150 | fi |
michael@0 | 151 | |
michael@0 | 152 | # gdb commands |
michael@0 | 153 | cmdfile=$(mktemp /tmp/gdb_android_XXXXXXXX) |
michael@0 | 154 | cat >$cmdfile<<EOF |
michael@0 | 155 | # set solib-absolute-prefix null |
michael@0 | 156 | set solib-search-path ${shared_lib_dir} |
michael@0 | 157 | file ${app_process} |
michael@0 | 158 | target remote :4321 |
michael@0 | 159 | EOF |
michael@0 | 160 | |
michael@0 | 161 | gdb=$(echo $ANDROID_TOOLCHAIN/../../linux-x86/bin/*gdb) |
michael@0 | 162 | if [[ ! -f ${gdb} ]] ; then |
michael@0 | 163 | echo "Wow no gdb in env var ANDROID_TOOLCHAIN which is $ANDROID_TOOLCHAIN" |
michael@0 | 164 | exit 4 |
michael@0 | 165 | else |
michael@0 | 166 | echo Using $gdb |
michael@0 | 167 | fi |
michael@0 | 168 | |
michael@0 | 169 | # ${gdb} -x $cmdfile $* $app_process |
michael@0 | 170 | ${gdb} -x $cmdfile $gdb_args |
michael@0 | 171 | rm $cmdfile |