| #!/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. |
| |
| ### 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-process-info] [--stack=<value>] |
| ## [--syscalls=<regexp>] [--exclude-syscalls=<regexp>] |
| ## [--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. |
| ## --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_.*" |
| ## --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. |
| ## 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 $? |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../contrib/lib/debug.sh || exit $? |
| |
| agent_out="/dev/null" |
| action= |
| debug_mode= |
| with_process_info= |
| stack= |
| syscalls=() |
| verbose= |
| quiet= |
| log_file= |
| remote_pids=() |
| remote_names=() |
| |
| while [[ $# -gt 0 ]]; do |
| case "$1" in |
| --help|-h) |
| fx-command-help |
| exit 0 |
| ;; |
| --port|-p) |
| shift |
| port="$1" |
| ;; |
| --debug-mode) |
| agent_out="/dev/stdout" |
| debug_mode="--debug-mode" |
| ;; |
| --with-process-info) |
| with_process_info="--with-process-info" |
| ;; |
| --stack=*) |
| stack="$1" |
| ;; |
| --syscalls=*) |
| syscalls+="$1 " |
| ;; |
| --exclude-syscalls=*) |
| syscalls+="$1 " |
| ;; |
| --verbose=*) |
| verbose="$1" |
| ;; |
| --quiet=*) |
| quiet="$1" |
| ;; |
| --log-file=*) |
| log_file="$1" |
| ;; |
| --remote-pid=*) |
| remote_pids+="$1 " |
| ;; |
| --remote-name=*) |
| remote_names+="$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 |
| |
| target=$(get-fuchsia-device-addr) |
| |
| # 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; then |
| # We start the client with the flag that tells it to quit the agent when zxdb quits. |
| "${FUCHSIA_BUILD_DIR}/host-tools/fidlcat" \ |
| "--connect" "[${target}]:${port}" \ |
| "--fidl-ir-path" @"${FUCHSIA_BUILD_DIR}"/all_fidl_json.txt \ |
| "-s" "${FUCHSIA_BUILD_DIR}" \ |
| "-s" "${ZIRCON_BUILDROOT}" \ |
| "-s" "${PREBUILT_CLANG_DIR}/lib/debug" \ |
| --pretty-print \ |
| ${with_process_info} \ |
| ${stack} \ |
| ${syscalls} \ |
| ${verbose} \ |
| ${quiet} \ |
| ${log_file} \ |
| ${remote_pids} \ |
| ${remote_names} \ |
| $@ |
| else |
| fx-error "Could not launch debug agent. Exiting." |
| exit 1 |
| fi |