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