blob: 9d96bcaa09397e3d77e7cff0abda9ea52ea60279 [file] [log] [blame]
#!/usr/bin/env bash
#
# Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Dump the current call stack.
#
# This function takes no arguments, and prints the call stack of the script at
# the point at which it was called.
dump_stack() {(
set +x
for ((i = 1; i < ${#FUNCNAME[@]}; i++)); do
local function="${FUNCNAME[$((i + 1))]:-<unknown>}"
local line="${BASH_LINENO[$i]}"
local source="${BASH_SOURCE[$((i + 1))]:-<unknown>}"
echo -e "[$i]: ${source}:${line} (${function})"
done
)}
# Dump the process tree.
#
# This function takes no arguments, and prints the process tree of the current
# process. This can be useful for, for example, determining the arguments that
# the script has been called with.
dump_process_tree() {
ps --forest --no-headers --format command
}
# Dump the complete program state.
#
# This function takes no arguments, and combines the output of the `dump_stack`
# and `dump_process_tree` functions.
dump() {(
set +x
echo "Process tree:"
echo
dump_process_tree | while IFS= read -r line; do
echo " ${line}"
done
echo
echo "Call stack:"
echo
dump_stack | while read -r line; do
echo " ${line}"
done
)}
# Generate an error backtrace.
#
# This function dumps the backtrace at the point at which the function is
# called, with additional information about the command that failed.
#
# This is best used as a trap handler (e.g. `trap backtrace ERR`) rather than by
# being called directly. If you want to explicitly dump the script state, prefer
# to use the `dump` function instead.
backtrace() {
local error=$?
local command=${BASH_COMMAND}
(
set +x
echo "" >&2
echo "ERROR: Command at ${BASH_SOURCE[1]:-<unknown>}:${BASH_LINENO[0]} exited with error ${error}:" >&2
echo "ERROR:" >&2
echo "${command}" | while IFS= read -r line; do
echo "ERROR: ${line}" >&2
done
echo "ERROR:" >&2
dump | while IFS= read -r line; do
echo "ERROR: ${line}" >&2
done
)
}