diff options
Diffstat (limited to '')
-rwxr-xr-x | tools/debug-sd-boot.sh | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/tools/debug-sd-boot.sh b/tools/debug-sd-boot.sh new file mode 100755 index 0000000..0420dbd --- /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 "Example 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 "${1%efi}elf") +elif [[ "${1}" =~ linux([[:alnum:]]+).efi.stub ]]; then + target="systemd-stub" + symbols=$(realpath "${1%efi.stub}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/stub will print out a line like this to inform us where it was loaded: +# systemd-boot@0xC0DE +while read -r line; do + if [[ "${line}" =~ ${target}@(0x[[:xdigit:]]+) ]]; then + loaded_base="${BASH_REMATCH[1]}" + break + fi +done <"${2}" + +if [[ -z "${loaded_base}" ]]; then + echo "Could not determine loaded image base." + 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 + +cat >"${gdb_script}" <<EOF +file ${binary} +symbol-file ${symbols} -o ${loaded_base} +set architecture ${arch} +EOF + +if [[ -z "${3}" ]]; then + gdb -x "${gdb_script}" -ex "target remote :1234" +else + echo "GDB script written to '${gdb_script}'." +fi |