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

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