From: Oto Šťáva Date: Wed, 9 Nov 2022 11:57:03 +0000 (+0100) Subject: scripts: add kresd-dbg.sh convenience script for debugging X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=35bbb142c8ba8adc4650829c7a1e9844a99051e4;p=thirdparty%2Fknot-resolver.git scripts: add kresd-dbg.sh convenience script for debugging --- diff --git a/scripts/kresd-dbg.sh b/scripts/kresd-dbg.sh new file mode 100755 index 000000000..a2ed45b38 --- /dev/null +++ b/scripts/kresd-dbg.sh @@ -0,0 +1,310 @@ +#!/bin/bash + +################################################################################ +# +# Debugging harness for Knot Resolver +# +# Convenience script for running kresd with different tools and configurations. +# Always automatically builds kresd before running, deletes kresd's caches, +# optionally cleans the build directory, etc. +# +# For more info about the script's options, run it with '--help'. +# +# The recommended way of using this script is to create a simple wrapper script, +# which may look something like this: +# +# #!/bin/bash +# export KRDBG_SCRIPT_FILE="$(realpath "${BASH_SOURCE[0]}")" +# export KRDBG_WORKING_DIR="/tmp/krwd" +# export KRDBG_NINJA_PATH="/path/to/knot-resolver/build_dir" +# export KRDBG_PREFIX="/path/to/install/prefix" +# source "/path/to/this/script.sh" +# +# Note that KRDBG_PREFIX must match the one configured by Meson in +# KRDBG_NINJA_PATH. +# +# KRDBG_WORKING_DIR is the working directory for kresd, where its cache and +# potentially other data is stored. It is recommended for it to be in tmpfs. +# +################################################################################ + + +## Help ######################################################################## + +short_help_text=$(cat << EOF +Debugging harness for Knot Resolver +USAGE: $0 [options] -- [kresd args] +EOF +) + +help_text=$(cat << EOF +$short_help_text + +Available options: + -b, --debug [debugger] + Runs kresd under the specified debugger (gdb by default) + + -c, --clean + Cleans the Ninja directory before running + + -d, --no-run + Performs all the preparation steps, but does not run kresd + itself (may be used for extra cleanup if the user forgot about + something the last time) + + -g, --valgrind + Runs kresd under Valgrind Memcheck + + -h, --help + Displays this help and exits + + -m, --massif [args] + Runs kresd under Valgrind Massif, optionally with the specified + arguments, with default output to 'massif.out.kresd' in + the wrapper script directory + + -n, --no-delete + Does not delete kresd's working directory data before running + + -p, --caps + Uses setcap to set XDP capabilities for kresd and, optionally, + the debugger if --debug is specified + + -r, --rr [args] + Records kresd's run using rr, optionally with the specified + arguments + + -s, --sudo + Runs kresd with sudo + + -x, --xdp-if + Sets interfaces to clean up XDP on after kresd ends. Multiple + interfaces are comma-separated. +EOF +) + + +## Basic script setup ########################################################## + +set -e + +kill_and_wait_all () { + JOBS=$(jobs -p) + if [ -n "$JOBS" ]; then + kill $JOBS + wait $JOBS + fi +} + +trap "kill_and_wait_all" EXIT + + +## Process environment variables ############################################### + +if [ -z "$KRDBG_NINJA_PATH" ]; then + echo '$KRDBG_NINJA_PATH missing - set it to the Ninja build directory of kresd' >&2 + exit 1 +fi +build_path="$KRDBG_NINJA_PATH" + +if [ -z "$KRDBG_PREFIX" ]; then + # TODO - could potentially be automated + echo '$KRDBG_PREFIX missing - set it to the prefix where Ninja installs kresd' >&2 + exit 1 +fi +kresd_path="$KRDBG_PREFIX/sbin/kresd" + +if [ -z "$KRDBG_WORKING_DIR" ]; then + echo '$KRDBG_WORKING_DIR missing - set it to the desired working directory of kresd' >&2 + exit 1 +fi +wd_dir="$KRDBG_WORKING_DIR" + +if [ -z "$KRDBG_SCRIPT_FILE" ]; then + echo '$KRDBG_SCRIPT_FILE missing - set it to the path to the script that executes the harness' >&2 + exit 1 +fi +script_file=$(realpath "$KRDBG_SCRIPT_FILE") +script_dir=$(cd -- "$(dirname -- "$script_file")" && pwd) + +if [ -z "$KRDBG_CONFIG" ]; then + config="$script_dir/kresd.conf" +else + config="$(realpath $KRDBG_CONFIG)" +fi + + +## Process CLI arguments ####################################################### + +GETOPT=$(getopt \ + --options 'b::cdghm::npr::sx'\ + --longoptions 'debug::,clean,no-run,valgrind,help,massif::,no-delete,caps,rr::,sudo,xdp-if:'\ + --name 'krdbg'\ + -- "$@") + +if [ $? -ne 0 ]; then + echo "$short_help_text" >&2 + echo 'Terminating...' >&2 + exit 1 +fi + +eval set -- "$GETOPT" +unset GETOPT + +while true; do + case "$1" in + '-b'|'--debug') + debug=1 + if [ -z "$2" ]; then + debugger="gdb --args" + else + debugger="$2" + fi + shift 2 + continue + ;; + '-c'|'--clean') + clean=1 + shift + continue + ;; + '-d'|'--no-run') + no_run=1 + shift + continue + ;; + '-g'|'--valgrind') + valgrind=1 + shift + continue + ;; + '-h'|'--help') + echo "$help_text" + exit 0 + ;; + '-m'|'--massif') + massif=1 + massif_args="$2" + shift 2 + continue + ;; + '-n'|'--no-delete') + no_delete=1 + shift + continue + ;; + '-p'|'--caps') + caps=1 + shift + continue + ;; + '-r'|'--rr') + rr=1 + rr_args="$2" + shift 2 + continue + ;; + '-s'|'--sudo') + sudo=1 + shift + continue + ;; + '-x'|'--xdp-if') + xdp_if="$2" + shift 2 + continue + ;; + '--') + shift + break + ;; + *) + echo 'Internal error!' >&2 + exit 1 + ;; + esac +done + + +## Prepare kresd ############################################################### + +mkdir -p "$wd_dir" +cd "$wd_dir" + +if [ "$clean" == "1" ]; then + ninja clean -C "$build_path" +fi + +ninja -C "$build_path" +ninja install -C "$build_path" + +kr_command="\"$kresd_path\" --config=\"$config\" $@" + +if [ -z "$no_delete" -o "$no_delete" == "0" ]; then + rm_command="rm -rf control data.mdb lock.mdb" + $rm_command || sudo $rm_command +fi + +caps_string=$(cat << EOF + CAP_NET_BIND_SERVICE=+eip + CAP_NET_RAW=+eip + CAP_NET_ADMIN=+eip + CAP_SYS_ADMIN=+eip + CAP_IPC_LOCK=+eip + CAP_SYS_RESOURCE=+eip + CAP_SYS_PTRACE=+eip +EOF +) + +if [ "$caps" == "1" ]; then + sudo setcap "$caps_string" "$kresd_path" + sudo setcap -v "$caps_string" "$kresd_path" +fi + + +## Prepare the kresd command ################################################### + +if [ "$rr" == "1" ]; then + if [ "$caps" == "1" ]; then + kr_command="sudo -EP --preserve-env=HOME rr record --setuid-sudo $rr_args $kr_command" + else + kr_command="rr record $rr_args $kr_command" + fi +fi +if [ "$debug" == "1" ]; then + kr_command="${debugger[@]} $kr_command" +fi +if [ "$massif" == "1" ]; then + kr_command="valgrind --tool=massif --massif-out-file=\"$script_dir/massif.out.kresd $massif_args\" -- $kr_command" +fi +if [ "$valgrind" == "1" ]; then + kr_command="valgrind -- $kr_command" +fi +if [ "$sudo" == "1" ]; then + kr_command="sudo $kr_command" +fi + + +## Run kresd ################################################################### + +export ASAN_OPTIONS="$ASAN_OPTIONS:disable_coredump=0:unmap_shadow_on_exit=1:abort_on_error=1" +set +e +echo "Command: $kr_command" + +if [ -z "$no_run" -o "$no_run" == 0 ]; then + eval $kr_command + echo "Exited with $?" +else + echo "--no-run specified - skipping kresd" +fi + + +## Clean up #################################################################### + +if [ -n "$xdp_if" ]; then + for ifc in $(echo $xdp_if | tr ',' ' '); do + echo "Disabling XDP for $ifc" + sudo ip link set dev "$ifc" xdp off + done +fi +