QEMU and GDB in long mode

From OSDev.wiki
Revision as of 11:09, 14 April 2016 by osdev>Hellbender (Added instructions how to deal with the "packed too long" error.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

If you encounter "Remote 'g' packet reply is too long: ..." error when the QEMU has switched to long mode, you have two possible solutions. You can either disconnect and reconnect to force GDB to use the x86_64 architecture, or you can patch GDB to switch the architecture on the fly.

Reconnecting

When you start GDB, you connect to the QEMU as follows:

> gdb
set arch i386:x86-64:intel
target remote localhost:1234
symbol-file YOUR_KERNEL_FILE
break SOME_FUNCTION_IN_LONG_MODE
continue

When the break point is hit and the "packet reply is too long" happens, you just run the following:

disconnect
set arch i386:x86-64
target remote localhost:1234

Note that you must use different architecture names in those two "set arch" commands.

Patching GDB

This is a slightly modified version from http://forum.osdev.org/viewtopic.php?f=1&t=28262. I added a warning to see when the package error happens.

tar xzf gdb-7.11.tar.gz
cd gdb-7.11
patch -p0 <<EOF
--- 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
EOF
cd ..
mkdir build-gdb
cd build-gdb
../gdb-7.11/configure --prefix$HOME/opt/cross --disable-docs
make && make install

The patched GDB emits the error as a warning but continues to function across the mode change.

External Links

http://forum.osdev.org/viewtopic.php?f=1&t=28262

http://forum.osdev.org/viewtopic.php?f=1&t=30285

http://forum.osdev.org/viewtopic.php?f=13&p=177644