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

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