blob: e8945f6855c81910f26c80e814a34033d51d4419 [file] [log] [blame] [edit]
#!/bin/bash
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#### CATEGORY=Run, inspect and debug
### run the debug agent on target and connect to it with zxdb
## Starts the debug agent on the proposed target and automatically connect zxdb
## to it. Will close the debug agent on exit.
##
## TROUBLESHOOTING TIPS:
##
## - Remember to use "fx set-device" when working with multiple devices.
## - This scripts by default will mute the SSH connection stdout/stderr, so any
## errors triggered by it won't appear. Use the --verbose-agent flag to see
## the output.
## - This scripts uses the tool "nc" for testing TCP connections. Check that it
## is in $PATH and that it works.
##
## Usage: fx debug [(--core|-c) <CORE>] [--no-agent] [(--port|-p) <PORT>]
## [--unwind=(aosp|ng)] [(--verbose-agent|-va)]
##
## --core Load a minidump file into zxdb.
## --no-agent Don't start a Debug Agent.
## --port Port the debug agent will be listening on.
## Will use 2345 by default.
## --target-core Look on the target for a minidump file taken by
## crashpad, download it and load it into zxdb.
## --unwind Choose the unwinder to use. Options are "ng" for "ngunwind" (Fuchsia's
## fork of libunwind), or "aosp" (Android's unwinder). Defaults to "aosp".
## --verbose-agent Whether the debug agent's stdout/stderr should be shown.
## Useful for debugging the debugger. Yo' dawg.
##
## Flags after -- are parsed by zxdb. See zxdb's documentation for more
## details.
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../lib/vars.sh || exit $?
fx-config-read
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/debug-agent.sh || exit $?
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/symbol-index.sh || exit $?
# Defaults.
port=
core=
unwind_flag=
agent_out="/dev/null"
no_agent=
target_core=
# Flag parsing.
while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h)
fx-command-help
exit 0
;;
--no-agent)
no_agent=true
;;
--port|-p)
shift
port="$1"
;;
--port=*)
port="${1:7}"
;;
--verbose-agent|-va)
agent_out="/dev/stdout"
;;
--core|-c)
arg=$1
shift
core="$1"
if [[ -z "${core}" ]]; then
echo "${arg} takes an argument"
exit 1
fi
no_agent=true
;;
--core=*)
core="${1:7}"
no_agent=true
;;
--target-core)
target_core=true
no_agent=true
;;
--unwind)
shift
unwind_flag="--unwind=$1"
;;
--unwind=*)
unwind_flag="--unwind=${1:9}"
;;
--)
shift
break # Remaining flags are passed to zxdb
;;
*)
echo "Invalid flag $1"
exit 1
esac
shift
done
if [[ -n "${port}" && -n "${core}" ]]; then
echo "Specifying both a port and a core doesn't make sense"
exit 1
fi
if [[ -n "${target_core}" && -n "${core}" ]]; then
echo "Cannot specify a core file when fetching a core from the target"
exit 1;
fi
if [[ -n "${port}" && -n "${target_core}" ]]; then
echo "Cannot specify a port file when fetching a core from the target"
exit 1
fi
if [[ -z "${port}" ]]; then
port=2345
fi
if [[ -n "${target_core}" ]]; then
crash_reports_cache_dir=`fx-command-run shell ls /data/cache/r/sys | grep crash_reports`
crash_reports_tmp_dir=`fx-command-run shell ls /tmp/r/sys | grep crash_reports`
if [[ -z "${crash_reports_tmp_dir}" ]] || [[ -z "${crash_reports_cache_dir}" ]]; then
fx-error "Could not find crash reports directory on target"
exit 1
fi
cache_core_names=`fx-command-run shell \
"cd /data/cache/r/sys/${crash_reports_cache_dir}/reports 2>/dev/null && find . -name minidump.dmp -type f"`
tmp_core_names=`fx-command-run shell \
"cd /tmp/r/sys/${crash_reports_tmp_dir}/reports 2>/dev/null && find . -name minidump.dmp -type f"`
core_name="$echo "${cache_core_names[@]}" "${tmp_core_names[@]}""
if [[ -z "${core_name}" ]]; then
fx-error "No cores available on device"
exit 1
fi
if [[ "$(echo "${core_name}" | wc -l)" -ge 2 ]]; then
echo "Which core would you like to analyze?"
select choice in ${core_name}; do
core_name=${choice}
break
done
fi
core="/tmp/zxdb_fetched_core.dmp"
if [[ " ${cache_core_names[*]} " == *"$core_name"* ]]; then
fx-command-run "cp" "--to-host" \
"/data/cache/r/sys/${crash_reports_cache_dir}/reports/${core_name}" \
"${core}"
else
fx-command-run "cp" "--to-host" \
"/tmp/r/sys/${crash_reports_tmp_dir}/reports/${core_name}" \
"${core}"
fi
fi
if [[ -n "${core}" && ! -f "${core}" ]]; then
echo "Cannot find file ${core}"
exit 1
fi
connect_ops=()
if [[ ! -z "${core}" ]]; then
connect_ops=("--core" "${core}")
elif [[ ! -z "${no_agent}" ]]; then
echo "Not starting a debug agent."
else
if launch_debug_agent "${port}" "${unwind_flag}" "${agent_out}"; then
connect_ops=("--connect" "$(get-device-addr-resource):${port}" "--quit-agent-on-exit")
else
fx-error "Could not launch debug agent. Exiting. Make sure you're running 'fx serve'."
exit 1
fi
fi
ensure-symbol-index-registered || fx-warn "Failed to register ${FUCHSIA_DIR} in symbol-index!"
"${FUCHSIA_BUILD_DIR}/host-tools/zxdb" \
${connect_ops[@]} \
"--symbol-server" "gs://fuchsia-artifacts-release/debug" \
"$@"
# launch_debug_agent starts the agent in a subprocess, which zxdb will
# terminate by --quit-agent-on-exit, we want to wait that process however.
wait