[PATCH 18/27] efi: Provide an easy way to debug with gdb

Simon Glass sjg at chromium.org
Wed May 28 10:24:44 CEST 2025


Add a Kconfig option to easily enable debugging of the app using the
recommended method. Provide some docs too.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 doc/develop/uefi/u-boot_on_efi.rst | 39 ++++++++++++++++++++++++++++++
 lib/efi_client/Kconfig             | 12 ++++++++-
 lib/efi_client/efi.c               | 36 +++++++++++++++++++++++++++
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/doc/develop/uefi/u-boot_on_efi.rst b/doc/develop/uefi/u-boot_on_efi.rst
index f1f9113b01f..d20d5b00ec6 100644
--- a/doc/develop/uefi/u-boot_on_efi.rst
+++ b/doc/develop/uefi/u-boot_on_efi.rst
@@ -338,6 +338,45 @@ Additionally something like (sda is assumed as disk device):
 	append  root=/dev/sda2 console=tty0 console=ttyS0,115200n8 rootwait rw
 
 
+Debugging
+---------
+
+Debugging the app is not straightforward since it is relocated by the UEFI
+firmware before it is run.
+
+See
+`Debugging UEFI applications with GDB <https://wiki.osdev.org/Debugging_UEFI_applications_with_GDB>`_
+for details.
+
+Within U-Boot, enable `CONFIG_EFI_APP_DEBUG` which will cause U-Boot to write
+deadbeef to address `10000` which you can catch with gdb.
+
+In gdb the procedure is something like this, for a 64-bit machine::
+
+  # Enable CONFIG_EFI_APP_DEBUG in the build
+  $ grep CONFIG_EFI_APP_DEBUG .config
+  CONFIG_EFI_APP_DEBUG=y
+
+  $ gdb u-boot
+  # Connect to the target; here we assume 'qemu -Ss' has been started
+  (gdb) target remote localhost:1234
+
+  # Set a watchpoint for the marker write
+  (gdb) watch *(unsigned long *)0x10000 == 0xdeadbeef
+  (gdb) continue
+
+  # Execution will break as soon as the marker is written.
+  # Now, fetch the relocated base address:
+  (gdb) set $base = *(unsigned long long *)0x10008
+  (gdb) add-symbol-file u-boot -o $base
+
+  # Now you can set other breakpoints as needed
+
+For a 32-bit machine, use `unsigned long` for the cast when setting `$base`
+
+The address of 0x10000 is defined by `GDB_ADDR` which you can change in the
+code if needed.
+
 
 Future work
 -----------
diff --git a/lib/efi_client/Kconfig b/lib/efi_client/Kconfig
index fec5b7e004c..7ac6497ec09 100644
--- a/lib/efi_client/Kconfig
+++ b/lib/efi_client/Kconfig
@@ -70,9 +70,10 @@ config EFI_STUB_64BIT
 
 endchoice
 
+if EFI_APP
+
 config EFI_RAM_SIZE
 	hex "Amount of EFI RAM for U-Boot"
-	depends on EFI_APP
 	default 0x10000000
 	help
 	  Set the amount of EFI RAM which is claimed by U-Boot for its own
@@ -80,4 +81,13 @@ config EFI_RAM_SIZE
 	  other smaller amounts) and it can never be increased after that.
 	  It is used as the RAM size in with U-Boot.
 
+config EFI_APP_DEBUG
+	bool "Enable GDB debugging"
+	help
+	  Enable this to allow GDB to stop the app at an early stage, so it is
+	  possible to set the symbol offset. Since the app is relocated to an
+	  unknown address, breakpoints will only work if this is done.
+
+endif  # EFI_APP
+
 endmenu
diff --git a/lib/efi_client/efi.c b/lib/efi_client/efi.c
index bb1d9e24f84..8b825c7a66e 100644
--- a/lib/efi_client/efi.c
+++ b/lib/efi_client/efi.c
@@ -18,6 +18,31 @@
 #include <efi.h>
 #include <efi_api.h>
 
+enum {
+	/* magic number to trigger gdb breakpoint */
+	GDB_MAGIC	= 0xdeadbeef,
+
+	/* breakpoint address */
+	GDB_ADDR	= 0x10000,
+};
+
+/**
+ * struct gdb_marker - structure to simplify debugging with gdb
+ *
+ * This struct is placed in memory and accessed to trigger a breakpoint in
+ * gdb.
+ *
+ * @magic: Magic number (GDB_MAGIC)
+ * @base: Base address of the app
+ */
+struct gdb_marker {
+	union {
+		u32 magic;
+		u64 space;
+	};
+	void *base;
+};
+
 static struct efi_priv *global_priv;
 
 struct efi_priv *efi_get_priv(void)
@@ -116,6 +141,17 @@ int efi_init(struct efi_priv *priv, const char *banner, efi_handle_t image,
 	priv->loaded_image = loaded_image;
 	priv->image_data_type = loaded_image->image_data_type;
 
+	if (IS_ENABLED(CONFIG_EFI_APP_DEBUG)) {
+		struct gdb_marker *marker = (struct gdb_marker *)GDB_ADDR;
+		char buf[64];
+
+		marker->base = priv->loaded_image->image_base;
+		snprintf(buf, sizeof(buf), "\ngdb marker at %p base %p\n",
+			 marker, marker->base);
+		efi_puts(priv, buf);
+		marker->magic = 0xdeadbeef;
+	}
+
 	return 0;
 }
 
-- 
2.43.0



More information about the U-Boot mailing list