| #!/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 "ng". | |
| ## --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 $? | |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../contrib/lib/debug.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 | |
| target=$(get-fuchsia-device-addr-or-die) | |
| crashpad_agent_dir=`fx-command-run "ssh" "${target}" "ls /tmp/r/sys" | \ | |
| grep crashpad_agent` | |
| if [[ -z "${crashpad_agent_dir}" ]]; then | |
| fx-error "Could not find crashpad agent directory" | |
| exit 1 | |
| fi | |
| core_name=`fx-command-run "ssh" ${target} \ | |
| "ls /tmp/r/sys/${crashpad_agent_dir}/crashes/completed" | grep -v meta` | |
| 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" | |
| fx-command-run "cp" "--to-host" \ | |
| "/tmp/r/sys/${crashpad_agent_dir}/crashes/completed/${core_name}" \ | |
| "${core}" | |
| 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; then | |
| target=$(get-fuchsia-device-addr) | |
| connect_ops="--connect [${target}]:${port}" | |
| else | |
| fx-error "Could not launch debug agent. Exiting. Make sure you're running 'fx serve'." | |
| exit 1 | |
| fi | |
| fi | |
| # We start the client with the flag that tells it to quit the agent when zxdb quits. | |
| "${FUCHSIA_BUILD_DIR}/host-tools/zxdb" \ | |
| ${connect_ops} \ | |
| "--quit-agent-on-exit" \ | |
| "-b" "${FUCHSIA_BUILD_DIR}" \ | |
| "-s" "${FUCHSIA_BUILD_DIR}" \ | |
| "-s" "${ZIRCON_BUILDROOT}" \ | |
| "-s" "${PREBUILT_CLANG_DIR}/lib/debug" \ | |
| "--symbol-cache" ~ \ | |
| "--symbol-server" "gs://fuchsia-infra-debug-symbols" \ | |
| $@ |