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