Blame SOURCES/gdb-x86_64-i386-syscall-restart.patch

f9426a
http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html
f9426a
Subject: [patch] Fix syscall restarts for amd64->i386 biarch
f9426a
f9426a
Hi,
f9426a
f9426a
tested only on recent Linux kernels, it should apply also on vanilla ones.
f9426a
There were various changes of the kernels behavior in the past.
f9426a
f9426a
FSF GDB HEAD state:
f9426a
kernel debugger inferior state
f9426a
x86_64 x86_64   x86_64   PASS
f9426a
x86_64 x86_64   i386     FAIL without this patch, PASS with this patch
f9426a
x86_64 i386     i386     PASS on recent kernels
f9426a
                         (FAIL: kernel-2.6.31.5-127.fc12.x86_64 - Fedora 12)
f9426a
                         (PASS: kernel-2.6.32-0.55.rc8.git1.fc13.x86_64)
f9426a
i386   i386     i386     PASS
f9426a
f9426a
f9426a
Currently gdb.base/interrupt.exp fails on amd64 host running under
f9426a
--target_board unix/-m32 with:
f9426a
	continue
f9426a
	Continuing.
f9426a
	Unknown error 512
f9426a
f9426a
<linux/errno.h>:
f9426a
/*
f9426a
 * These should never be seen by user programs.  To return one of ERESTART*
f9426a
 * codes, signal_pending() MUST be set.  Note that ptrace can observe these
f9426a
 * at syscall exit tracing, but they will never be left for the debugged user
f9426a
 * process to see.
f9426a
 */
f9426a
#define ERESTARTSYS     512
f9426a
f9426a
"Unknown error 512" printed above is printed by the inferior itself, not by GDB.
f9426a
f9426a
It is because GDB reads it as 0xfffffffffffffe00 but writes it back as
f9426a
0xfffffe00.
f9426a
+      /* Sign-extend %eax as during return from a syscall it is being checked
f9426a
+	 for -ERESTART* values -512 being above 0xfffffffffffffe00; tested by
f9426a
+	 interrupt.exp.  */
f9426a
f9426a
f9426a
Quote of Roland McGrath from IRC:
f9426a
f9426a
roland: in the user_regset model, there are 64-bit user_regset flavors and
f9426a
32-bit user_regset flavors, so at the kabi level the (kernel) caller can say
f9426a
what it means: calls on the 32-bit user_regset flavor will behave as if on
f9426a
a 32-bit kernel/userland.  in ptrace, there is no way for x86_64 ptrace calls
f9426a
to say "i think of the inferior as being 32 bits, so act accordingly" (tho ppc
f9426a
and/or sparc have ptr
f9426a
roland: ace requests that do that iirc)
f9426a
roland: ergo 64-bit ptrace callers must either save/restore full 64-bits so
f9426a
the kernel's sign-extension choices are preserved, or else grok magic ways to
f9426a
expand stored 32-bit register contents to 64-bit values to stuff via 64-bit
f9426a
ptrace
f9426a
[...]
f9426a
roland: there is a "32-bit-flavored task", but it's not really true that it
f9426a
has 32-bit registers.  there is no 32-bit-only userland condition.  any task
f9426a
can always ljmp to the 64-bit code segment and run 64-bit insns including
f9426a
a 64-bit syscall
f9426a
roland: so a 64-bit debugger should see and be able to fiddle the full
f9426a
registers.  it can even change cs via ptrace to force the inferior into
f9426a
running 32 or 64 bit code.
f9426a
f9426a
f9426a
Saving whole 64bits for i386 targets on x86_64 hosts does not much match the
f9426a
GDB architecture as `struct type' for these registers still should be 32bit
f9426a
etc.   Therefore provided just this exception.
f9426a
f9426a
The problem is reproducible only if one does an inferior call during the
f9426a
interruption to do full inferior save/restore from GDB regcache.
f9426a
f9426a
Regression tested on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu.
f9426a
f9426a
f9426a
Thanks,
f9426a
Jan
f9426a
f9426a
f9426a
gdb/
f9426a
2009-11-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
f9426a
f9426a
	* amd64-nat.c (amd64_collect_native_gregset): Do not pre-clear %eax.
f9426a
	Sign extend it afterwards.
f9426a
f9426a
--- a/gdb/amd64-nat.c
f9426a
+++ b/gdb/amd64-nat.c
f9426a
@@ -131,9 +131,9 @@ amd64_collect_native_gregset (const struct regcache *regcache,
f9426a
     {
f9426a
       num_regs = amd64_native_gregset32_num_regs;
f9426a
 
f9426a
-      /* Make sure %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and
f9426a
+      /* Make sure %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and
f9426a
          %eip get zero-extended to 64 bits.  */
f9426a
-      for (i = 0; i <= I386_EIP_REGNUM; i++)
f9426a
+      for (i = I386_ECX_REGNUM; i <= I386_EIP_REGNUM; i++)
f9426a
 	{
f9426a
 	  if (regnum == -1 || regnum == i)
f9426a
 	    memset (regs + amd64_native_gregset_reg_offset (gdbarch, i), 0, 8);
f9426a
@@ -159,4 +159,20 @@ amd64_collect_native_gregset (const struct regcache *regcache,
f9426a
 	    regcache_raw_collect (regcache, i, regs + offset);
f9426a
 	}
f9426a
     }
f9426a
+
f9426a
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
f9426a
+    {
f9426a
+      /* Sign-extend %eax as during return from a syscall it is being checked
f9426a
+	 for -ERESTART* values -512 being above 0xfffffffffffffe00; tested by
f9426a
+	 interrupt.exp.  */
f9426a
+
f9426a
+      int i = I386_EAX_REGNUM;
f9426a
+
f9426a
+      if (regnum == -1 || regnum == i)
f9426a
+	{
f9426a
+	  void *ptr = regs + amd64_native_gregset_reg_offset (gdbarch, i);
f9426a
+
f9426a
+	  *(int64_t *) ptr = *(int32_t *) ptr;
f9426a
+	}
f9426a
+    }
f9426a
 }
f9426a