| #!/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|fuchsia)] [(--verbose-agent|-va)] [--gdb] | |
| ## | |
| ## --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 | |
| ## - "aosp" (Android's unwinder) | |
| ## - "ng" for "ngunwind" (Fuchsia's fork of libunwind) | |
| ## - "fuchsia" (an experimental homemade unwinder) | |
| ## Defaults to "aosp". | |
| ## --verbose-agent Whether the debug agent's stdout/stderr should be shown. | |
| ## Useful for debugging the debugger. Yo' dawg. | |
| ## --gdb Launch zxdb using gdb. This is only useful to be able to debug zxdb. This | |
| ## option only works if you have the unstripped version of zxdb. | |
| ## | |
| ## 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= | |
| use_gdb=0 | |
| # 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" | |
| ;; | |
| --gdb) | |
| use_gdb=1 | |
| ;; | |
| --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 | |
| id='fd81549e77f2f3b199d4dca16131c3525428140828f0843a0fd30e7c0d2e2631' | |
| cache_coredumps=$(fx-command-run shell "find /data/cache/${id}/reports -name minidump.dmp -type f") | |
| tmp_coredumps=$(fx-command-run shell "find /tmp/${id}/reports -name minidump.dmp -type f") | |
| all_coredumps=("${cache_coredumps[@]}" "${tmp_coredumps[@]}") | |
| num_coredumps=${#all_coredumps[@]} | |
| if [[ ${num_coredumps} -eq 0 ]]; then | |
| fx-error "No core dumps available on device" | |
| exit 1 | |
| elif [[ ${num_coredumps} -ge 2 ]]; then | |
| echo "Which core dump would you like to analyze?" | |
| select choice in "${all_coredumps[@]}"; do | |
| coredump=${choice} | |
| break | |
| done | |
| else | |
| coredump=${all_coredumps[0]} | |
| fi | |
| core="/tmp/zxdb_fetched_core.dmp" | |
| if ! fx-command-run cp --to-host "${coredump}" ${core}; then | |
| fx-error "Failed to copy core dump over to host" | |
| exit 1 | |
| fi | |
| fi | |
| if [[ -n "${core}" && ! -f "${core}" ]]; then | |
| echo "Cannot find file ${core}" | |
| exit 1 | |
| fi | |
| arguments=("--symbol-server" "gs://fuchsia-artifacts-release/debug") | |
| if [[ -n "${core}" ]]; then | |
| arguments+=("--core" "${core}") | |
| elif [[ -n "${no_agent}" ]]; then | |
| echo "Not starting a debug agent." | |
| else | |
| if launch_debug_agent "${port}" "${unwind_flag}" "${agent_out}"; then | |
| arguments+=("--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!" | |
| ZXDB=$(fx-command-run host-tool --print zxdb) | |
| ZXDB_UNSTRIPPED="$(dirname "$ZXDB")/exe.unstripped/$(basename "$ZXDB")" | |
| arguments+=("$@") | |
| if [[ ${use_gdb} -eq 1 ]]; then | |
| # Starts gdb. | |
| gdb --args "$ZXDB_UNSTRIPPED" "${arguments[@]}" | |
| else | |
| # Now that the debug agent is launched, start zxdb. | |
| "$ZXDB" "${arguments[@]}" | |
| fi | |
| # 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 |