aboutsummaryrefslogtreecommitdiffstats
path: root/java/debug.sh
diff options
context:
space:
mode:
Diffstat (limited to 'java/debug.sh')
-rwxr-xr-xjava/debug.sh242
1 files changed, 242 insertions, 0 deletions
diff --git a/java/debug.sh b/java/debug.sh
new file mode 100755
index 00000000000..dd710dc31af
--- /dev/null
+++ b/java/debug.sh
@@ -0,0 +1,242 @@
1#!/bin/bash
2### Run Emacs under GDB or JDB on Android.
3
4## Copyright (C) 2023 Free Software Foundation, Inc.
5
6## This file is part of GNU Emacs.
7
8## GNU Emacs is free software: you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation, either version 3 of the License, or
11## (at your option) any later version.
12
13## GNU Emacs is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16## GNU General Public License for more details.
17
18## You should have received a copy of the GNU General Public License
19## along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20
21set -m
22oldpwd=`pwd`
23cd `dirname $0`
24
25devices=`adb devices | grep device | awk -- '/device\y/ { print $1 }' -`
26device=
27progname=$0
28package=org.gnu.emacs
29activity=org.gnu.emacs.EmacsActivity
30gdb_port=5039
31jdb_port=64013
32jdb=no
33
34while [ $# -gt 0 ]; do
35 case "$1" in
36 ## This option specifies the serial number of a device to use.
37 "--device" )
38 device="$2"
39 if [ -z device ]; then
40 echo "You must specify an argument to --device"
41 exit 1
42 fi
43 ;;
44 "--help" )
45 echo "Usage: $progname [options] -- [gdb options]"
46 echo ""
47 echo " --device DEVICE run Emacs on the specified device"
48 echo " --port PORT run the GDB server on a specific port"
49 echo " --jdb-port PORT run the JDB server on a specific port"
50 echo " --jdb run JDB instead of GDB"
51 echo " --help print this message"
52 echo ""
53 echo "Available devices:"
54 for device in $devices; do
55 echo " " $device
56 done
57 echo ""
58 exit 0
59 ;;
60 "--jdb" )
61 jdb=yes
62 ;;
63 "--port" )
64 gdb_port=$1
65 ;;
66 "--" )
67 shift
68 gdbargs=$@
69 break;
70 ;;
71 * )
72 echo "$progname: Unrecognized argument $1"
73 exit 1
74 ;;
75 esac
76 shift
77done
78
79if [ -z $devices ]; then
80 echo "No devices are available."
81 exit 1
82fi
83
84if [ -z $device ]; then
85 device=$devices
86fi
87
88if [ `wc -w <<< "$devices"` -gt 1 ] && [ -z device ]; then
89 echo "Multiple devices are available. Please pick one using"
90 echo "--device and try again."
91fi
92
93echo "Looking for $package on device $device"
94
95# Find the application data directory
96app_data_dir=`adb -s $device shell run-as $package sh -c 'pwd 2> /dev/null'`
97
98if [ -z $app_data_dir ]; then
99 echo "The data directory for the package $package was not found."
100 echo "Is it installed?"
101fi
102
103echo "Found application data directory at $app_data_dir..."
104
105# Find which PIDs are associated with org.gnu.emacs
106package_uid=`adb -s $device shell run-as $package id -u`
107
108if [ -z $package_uid ]; then
109 echo "Failed to obtain UID of packages named $package"
110 exit 1
111fi
112
113# First, run ps -u $package_uid -o PID,CMD to fetch the list of
114# process IDs.
115package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
116
117# Next, remove lines matching "ps" itself.
118package_pids=`awk -- '{
119 if (!match ($0, /(PID|ps)/))
120 print $1
121}' <<< $package_pids`
122
123# Finally, kill each existing process.
124for pid in $package_pids; do
125 echo "Killing existing process $pid..."
126 adb -s $device shell run-as $package kill -9 $pid &> /dev/null
127done
128
129# Now run the main activity. This must be done as the adb user and
130# not as the package user.
131echo "Starting activity $activity and attaching debugger"
132
133# Exit if the activity could not be started.
134adb -s $device shell am start -D "$package/$activity"
135if [ ! $? ]; then
136 exit 1;
137fi
138
139# Now look for processes matching the package again.
140package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
141
142# Next, remove lines matching "ps" itself.
143package_pids=`awk -- '{
144 if (!match ($0, /(PID|ps)/))
145 print $1
146}' <<< $package_pids`
147
148pid=$package_pids
149num_pids=`wc -w <<< "$package_pids"`
150
151if [ $num_pids -gt 1 ]; then
152 echo "More than one process was started:"
153 echo ""
154 adb -s $device shell run-as $package ps -u $package_uid | awk -- '{
155 if (!match ($0, /ps/))
156 print $0
157 }'
158 echo ""
159 printf "Which one do you want to attach to? "
160 read pid
161elif [ -z $package_pids ]; then
162 echo "No processes were found to attach to."
163 exit 1
164fi
165
166# Start JDB to make the wait dialog disappear.
167echo "Attaching JDB to unblock the application."
168adb -s $device forward --remove-all
169adb -s $device forward "tcp:$jdb_port" "jdwp:$pid"
170
171if [ ! $? ]; then
172 echo "Failed to forward jdwp:$pid to $jdb_port!"
173 echo "Perhaps you need to specify a different port with --port?"
174 exit 1;
175fi
176
177jdb_command="jdb -connect \
178 com.sun.jdi.SocketAttach:hostname=localhost,port=$jdb_port"
179
180if [ $jdb = "yes" ]; then
181 # Just start JDB and then exit
182 $jdb_command
183 exit 1
184fi
185
186exec 4<> /tmp/file-descriptor-stamp
187
188# Now run JDB with IO redirected to file descriptor 4 in a subprocess.
189$jdb_command <&4 >&4 &
190
191character=
192# Next, wait until the prompt is found.
193while read -n1 -u 4 character; do
194 if [ "$character" = ">" ]; then
195 echo "JDB attached successfully"
196 break;
197 fi
198done
199
200# Now start gdbserver on the device asynchronously.
201
202echo "Attaching gdbserver to $pid on $device..."
203exec 5<> /tmp/file-descriptor-stamp
204adb -s $device shell run-as $package /system/bin/gdbserver --once \
205 "+debug.$package_uid.socket" --attach $pid >&5 &
206
207# Wait until gdbserver successfully runs.
208line=
209while read -u 5 line; do
210 case "$line" in
211 *Attached* )
212 break;
213 ;;
214 *error* | *Error* | failed )
215 echo $line
216 exit 1
217 ;;
218 * )
219 ;;
220 esac
221done
222
223# Send EOF to JDB to make it go away. This will also cause Android to
224# allow Emacs to continue executing.
225echo "Making JDB go away..."
226echo "exit" >&4
227read -u 4 line
228echo "JDB has gone away with $line"
229
230# Forward the gdb server port here.
231adb -s $device forward "tcp:$gdb_port" \
232 "localfilesystem:$app_data_dir/debug.$package_uid.socket"
233if [ ! $? ]; then
234 echo "Failed to forward $app_data_dir/debug.$package_uid.socket"
235 echo "to $gdb_port! Perhaps you need to specify a different port"
236 echo "with --port?"
237 exit 1;
238fi
239
240# Finally, start gdb with any extra arguments needed.
241cd "$oldpwd"
242gdb --eval-command "" --eval-command "target remote localhost:$gdb_port" $gdbargs