QEMU and GDB in long mode

From OSDev Wiki
Jump to: navigation, search

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 happens error 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.

Contents

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.

--- 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.

Other issues

Some have experienced issues with breakpoints (using the break command) not firing. Use hbreak instead.

See also

Threads

Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox