QEMU and GDB in long mode
If you're running in Long Mode and using QEMU as your emulator you'll likely encounter the following error trying to use QEMU's gdb-stub:
Remote 'g' packet reply is too long: ...
This error happens when QEMU has switched to long mode. There are two workarounds for this: you can either disconnect and reconnect to force GDB to use the x86_64 architecture or patch GDB to switch the architecture on the fly.
Workaround 1: Reconnecting
When you start GDB, connect to QEMU with these commands:
$ gdb
(gdb) set arch i386:x86-64:intel
(gdb) target remote localhost:1234
(gdb) symbol-file YOUR_KERNEL_FILE
(gdb) break SOME_FUNCTION_IN_LONG_MODE
(gdb) continue
When the break point is hit and the "packet reply is too long" happens, run the following:
(gdb) disconnect
(gdb) set arch i386:x86-64
(gdb) target remote localhost:1234
Note that you must use different architecture names in those two "set arch" commands.
Workaround 2: Patching GDB
This is a slightly modified version of the patch posted in this thread. As a bonus, this patch produces a warning when it suspects that the mode switch happened.
[NOTE]: There is an updated version (for GDB 12.1) of this patch at https://github.com/mduft/tachyon3/blob/master/tools/patches/gdb-12.1-archswitch.patch - this is confirmed working with QEMU 7.2.0.
--- gdb/remote.c 2016-04-14 11:13:49.962628700 +0300
+++ gdb/remote.c 2016-04-14 11:15:38.257783400 +0300
@@ -7181,8 +7181,28 @@
buf_len = strlen (rs->buf);
/* Further sanity checks, with knowledge of the architecture. */
+// HACKFIX for changing architectures for qemu. It's ugly. Don't use, unless you have to.
+ // Just a tiny modification of the patch of Matias Vara (http://forum.osdev.org/viewtopic.php?f=13&p=177644)
if (buf_len > 2 * rsa->sizeof_g_packet)
- error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
+ {
+ warning (_("Assuming long-mode change. [Remote 'g' packet reply is too long: %s]"), rs->buf);
+ rsa->sizeof_g_packet = buf_len ;
+
+ for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
+ {
+ if (rsa->regs[i].pnum == -1)
+ continue;
+
+ if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
+ rsa->regs[i].in_g_packet = 0;
+ else
+ rsa->regs[i].in_g_packet = 1;
+ }
+
+ // HACKFIX: Make sure at least the lower half of EIP is set correctly, so the proper
+ // breakpoint is recognized (and triggered).
+ rsa->regs[8].offset = 16*8;
+ }
/* Save the size of the packet sent to us by the target. It is used
as a heuristic when determining the max size of packets that the
The patched GDB emits the error as a warning but continues to function across the mode change. This patch has been tested with gdb 7.11 and 7.12.
Alternatively, you can patch QEMU so that you can use gdb unpatched. Be warned, this probably breaks support for debugging 32-bit code (also, compiling QEMU is hour-long task). In order to do this, replace each occurence of if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
in the file gdbstub.c with if (TARGET_LONG_BITS == 64) {
. However, this method originates from a thread back in 2011, and is untested since.
Workaround 3: Connecting from GDB after long mode has been enabled
This is an easy solution if you don't care to loose a few seconds of computation at the beginning of the emulation. The problem is that gdb is too dumb to understand that processor execution mode changed, so to workaround it you just connect after long mode has been enabled, and gdb never sees the switch. You can create this debug-with-qemu.sh script (or put this in a make target):
#!/bin/env bash
# use setsid so that ctrl+c in gdb doesn't kill qemu
setsid qemu-system-x86_64 -s -boot d -cdrom kernel.iso &
sleep 5
gdb kernel.bin -x qemudbg
where your qemudbg should have something like this:
target remote localhost:1234
and that's it (as long as you don't switch back and forth between modes).
Other issues
Some have experienced issues with breakpoints (using the break
command) not firing. Use hbreak
instead.
In case of using gentoo, this error might occur when emerging sys-devel/gdb
[1] without the xml
USE flag.
See also
Threads
- Emulator for Mac OS X - Dealing with issues on macOS
- Debugging long mode kernel (gdb + qemu)? - workaround without patching gdb
- GDB and QEMU on Win64 - patches for either gdb or qemu
- GDB not breaking at my breakpoints - dealing with 'skipped' breakpoints