]> git.ipfire.org Git - thirdparty/systemd.git/blob - tools/debug-sd-boot.sh
Merge pull request #32336 from teknoraver/foreach_element
[thirdparty/systemd.git] / tools / debug-sd-boot.sh
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3
4 set -e
5
6 if [[ $# -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
30 fi
31
32 binary=$(realpath "${1}")
33 if [[ "${1}" =~ systemd-boot([[:alnum:]]+).efi ]]; then
34 target="systemd-boot"
35 symbols=$(realpath "${1%efi}elf")
36 elif [[ "${1}" =~ linux([[:alnum:]]+).efi.stub ]]; then
37 target="systemd-stub"
38 symbols=$(realpath "${1%efi.stub}elf.stub")
39 else
40 echo "Cannot detect EFI binary '${1}'."
41 exit 1
42 fi
43
44 case "${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
52 esac
53
54 # system-boot/stub will print out a line like this to inform us where it was loaded:
55 # systemd-boot@0xC0DE
56 while read -r line; do
57 if [[ "${line}" =~ ${target}@(0x[[:xdigit:]]+) ]]; then
58 loaded_base="${BASH_REMATCH[1]}"
59 break
60 fi
61 done <"${2}"
62
63 if [[ -z "${loaded_base}" ]]; then
64 echo "Could not determine loaded image base."
65 exit 1
66 fi
67
68 if [[ -z "${3}" ]]; then
69 gdb_script=$(mktemp /tmp/debug-sd-boot.XXXXXX.gdb)
70 trap 'rm -f "${gdb_script}"' EXIT
71 else
72 gdb_script="${3}"
73 fi
74
75 cat >"${gdb_script}" <<EOF
76 file ${binary}
77 symbol-file ${symbols} -o ${loaded_base}
78 set architecture ${arch}
79 EOF
80
81 if [[ -z "${3}" ]]; then
82 gdb -x "${gdb_script}" -ex "target remote :1234"
83 else
84 echo "GDB script written to '${gdb_script}'."
85 fi