1#!/usr/bin/env bash 2# SPDX-License-Identifier: LGPL-2.1-or-later 3 4set -e 5 6if [[ $# -lt 2 ]]; then 7 echo "Usage: ${0} TARGET INPUT [GDBSCRIPT]" 8 echo "Debug systemd-boot/stub in QEMU." 9 echo 10 echo "TARGET should point to the EFI binary to be examined inside the" 11 echo "build directory (systemd-boot\$ARCH.efi or linux\$arch.efi.stub)." 12 echo 13 echo "INPUT should point to the QEMU serial output pipe. This is used to" 14 echo "extract the location of the symbols. For this to work, QEMU must" 15 echo "be run with '-s -serial pipe:PATH'. Note that QEMU will append" 16 echo ".in/.out to the path, while this script expects the out pipe directly." 17 echo 18 echo "If GDBSCRIPT is empty, gdb is run directly attached to the boot" 19 echo "loader, otherwise a script is generated in the given path that allows" 20 echo "attaching manually like this:" 21 echo " (gdb) source GDBSCRIPT" 22 echo " (gdb) target remote :1234" 23 echo 24 echo "Example usage:" 25 echo " mkfifo /tmp/sdboot.{in,out}" 26 echo " qemu-system-x86_64 [...] -s -serial pipe:/tmp/sdboot" 27 echo " ./tools/debug-sd-boot.sh ./build/src/boot/efi/systemd-bootx64.efi \\" 28 echo " /tmp/sdboot.out" 29 exit 1 30fi 31 32binary=$(realpath "${1}") 33if [[ "${1}" =~ systemd-boot([[:alnum:]]+).efi ]]; then 34 target="systemd-boot" 35 symbols=$(realpath "${1%efi}elf") 36elif [[ "${1}" =~ linux([[:alnum:]]+).efi.stub ]]; then 37 target="systemd-stub" 38 symbols=$(realpath "${1%efi.stub}elf.stub") 39else 40 echo "Cannot detect EFI binary '${1}'." 41 exit 1 42fi 43 44case "${BASH_REMATCH[1]}" in 45 ia32) arch="i386";; 46 x64) arch="i386:x86-64";; 47 aa64) arch="aarch64";; 48 arm|riscv64) arch="${BASH_REMATCH[1]}";; 49 *) 50 echo "Unknown EFI arch '${BASH_REMATCH[1]}'." 51 exit 1 52esac 53 54# system-boot will print out a line like this to inform us where gdb is supposed to 55# look for .text and .data section: 56# systemd-boot@0x0,0x0 57while read -r line; do 58 if [[ "${line}" =~ ${target}@(0x[[:xdigit:]]+),(0x[[:xdigit:]]+) ]]; then 59 text="${BASH_REMATCH[1]}" 60 data="${BASH_REMATCH[2]}" 61 break 62 fi 63done < "${2}" 64 65if [[ -z "${text}" || -z "${data}" ]]; then 66 echo "Could not determine text and data location." 67 exit 1 68fi 69 70if [[ -z "${3}" ]]; then 71 gdb_script=$(mktemp /tmp/debug-sd-boot.XXXXXX.gdb) 72 trap 'rm -f "${gdb_script}"' EXIT 73else 74 gdb_script="${3}" 75fi 76 77echo "file ${binary} 78add-symbol-file ${symbols} ${text} -s .data ${data} 79set architecture ${arch}" > "${gdb_script}" 80 81if [[ -z "${3}" ]]; then 82 gdb -x "${gdb_script}" -ex "target remote :1234" 83else 84 echo "GDB script written to '${gdb_script}'." 85fi 86