From 948d085e899273f3a34376665414d1ecd1858978 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Sun, 19 Dec 2021 18:05:44 +0100 Subject: boot: Add gdb support and documentation This will finally allow debugging issues in systemd without resorting to Print() calls all over the place. --- tools/debug-sd-boot.sh | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100755 tools/debug-sd-boot.sh (limited to 'tools') diff --git a/tools/debug-sd-boot.sh b/tools/debug-sd-boot.sh new file mode 100755 index 0000000000..1af97c18ec --- /dev/null +++ b/tools/debug-sd-boot.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +set -e + +if [[ $# -lt 2 ]]; then + echo "Usage: ${0} TARGET INPUT [GDBSCRIPT]" + echo "Debug systemd-boot/stub in QEMU." + echo + echo "TARGET should point to the EFI binary to be examined inside the" + echo "build directory (systemd-boot\$ARCH.efi or linux\$arch.efi.stub)." + echo + echo "INPUT should point to the QEMU serial output pipe. This is used to" + echo "extract the location of the symbols. For this to work, QEMU must" + echo "be run with '-s -serial pipe:PATH'. Note that QEMU will append" + echo ".in/.out to the path, while this script expects the out pipe directly." + echo + echo "If GDBSCRIPT is empty, gdb is run directly attached to the boot" + echo "loader, otherwise a script is generated in the given path that allows" + echo "attaching manually like this:" + echo " (gdb) source GDBSCRIPT" + echo " (gdb) target remote :1234" + echo + echo "Exmaple usage:" + echo " mkfifo /tmp/sdboot.{in,out}" + echo " qemu-system-x86_64 [...] -s -serial pipe:/tmp/sdboot" + echo " ./tools/debug-sd-boot.sh ./build/src/boot/efi/systemd-bootx64.efi \\" + echo " /tmp/sdboot.out" + exit 1 +fi + +binary=$(realpath "${1}") +if [[ "${1}" =~ systemd-boot([[:alnum:]]+).efi ]]; then + target="systemd-boot" + symbols=$(realpath "$(dirname "${1}")/systemd_boot.so") +elif [[ "${1}" =~ linux([[:alnum:]]+).efi.stub ]]; then + target="systemd-stub" + symbols=$(realpath "$(dirname "${1}")/linux${BASH_REMATCH[1]}.elf.stub") +else + echo "Cannot detect EFI binary '${1}'." + exit 1 +fi + +case "${BASH_REMATCH[1]}" in + ia32) arch="i386";; + x64) arch="i386:x86-64";; + aa64) arch="aarch64";; + arm|riscv64) arch="${BASH_REMATCH[1]}";; + *) + echo "Unknown EFI arch '${BASH_REMATCH[1]}'." + exit 1 +esac + +# system-boot will print out a line like this to inform us where gdb is supposed to +# look for .text and .data section: +# systemd-boot@0x0,0x0 +while read -r line; do + if [[ "${line}" =~ ${target}@(0x[[:xdigit:]]+),(0x[[:xdigit:]]+) ]]; then + text="${BASH_REMATCH[1]}" + data="${BASH_REMATCH[2]}" + break + fi +done < "${2}" + +if [[ -z "${text}" || -z "${data}" ]]; then + echo "Could not determine text and data location." + exit 1 +fi + +if [[ -z "${3}" ]]; then + gdb_script=$(mktemp /tmp/debug-sd-boot.XXXXXX.gdb) + trap 'rm -f "${gdb_script}"' EXIT +else + gdb_script="${3}" +fi + +echo "file ${binary} +add-symbol-file ${symbols} ${text} -s .data ${data} +set architecture ${arch}" > "${gdb_script}" + +if [[ -z "${3}" ]]; then + gdb -x "${gdb_script}" -ex "target remote :1234" +else + echo "GDB script written to '${gdb_script}'." +fi -- cgit v1.2.1