]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
scripts: add kresd-dbg.sh convenience script for debugging
authorOto Šťáva <oto.stava@nic.cz>
Wed, 9 Nov 2022 11:57:03 +0000 (12:57 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Sun, 26 Feb 2023 16:01:15 +0000 (17:01 +0100)
scripts/kresd-dbg.sh [new file with mode: 0755]

diff --git a/scripts/kresd-dbg.sh b/scripts/kresd-dbg.sh
new file mode 100755 (executable)
index 0000000..a2ed45b
--- /dev/null
@@ -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 <interfaces>
+               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
+