blob: e4fbfffe194dab4af6d556ecc340587b53f404e8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
#!/bin/bash
# TODO:
# 1. Check for ANDROID_SERIAL/multiple devices
if [ -z "$ANDROID_BUILD_TOP" ]; then
>&2 echo '$ANDROID_BUILD_TOP is not set. Source build/envsetup.sh.'
exit 1
fi
# We can use environment variables (like ANDROID_BUILD_TOP) from the user's
# shell, but not functions (like gettop), so we need to source envsetup in here
# as well.
source $ANDROID_BUILD_TOP/build/envsetup.sh
echo
function adb_get_product_device() {
local candidate=`adb shell getprop ro.hardware | tr -d '\r\n'`
if [[ "$candidate" =~ ^(goldfish|ranchu)$ ]]; then
# Emulator builds use product.device for OUT folder
candidate=`adb shell getprop ro.product.device | tr -d '\r\n'`
fi
echo $candidate
}
# returns 0 when process is not traced
function adb_get_traced_by() {
echo `adb shell cat /proc/$1/status | grep -e "^TracerPid:" | sed "s/^TracerPid:\t//" | tr -d '\r\n'`
}
function get_symbols_directory()
{
echo $(get_abs_build_var TARGET_OUT_UNSTRIPPED)
}
function gdbwrapper()
{
local GDB_CMD="$1"
shift 1
$GDB_CMD -x "$@"
}
function gdbclient() {
local PROCESS_NAME="n/a"
local PID=$1
local PORT=5039
if [ -z "$PID" ]; then
echo "Usage: gdbclient <pid|processname> [port number]"
return -1
fi
local DEVICE=$(adb_get_product_device)
local ROOT=$(gettop)
if [ -z "$ROOT" ]; then
# This is for the situation with downloaded symbols (from the build server)
# we check if they are available.
ROOT=`realpath .`
fi
if [[ -z "$DEVICE" || ! -d "$ROOT/out/target/product/$DEVICE" ]]; then
if [ -z "$CM_BUILD" ]; then
echo "Error: Unable to get device name. Please check if device is connected and ANDROID_SERIAL is set."
return -2
fi
DEVICE=$CM_BUILD
fi
if [ -n "$2" ]; then
PORT=$2
fi
local SYS_OUT_ROOT=$(get_build_var OUT_DIR)
local OUT_ROOT="${SYS_OUT_ROOT:-${OUT_DIR:-$ROOT/out}}/target/product/$DEVICE"
local SYMBOLS_DIR="$OUT_ROOT/symbols"
local IS_TAPAS_USER="$(get_build_var TARGET_BUILD_APPS)"
local TAPAS_SYMBOLS_DIR=
if [ $IS_TAPAS_USER ]; then
TAPAS_SYMBOLS_DIR=$(get_symbols_directory)
fi
if [ ! -d $SYMBOLS_DIR ]; then
if [ $IS_TAPAS_USER ]; then
mkdir -p $SYMBOLS_DIR/system/bin
else
echo "Error: couldn't find symbols: $SYMBOLS_DIR does not exist or is not a directory."
return -3
fi
fi
# let's figure out which executable we are about to debug
# check if user specified a name -> resolve to pid
if [[ ! "$PID" =~ ^[0-9]+$ ]] ; then
PROCESS_NAME=$PID
PIDS=( $(adb shell "pidof $PROCESS_NAME 2> /dev/null" | tr -d '\r\n') )
if [[ ${#PIDS[@]} == 0 ]]; then
echo "Error: couldn't resolve pid by process name: $PROCESS_NAME"
return -4
elif [[ ${#PIDS[@]} != 1 ]]; then
echo "Error: more than one 1 PID resolved by process name: $PROCESS_NAME"
echo " PIDs -> ${PIDS[@]}"
return -5
fi
PID="${PIDS[0]}"
echo "Resolved pid for $PROCESS_NAME is [$PID]"
fi
local ID=`adb shell id -u`
if [ "$ID" != "0" ]; then
echo "Error: gdbclient only works if you've run 'adb root'"
return -4
fi
local EXE=`adb shell readlink /proc/$PID/exe | tr -d '\r\n'`
if [ -z "$EXE" ]; then
echo "Error: couldn't find executable for pid $PID --- is the process still alive?"
return -4
fi
local LOCAL_EXE_PATH=$SYMBOLS_DIR$EXE
if [ ! -f $LOCAL_EXE_PATH ]; then
if [ $IS_TAPAS_USER ]; then
adb pull $EXE $LOCAL_EXE_PATH
else
echo "Error: unable to find symbols for executable $EXE: file $LOCAL_EXE_PATH does not exist"
return -5
fi
fi
local USE64BIT=""
if [[ "$(file $LOCAL_EXE_PATH)" =~ 64-bit ]]; then
USE64BIT="64"
fi
# and now linker for tapas users...
if [ -n "$IS_TAPAS_USER" -a ! -f "$SYMBOLS_DIR/system/bin/linker$USE64BIT" ]; then
adb pull /system/bin/linker$USE64BIT $SYMBOLS_DIR/system/bin/linker$USE64BIT
fi
local GDB
case $(uname -s) in
Darwin)
GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/darwin-x86/bin/gdb
;;
Linux)
GDB=$ANDROID_BUILD_TOP/prebuilts/gdb/linux-x86/bin/gdb
;;
*)
echo "Error: Unknown platform '$(uname -s)'"
return 1
;;
esac
local CPU_ABI=`adb shell getprop ro.product.cpu.abilist | tr -d '\r\n'`
# TODO: check if tracing process is gdbserver and not some random strace...
if [ "$(adb_get_traced_by $PID)" -eq 0 ]; then
# start gdbserver
echo "Starting gdbserver..."
# TODO: check if adb is already listening $PORT
# to avoid unnecessary calls
echo ". adb forward for port=$PORT..."
adb forward tcp:$PORT tcp:$PORT
echo ". starting gdbserver to attach to pid=$PID..."
adb shell gdbserver$USE64BIT :$PORT --attach $PID &
echo ". give it couple of seconds to start..."
sleep 2
echo ". done"
else
echo "It looks like gdbserver is already attached to $PID (process is traced), trying to connect to it using local port=$PORT"
adb forward tcp:$PORT tcp:$PORT
fi
local OUT_SO_SYMBOLS=$SYMBOLS_DIR/system/lib$USE64BIT
local TAPAS_OUT_SO_SYMBOLS=$TAPAS_SYMBOLS_DIR/system/lib$USE64BIT
local OUT_VENDOR_SO_SYMBOLS=$SYMBOLS_DIR/vendor/lib$USE64BIT
local ART_CMD=""
local SOLIB_SYSROOT=$SYMBOLS_DIR
local SOLIB_SEARCHPATH=$OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines:$OUT_SO_SYMBOLS/drm:$OUT_SO_SYMBOLS/egl:$OUT_SO_SYMBOLS/soundfx:$OUT_VENDOR_SO_SYMBOLS:$OUT_VENDOR_SO_SYMBOLS/hw:$OUT_VENDOR_SO_SYMBOLS/egl
if [ $IS_TAPAS_USER ]; then
SOLIB_SYSROOT=$TAPAS_SYMBOLS_DIR:$SOLIB_SYSROOT
SOLIB_SEARCHPATH=$TAPAS_OUT_SO_SYMBOLS:$SOLIB_SEARCHPATH
fi
echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $SOLIB_SYSROOT"
echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $SOLIB_SEARCHPATH"
local DALVIK_GDB_SCRIPT=$ROOT/development/scripts/gdb/dalvik.gdb
if [ -f $DALVIK_GDB_SCRIPT ]; then
echo >>"$OUT_ROOT/gdbclient.cmds" "source $DALVIK_GDB_SCRIPT"
ART_CMD="art-on"
else
echo "Warning: couldn't find $DALVIK_GDB_SCRIPT - ART debugging options will not be available"
fi
echo >>"$OUT_ROOT/gdbclient.cmds" "target remote :$PORT"
if [[ $EXE =~ (^|/)(app_process|dalvikvm)(|32|64)$ ]]; then
echo >> "$OUT_ROOT/gdbclient.cmds" $ART_CMD
fi
echo >>"$OUT_ROOT/gdbclient.cmds" ""
gdbwrapper $GDB "$OUT_ROOT/gdbclient.cmds" "$LOCAL_EXE_PATH"
}
gdbclient $*
|