summaryrefslogtreecommitdiff
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 @@
+#!/bin/bash
+### Run Emacs under GDB or JDB on Android.
+
+## Copyright (C) 2023 Free Software Foundation, Inc.
+
+## This file is part of GNU Emacs.
+
+## GNU Emacs is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+
+## GNU Emacs is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+set -m
+oldpwd=`pwd`
+cd `dirname $0`
+
+devices=`adb devices | grep device | awk -- '/device\y/ { print $1 }' -`
+device=
+progname=$0
+package=org.gnu.emacs
+activity=org.gnu.emacs.EmacsActivity
+gdb_port=5039
+jdb_port=64013
+jdb=no
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ ## This option specifies the serial number of a device to use.
+ "--device" )
+ device="$2"
+ if [ -z device ]; then
+ echo "You must specify an argument to --device"
+ exit 1
+ fi
+ ;;
+ "--help" )
+ echo "Usage: $progname [options] -- [gdb options]"
+ echo ""
+ echo " --device DEVICE run Emacs on the specified device"
+ echo " --port PORT run the GDB server on a specific port"
+ echo " --jdb-port PORT run the JDB server on a specific port"
+ echo " --jdb run JDB instead of GDB"
+ echo " --help print this message"
+ echo ""
+ echo "Available devices:"
+ for device in $devices; do
+ echo " " $device
+ done
+ echo ""
+ exit 0
+ ;;
+ "--jdb" )
+ jdb=yes
+ ;;
+ "--port" )
+ gdb_port=$1
+ ;;
+ "--" )
+ shift
+ gdbargs=$@
+ break;
+ ;;
+ * )
+ echo "$progname: Unrecognized argument $1"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ -z $devices ]; then
+ echo "No devices are available."
+ exit 1
+fi
+
+if [ -z $device ]; then
+ device=$devices
+fi
+
+if [ `wc -w <<< "$devices"` -gt 1 ] && [ -z device ]; then
+ echo "Multiple devices are available. Please pick one using"
+ echo "--device and try again."
+fi
+
+echo "Looking for $package on device $device"
+
+# Find the application data directory
+app_data_dir=`adb -s $device shell run-as $package sh -c 'pwd 2> /dev/null'`
+
+if [ -z $app_data_dir ]; then
+ echo "The data directory for the package $package was not found."
+ echo "Is it installed?"
+fi
+
+echo "Found application data directory at $app_data_dir..."
+
+# Find which PIDs are associated with org.gnu.emacs
+package_uid=`adb -s $device shell run-as $package id -u`
+
+if [ -z $package_uid ]; then
+ echo "Failed to obtain UID of packages named $package"
+ exit 1
+fi
+
+# First, run ps -u $package_uid -o PID,CMD to fetch the list of
+# process IDs.
+package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
+
+# Next, remove lines matching "ps" itself.
+package_pids=`awk -- '{
+ if (!match ($0, /(PID|ps)/))
+ print $1
+}' <<< $package_pids`
+
+# Finally, kill each existing process.
+for pid in $package_pids; do
+ echo "Killing existing process $pid..."
+ adb -s $device shell run-as $package kill -9 $pid &> /dev/null
+done
+
+# Now run the main activity. This must be done as the adb user and
+# not as the package user.
+echo "Starting activity $activity and attaching debugger"
+
+# Exit if the activity could not be started.
+adb -s $device shell am start -D "$package/$activity"
+if [ ! $? ]; then
+ exit 1;
+fi
+
+# Now look for processes matching the package again.
+package_pids=`adb -s $device shell run-as $package ps -u $package_uid -o PID,CMD`
+
+# Next, remove lines matching "ps" itself.
+package_pids=`awk -- '{
+ if (!match ($0, /(PID|ps)/))
+ print $1
+}' <<< $package_pids`
+
+pid=$package_pids
+num_pids=`wc -w <<< "$package_pids"`
+
+if [ $num_pids -gt 1 ]; then
+ echo "More than one process was started:"
+ echo ""
+ adb -s $device shell run-as $package ps -u $package_uid | awk -- '{
+ if (!match ($0, /ps/))
+ print $0
+ }'
+ echo ""
+ printf "Which one do you want to attach to? "
+ read pid
+elif [ -z $package_pids ]; then
+ echo "No processes were found to attach to."
+ exit 1
+fi
+
+# Start JDB to make the wait dialog disappear.
+echo "Attaching JDB to unblock the application."
+adb -s $device forward --remove-all
+adb -s $device forward "tcp:$jdb_port" "jdwp:$pid"
+
+if [ ! $? ]; then
+ echo "Failed to forward jdwp:$pid to $jdb_port!"
+ echo "Perhaps you need to specify a different port with --port?"
+ exit 1;
+fi
+
+jdb_command="jdb -connect \
+ com.sun.jdi.SocketAttach:hostname=localhost,port=$jdb_port"
+
+if [ $jdb = "yes" ]; then
+ # Just start JDB and then exit
+ $jdb_command
+ exit 1
+fi
+
+exec 4<> /tmp/file-descriptor-stamp
+
+# Now run JDB with IO redirected to file descriptor 4 in a subprocess.
+$jdb_command <&4 >&4 &
+
+character=
+# Next, wait until the prompt is found.
+while read -n1 -u 4 character; do
+ if [ "$character" = ">" ]; then
+ echo "JDB attached successfully"
+ break;
+ fi
+done
+
+# Now start gdbserver on the device asynchronously.
+
+echo "Attaching gdbserver to $pid on $device..."
+exec 5<> /tmp/file-descriptor-stamp
+adb -s $device shell run-as $package /system/bin/gdbserver --once \
+ "+debug.$package_uid.socket" --attach $pid >&5 &
+
+# Wait until gdbserver successfully runs.
+line=
+while read -u 5 line; do
+ case "$line" in
+ *Attached* )
+ break;
+ ;;
+ *error* | *Error* | failed )
+ echo $line
+ exit 1
+ ;;
+ * )
+ ;;
+ esac
+done
+
+# Send EOF to JDB to make it go away. This will also cause Android to
+# allow Emacs to continue executing.
+echo "Making JDB go away..."
+echo "exit" >&4
+read -u 4 line
+echo "JDB has gone away with $line"
+
+# Forward the gdb server port here.
+adb -s $device forward "tcp:$gdb_port" \
+ "localfilesystem:$app_data_dir/debug.$package_uid.socket"
+if [ ! $? ]; then
+ echo "Failed to forward $app_data_dir/debug.$package_uid.socket"
+ echo "to $gdb_port! Perhaps you need to specify a different port"
+ echo "with --port?"
+ exit 1;
+fi
+
+# Finally, start gdb with any extra arguments needed.
+cd "$oldpwd"
+gdb --eval-command "" --eval-command "target remote localhost:$gdb_port" $gdbargs