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

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