| #!/bin/bash |
| # Copyright 2019 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 fidlcat on given target. |
| |
| ## Runs fidlcat in the given configuration; currently, fidlcat logs all FIDL |
| ## chatter from the given target executable. Starts the debug agent on the |
| ## proposed target, and closes the debug agent on exit. |
| ## |
| ## CAUTION: This support is experimental, and invocation strategy is likely to |
| ## change. The component launching configuration is *especially* likely to go |
| ## away over time. |
| ## |
| ## 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 --debug-mode flag to see |
| ## the debug log's from the debug agent and fidlcat. |
| ## - This scripts uses the tool "nc" for testing TCP connections. Check that it |
| ## is in $PATH and that it works. |
| ## |
| ## Usage: fx fidlcat [--debug-mode] [(--port|-p) <PORT>] [--with-symbol-server] |
| ## [--with-process-info] [--stack=<value>] |
| ## [--syscalls=<regexp>] [--exclude-syscalls=<regexp>] [--dump-messages] |
| ## [--verbose=<value> | --quiet=<value>] [--log-file <path>] |
| ## [--remote-pid=<pid> | --remote-name=<name> | run <component specification>] |
| ## |
| ## --port Port the debug agent will be listening on. Will use 2345 |
| ## by default. |
| ## --with-symbol-server Connect to the symbol server. The first time you use this option, |
| ## fidlcat will give you a link to an authentication page. |
| ## You then have to use the generated key to authenticate. |
| ## --debug-mode Whether the debug agent's debug logs should be shown. |
| ## --with-process-info Display the process name, process id and thread id on |
| ## each line (useful for grep). |
| ## --stack=<value> Define the amount of stack frame to display |
| ## 0: none (default value) |
| ## 1: call site (1 to 4 levels) |
| ## 2: full stack frame (adds some overhead) |
| ## --syscalls A regular expression which selects the syscalls to decode and display. |
| ## Can be passed multiple times. |
| ## By default, only zx_channel_.* syscalls are displayed. |
| ## To display all the syscalls, use: --syscalls ".*" |
| ## --exclude-syscalls A regular expression which selects the syscalls to not decode and |
| ## display. |
| ## Can be passed multiple times. |
| ## To be displayed, a syscall must verify --syscalls and not verify |
| ## --exclude-syscalls. |
| ## To display all the syscalls but the zx_handle syscalls, use: |
| ## --syscalls ".*" --exclude-syscalls "zx_handle_.*" |
| ## --dump-messages Always does a hexadecimal dump of the messages even if we can |
| ## decode them. |
| ## --verbose=<value> The log verbosity. Legal values are "info", "warning", |
| ## "error", "fatal", or a number, starting from 0. Extra |
| ## verbosity comes with higher levels. |
| ## --quiet=<value> The log verbosity. Legal values are "info", "warning", |
| ## "error", "fatal", or a number, starting from 0. Extra |
| ## verbosity comes with lower levels. |
| ## --log-file=<path> The log file destination. |
| ## --remote-pid The koid of the remote process to trace |
| ## --remote-name A set of comma-separated regexes. Fidlcat will monitor all existing |
| ## and future processes whose names match one of the regexes. |
| ## Can be provided multiple times for multiple regexes. |
| ## --symbol-path=<path> An extra location where fildcat can find debug symbols. |
| ## --fidl-ir-path=<path> An extra location where fidlcat can find FIDL compiled files. |
| ## --gdb Launch fidlcat using gdb. This is only useful to be able to debug |
| ## fidlcat. When this option is used, the string you have to type within |
| ## gdb to launch fidlcat is printed and then, gdb is launched. |
| ## This option only works if you have the unstripped version of fidlcat. |
| ## run A token indicating that you want to invoke and trace |
| ## the following component. The component is specified |
| ## with either a bash regex that matches a component URL |
| ## known to the build, or a full component URL not known |
| ## to your build, but available to your target. |
| ## |
| ## Flags after -- are parsed by fidlcat. Example usage: |
| ## |
| ## # Attaches to the process with the given pid on the target: |
| ## fx fidlcat --remote-pid=4755 |
| ## |
| ## # Launches the echo client, and monitors its FIDL chatter: |
| ## fx fidlcat run fuchsia-pkg://fuchsia.com/echo_client_cpp#meta/echo_client_cpp.cmx |
| ## |
| ## # Also launches the echo client, and monitors its FIDL chatter: |
| ## fx fidlcat run echo_client_cpp.cmx |
| ## |
| ## # Will trace existing and future processes whose name contains "echo_client" |
| ## fx fidlcat --remote-name=echo_client |
| ## |
| ## All three options --remote-pid, --remote-name and run can be used together. |
| ## However, run must always be the last one. |
| ## When --remote-name and run are used together, only processes which match |
| ## --remote-name are monitored. |
| ## |
| ## Examples (echo_server is launched by echo_client): |
| ## |
| ## # run and monitor echo_client. |
| ## fx fidlcat run echo_client_cpp.cmx |
| ## |
| ## # run and monitor echo_client. |
| ## fx fidlcat --remote-name=echo_client run echo_client_cpp.cmx |
| ## |
| ## # run echo_client and monitor echo_server. |
| ## fx fidlcat --remote-name=echo_server run echo_client_cpp.cmx |
| ## |
| ## # run echo_client and monitor echo_client and echo_server. |
| ## fx fidlcat --remote-name=echo run echo_client_cpp.cmx |
| ## |
| ## # run echo_client and monitor echo_client and echo_server. |
| ## fx fidlcat --remote-name=echo_client --remote-name=echo_server run echo_client_cpp.cmx |
| |
| 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)"/../contrib/lib/debug-agent.sh || exit $? |
| |
| action= |
| |
| arguments=() |
| |
| use_gdb=0 |
| |
| # Options for the zxdb client. |
| agent_out="/dev/null" |
| debug_mode= |
| |
| while [[ $# -gt 0 ]]; do |
| case "$1" in |
| --help|-h) |
| fx-command-help |
| exit 0 |
| ;; |
| --port|-p) |
| shift |
| port="$1" |
| ;; |
| --with-symbol-server) |
| arguments+=("--symbol-server") |
| arguments+=("gs://fuchsia-artifacts-release/debug") |
| ;; |
| --debug-mode) |
| agent_out="/dev/stdout" |
| debug_mode="--debug-mode" |
| ;; |
| --with-process-info) |
| arguments+=("--with-process-info") |
| ;; |
| --dump-messages) |
| arguments+=("--dump-messages") |
| ;; |
| --stack=*) |
| arguments+=("$1") |
| ;; |
| --syscalls=*) |
| arguments+=("$1") |
| ;; |
| --exclude-syscalls=*) |
| arguments+=("$1") |
| ;; |
| --verbose=*) |
| arguments+=("$1") |
| ;; |
| --quiet=*) |
| arguments+=("$1") |
| ;; |
| --log-file=*) |
| arguments+=("$1") |
| ;; |
| --remote-pid=*) |
| arguments+=("$1") |
| ;; |
| --remote-name=*) |
| arguments+=("$1") |
| ;; |
| --symbol-path=*) |
| arguments+=("$1") |
| ;; |
| --fidl-ir-path=*) |
| arguments+=("$1") |
| ;; |
| --gdb) |
| use_gdb=1 |
| ;; |
| run) |
| action="$1" |
| shift |
| break # Remaining flags are passed to fidlcat, with processing below |
| ;; |
| --) |
| shift |
| break # Remaining flags are passed to fidlcat |
| ;; |
| *) |
| echo "Invalid flag $1" |
| exit 1 |
| esac |
| shift |
| done |
| |
| # Infer the package URL from a regex-specified name. |
| package_file="${FUCHSIA_BUILD_DIR}/component_index_metadata" |
| if [[ "${action}" == "run" ]]; then |
| component=$1 |
| components=() |
| all_pkgs="$(cat "${package_file}")" |
| if [[ -n "${all_pkgs}" ]]; then |
| for pkg in ${all_pkgs}; do |
| if [[ "${pkg}" =~ ${component} ]]; then |
| components+=("${pkg}") |
| fi |
| done |
| else |
| # If there aren't any packages in the component_index_metadata file, then |
| # assume the users know what they are doing. fidlcat should complain. |
| components+=("${component}") |
| fi |
| |
| if [[ ${#components[@]} = 0 ]]; then |
| fx-error "Package $component is not known to the current build configuration." |
| fx-error "Check \`fx list-packages\` for the correct name," |
| fx-error "or adjust the build configuration with \`fx set\`." |
| exit 1 |
| elif [[ ${#components[@]} -gt 1 ]]; then |
| fx-error "Ambiguous match: $component matches the following ${#components[@]} packages:" |
| for component in "${components[@]}"; do |
| fx-error " $component" |
| done |
| exit 1 |
| fi |
| component="${components[0]}" |
| shift |
| # We have now removed "run <partial component URL regex>" from the remaining |
| # positional parameters. The following set command replaces them with "run |
| # <full component URL>". |
| set - "$@" "run" "${component}" |
| fi |
| |
| if [[ -z "${port}" ]]; then |
| port=2345 |
| fi |
| |
| if launch_debug_agent "${port}" "" "${agent_out}"; then |
| arguments+=("--connect" "$(get-device-addr-resource):${port}") |
| arguments+=("--fidl-ir-path" @"${FUCHSIA_BUILD_DIR}"/all_fidl_json.txt) |
| arguments+=("-s" "${FUCHSIA_BUILD_DIR}") |
| arguments+=("-s" "${ZIRCON_BUILDROOT}") |
| arguments+=("-s" "${PREBUILT_CLANG_DIR}/lib/debug") |
| arguments+=("--symbol-cache" "~") |
| arguments+=("--pretty-print") |
| arguments+=("$@") |
| |
| if [[ ${use_gdb} -eq 1 ]]; then |
| # Starts gdb. |
| gdb --args ${FUCHSIA_BUILD_DIR}/host_x64/exe.unstripped/fidlcat ${arguments[@]} |
| else |
| # Now that the debug agent is launched, starts fidlcat. |
| "${FUCHSIA_BUILD_DIR}/host-tools/fidlcat" ${arguments[@]} |
| fi |
| |
| # launch_debug_agent starts an agent in the background. Note: killing |
| # the ssh session as below generally won't terminate the agent, but |
| # it prevents us ending up with a zobmie on the host. |
| pids=$(jobs -p) |
| if [[ -n "${pids}" ]]; then |
| kill "${pids}" > /dev/null >&2 |
| wait |
| fi |
| else |
| fx-error "Could not launch debug agent. Exiting. Make sure you're running 'fx serve'." |
| exit 1 |
| fi |