]>
Commit | Line | Data |
---|---|---|
ab050a48 BZ |
1 | http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html |
2 | Subject: [patch] Fix syscall restarts for amd64->i386 biarch | |
3 | ||
4 | Hi, | |
5 | ||
6 | tested only on recent Linux kernels, it should apply also on vanilla ones. | |
7 | There were various changes of the kernels behavior in the past. | |
8 | ||
9 | FSF GDB HEAD state: | |
10 | kernel debugger inferior state | |
11 | x86_64 x86_64 x86_64 PASS | |
12 | x86_64 x86_64 i386 FAIL without this patch, PASS with this patch | |
13 | x86_64 i386 i386 PASS on recent kernels | |
14 | (FAIL: kernel-2.6.31.5-127.fc12.x86_64 - Fedora 12) | |
15 | (PASS: kernel-2.6.32-0.55.rc8.git1.fc13.x86_64) | |
16 | i386 i386 i386 PASS | |
17 | ||
18 | ||
19 | Currently gdb.base/interrupt.exp fails on amd64 host running under | |
20 | --target_board unix/-m32 with: | |
21 | continue | |
22 | Continuing. | |
23 | Unknown error 512 | |
24 | ||
25 | <linux/errno.h>: | |
26 | /* | |
27 | * These should never be seen by user programs. To return one of ERESTART* | |
28 | * codes, signal_pending() MUST be set. Note that ptrace can observe these | |
29 | * at syscall exit tracing, but they will never be left for the debugged user | |
30 | * process to see. | |
31 | */ | |
32 | #define ERESTARTSYS 512 | |
33 | ||
34 | "Unknown error 512" printed above is printed by the inferior itself, not by GDB. | |
35 | ||
36 | It is because GDB reads it as 0xfffffffffffffe00 but writes it back as | |
37 | 0xfffffe00. | |
38 | + /* Sign-extend %eax as during return from a syscall it is being checked | |
39 | + for -ERESTART* values -512 being above 0xfffffffffffffe00; tested by | |
40 | + interrupt.exp. */ | |
41 | ||
42 | ||
43 | Quote of Roland McGrath from IRC: | |
44 | ||
45 | roland: in the user_regset model, there are 64-bit user_regset flavors and | |
46 | 32-bit user_regset flavors, so at the kabi level the (kernel) caller can say | |
47 | what it means: calls on the 32-bit user_regset flavor will behave as if on | |
48 | a 32-bit kernel/userland. in ptrace, there is no way for x86_64 ptrace calls | |
49 | to say "i think of the inferior as being 32 bits, so act accordingly" (tho ppc | |
50 | and/or sparc have ptr | |
51 | roland: ace requests that do that iirc) | |
52 | roland: ergo 64-bit ptrace callers must either save/restore full 64-bits so | |
53 | the kernel's sign-extension choices are preserved, or else grok magic ways to | |
54 | expand stored 32-bit register contents to 64-bit values to stuff via 64-bit | |
55 | ptrace | |
56 | [...] | |
57 | roland: there is a "32-bit-flavored task", but it's not really true that it | |
58 | has 32-bit registers. there is no 32-bit-only userland condition. any task | |
59 | can always ljmp to the 64-bit code segment and run 64-bit insns including | |
60 | a 64-bit syscall | |
61 | roland: so a 64-bit debugger should see and be able to fiddle the full | |
62 | registers. it can even change cs via ptrace to force the inferior into | |
63 | running 32 or 64 bit code. | |
64 | ||
65 | ||
66 | Saving whole 64bits for i386 targets on x86_64 hosts does not much match the | |
67 | GDB architecture as `struct type' for these registers still should be 32bit | |
68 | etc. Therefore provided just this exception. | |
69 | ||
70 | The problem is reproducible only if one does an inferior call during the | |
71 | interruption to do full inferior save/restore from GDB regcache. | |
72 | ||
73 | Regression tested on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu. | |
74 | ||
75 | ||
76 | Thanks, | |
77 | Jan | |
78 | ||
79 | ||
80 | gdb/ | |
81 | 2009-11-29 Jan Kratochvil <jan.kratochvil@redhat.com> | |
82 | ||
83 | * amd64-nat.c (amd64_collect_native_gregset): Do not pre-clear %eax. | |
84 | Sign extend it afterwards. | |
85 | ||
86 | --- a/gdb/amd64-nat.c | |
87 | +++ b/gdb/amd64-nat.c | |
88 | @@ -131,9 +131,9 @@ amd64_collect_native_gregset (const struct regcache *regcache, | |
89 | { | |
90 | num_regs = amd64_native_gregset32_num_regs; | |
91 | ||
92 | - /* Make sure %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and | |
93 | + /* Make sure %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and | |
94 | %eip get zero-extended to 64 bits. */ | |
95 | - for (i = 0; i <= I386_EIP_REGNUM; i++) | |
96 | + for (i = I386_ECX_REGNUM; i <= I386_EIP_REGNUM; i++) | |
97 | { | |
98 | if (regnum == -1 || regnum == i) | |
99 | memset (regs + amd64_native_gregset_reg_offset (gdbarch, i), 0, 8); | |
100 | @@ -159,4 +159,20 @@ amd64_collect_native_gregset (const struct regcache *regcache, | |
101 | regcache_raw_collect (regcache, i, regs + offset); | |
102 | } | |
103 | } | |
104 | + | |
105 | + if (gdbarch_ptr_bit (gdbarch) == 32) | |
106 | + { | |
107 | + /* Sign-extend %eax as during return from a syscall it is being checked | |
108 | + for -ERESTART* values -512 being above 0xfffffffffffffe00; tested by | |
109 | + interrupt.exp. */ | |
110 | + | |
111 | + int i = I386_EAX_REGNUM; | |
112 | + | |
113 | + if (regnum == -1 || regnum == i) | |
114 | + { | |
115 | + void *ptr = regs + amd64_native_gregset_reg_offset (gdbarch, i); | |
116 | + | |
117 | + *(int64_t *) ptr = *(int32_t *) ptr; | |
118 | + } | |
119 | + } | |
120 | } | |
121 |