* Re: [rfa] Handle amd64-linux %orig_rax
@ 2006-10-31 20:10 Datoda
2006-10-31 20:17 ` Andi Kleen
0 siblings, 1 reply; 13+ messages in thread
From: Datoda @ 2006-10-31 20:10 UTC (permalink / raw)
To: Andi Kleen, Daniel Jacobowitz; +Cc: gdb-patches
I think i386 shouldn't have the same problems, as far as gdb inferior calls are concerned, because arguments are passed in stack rather than in registers.
----- Original Message ----
From: Andi Kleen <ak@suse.de>
To: Daniel Jacobowitz <drow@false.org>
Cc: Datoda <datoda@yahoo.com>; gdb-patches@sourceware.org
Sent: Tuesday, October 31, 2006 1:40:38 PM
Subject: Re: [rfa] Handle amd64-linux %orig_rax
On Tuesday 31 October 2006 19:22, Daniel Jacobowitz wrote:
> Andi, have you got any opinion on this? The problem arises when GDB
> sets %orig_rax to -1 to indicate that the interrupted syscall should
> not be resumed, and then sets %rip to some other address; the kernel is
> still changing %rcx on the way out to userspace. I think this sounds
> like a kernel bug.
You would need to complain to the x86 ISA designers.
SYSRET requires us to trash %rcx, there is no other way to use it.
This means IRET won't clobber any registers (and it is used in a few
situations where this is critical), but it is significantly slower.
Ok in theory we could check if the process is traced and then
always use IRET, but then you would get different behaviour
depending on being traced or not which is probably not
a good idea.
BTW on i386 which uses SYSEXIT sometimes there are likely similar
problems. SYSEXIT also requires to clobber registers.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
@ 2006-11-01 15:10 Datoda
2006-11-01 15:15 ` Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Datoda @ 2006-11-01 15:10 UTC (permalink / raw)
To: Daniel Jacobowitz, Andi Kleen, gdb-patches
Here's the kernel version info:
godel:~/gdb-ftp/gdb-6.5.50.20061030/gdb$ uname -a
Linux godel 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:29:47 EST 2005 x86_64 x86_64 x86_64 GNU/Linux
It's EL4 and quite old. Do you know what kernel version would have Andi's patch?
----- Original Message ----
From: Daniel Jacobowitz <drow@false.org>
To: Andi Kleen <ak@suse.de>; Datoda <datoda@yahoo.com>; gdb-patches@sourceware.org
Sent: Tuesday, October 31, 2006 2:32:57 PM
Subject: Re: [rfa] Handle amd64-linux %orig_rax
On Tue, Oct 31, 2006 at 02:30:35PM -0500, Daniel Jacobowitz wrote:
> On Tue, Oct 31, 2006 at 08:11:20PM +0100, Andi Kleen wrote:
> >
> > > Oh dear. So if we set registers on the syscall exit path, the
> > > kernel/ISA may just eat them. And we have no reliable way to know
> > > whether we're stopped on the syscall exit path.
> >
> > If you're single stepping over it you can remember it from
> > one instruction before (check if the opcode is SYSCALL or SYSENTER,
> > these are unique 2 byte opcodes each)
> >
> > If someone sets a breakpoint directly on the return point
> > and doesn't single step that wouldn't work, but then you shouldn't care about
> > the previous register state anyways.
>
> This case is usually SIGINT while inside a syscall, e.g. nanosleep.
> That gives us a prompt, and if the user changes $rcx there, we write
> into the register - and later it gets overridden. i.e. we're at the
> ptrace_stop call in kernel/signal.c:get_signal_to_deliver.
>
> I'm not quite sure how we're getting into the problem case though?
> I'd have guessed we were in sysret_signal and that uses iret.
Datoda, what kernel version were you using? I wonder if this fixed it
as a side effect:
Commit: 7bf36bbc5e0c09271f9efe22162f8cc3f8ebd3d2
Author: Andi Kleen <ak@suse.de> Fri, 07 Apr 2006 19:50:00 +0200
[PATCH] x86_64: When user could have changed RIP always force IRET
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [rfa] Handle amd64-linux %orig_rax
2006-11-01 15:10 Datoda
@ 2006-11-01 15:15 ` Daniel Jacobowitz
0 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-11-01 15:15 UTC (permalink / raw)
To: Datoda; +Cc: Andi Kleen, gdb-patches
On Wed, Nov 01, 2006 at 07:10:09AM -0800, Datoda wrote:
> Here's the kernel version info:
>
> godel:~/gdb-ftp/gdb-6.5.50.20061030/gdb$ uname -a
> Linux godel 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:29:47 EST 2005 x86_64 x86_64 x86_64 GNU/Linux
>
> It's EL4 and quite old. Do you know what kernel version would have Andi's patch?
Not offhand. However, I just tried this on a 2.6.19-rc1 x86_64 kernel
- and now it works OK.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE:[rfa] Handle amd64-linux %orig_rax
@ 2006-10-31 18:17 Datoda
2006-10-31 18:22 ` [rfa] " Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Datoda @ 2006-10-31 18:17 UTC (permalink / raw)
To: gdb-patches
I just downloaded the GDB CVS snapshot from 20061030, which contains Daniel's patch, and built a gdb with it on x86_64 Linux. Here's a transcript of a debug session:
--- Transcript begins ---
GNU gdb 6.5.50.20061030
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...
Using host libthread_db library "/lib64/tls/libthread_db.so.1".
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Function "info_command" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
/site/spt/usr7/cchen15/gdb-ftp/gdb-6.5.50.20061030/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) l 1
1 #include <stdio.h>
2 #include <unistd.h>
3
4 int func1 (int a, int b, int c, int d)
5 {
6 return a + b + c + d;
7 }
8
9 int main ()
10 {
(gdb) l
11 printf ("Sleeping...\n");
12 sleep(100);
13 func1(1,2,3,4);
14 return 0;
15 }
16
(gdb) r
Starting program: /site/spt/usr7/cchen15/em64t/interrupt
Sleeping...
Program received signal SIGINT, Interrupt.
0x0000003cad08e992 in __nanosleep_nocancel () from /lib64/tls/libc.so.6
(gdb) p func1(1,2,3,4)
During symbol reading, incomplete CFI data; unspecified registers (e.g., rax) at 0x3cad08e99f.
$1 = 4195998
(gdb) p func1(1,2,3,4)
$2 = 10
(gdb)
--- Transcript ends ---
As you can see, gdb returns the wrong value on a function that takes four (as shown here) or more arguments when the process is interrupted when inside a system call.
Here's my explanation of the cause of this problem: According to the AMD64 ABI, Section A.2, Item 2., the kernel destroys %rcx in a syscall. Meanwhile, the calling convention uses %rcx to pass in the fourth argument to the function being called. Therefore, the kernel may trash the fourth argument to an inferior call even when it's not restarting the interrupted system call (i.e., when %orig_rax is set to a negative value) because the kernel is still in the "syscall mode".
A repeat inferior call returns the correct value because the kernel has left that syscall mode when doing the first inferior call.
It appears to me that instead of telling the kernel not to restart a syscall by setting %orig_rax to -1, gdb should be telling the kernel to forget about the syscall all together when initiating an inferior call, and restoring the kernel's memory about the interrupted syscall when the inferior call finishes. I don't know how that can be achieved, though.
Alternatively, the kernel can be made to suppress trashing %rcx when the process is being debugged and %orig_rax is -1. But I don't know the ramification/implication of this change.
Or perhaps it's just a kernel bug that needs to be fixed....
Any other insight on this?
===========================================
[rfa] Handle amd64-linux %orig_rax
From: Daniel Jacobowitz <drow at false dot org>
To: gdb-patches at sourceware dot org
Date: Sat, 19 Aug 2006 00:20:40 -0400
Subject: [rfa] Handle amd64-linux %orig_rax
--------------------------------------------------------------------------------
x86_64-pc-linux-gnu has an %orig_rax "register", exactly parallel to the
i386-pc-linux-gnu %orig_eax. It's set to a syscall number to trigger
system call restarting, and has to be set to -1 when we want to prevent
restarting. It appears to be in every regard the same as the i386
version; this copies the i386 handling, and fits it into the existing
amd64 infrastructure.
Tested on x86_64-pc-linux-gnu; this fixes the interrupt.exp timeouts,
finally. I've known what this was for ages but never had the patience to
make the mechanical change before, and someone reported this as a bug on the
Eclipse CDT list recently.
Does this look OK?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 18:17 Datoda
@ 2006-10-31 18:22 ` Daniel Jacobowitz
2006-10-31 18:40 ` Andi Kleen
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-10-31 18:22 UTC (permalink / raw)
To: Datoda, Andi Kleen; +Cc: gdb-patches
Andi, have you got any opinion on this? The problem arises when GDB
sets %orig_rax to -1 to indicate that the interrupted syscall should
not be resumed, and then sets %rip to some other address; the kernel is
still changing %rcx on the way out to userspace. I think this sounds
like a kernel bug.
On Tue, Oct 31, 2006 at 10:17:01AM -0800, Datoda wrote:
> Here's my explanation of the cause of this problem: According to the
> AMD64 ABI, Section A.2, Item 2., the kernel destroys %rcx in a
> syscall. Meanwhile, the calling convention uses %rcx to pass in the
> fourth argument to the function being called. Therefore, the kernel
> may trash the fourth argument to an inferior call even when it's not
> restarting the interrupted system call (i.e., when %orig_rax is set
> to a negative value) because the kernel is still in the "syscall
> mode".
>
> A repeat inferior call returns the correct value because the kernel
> has left that syscall mode when doing the first inferior call.
>
> It appears to me that instead of telling the kernel not to restart a
> syscall by setting %orig_rax to -1, gdb should be telling the kernel
> to forget about the syscall all together when initiating an inferior
> call, and restoring the kernel's memory about the interrupted syscall
> when the inferior call finishes. I don't know how that can be
> achieved, though.
We don't need to restore it; we can just restart the syscall from
scratch.
> Alternatively, the kernel can be made to suppress trashing %rcx when
> the process is being debugged and %orig_rax is -1. But I don't know
> the ramification/implication of this change.
>
> Or perhaps it's just a kernel bug that needs to be fixed....
>
> Any other insight on this?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 18:22 ` [rfa] " Daniel Jacobowitz
@ 2006-10-31 18:40 ` Andi Kleen
2006-10-31 18:49 ` Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Andi Kleen @ 2006-10-31 18:40 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Datoda, gdb-patches
On Tuesday 31 October 2006 19:22, Daniel Jacobowitz wrote:
> Andi, have you got any opinion on this? The problem arises when GDB
> sets %orig_rax to -1 to indicate that the interrupted syscall should
> not be resumed, and then sets %rip to some other address; the kernel is
> still changing %rcx on the way out to userspace. I think this sounds
> like a kernel bug.
You would need to complain to the x86 ISA designers.
SYSRET requires us to trash %rcx, there is no other way to use it.
This means IRET won't clobber any registers (and it is used in a few
situations where this is critical), but it is significantly slower.
Ok in theory we could check if the process is traced and then
always use IRET, but then you would get different behaviour
depending on being traced or not which is probably not
a good idea.
BTW on i386 which uses SYSEXIT sometimes there are likely similar
problems. SYSEXIT also requires to clobber registers.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 18:40 ` Andi Kleen
@ 2006-10-31 18:49 ` Daniel Jacobowitz
2006-10-31 19:11 ` Andi Kleen
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-10-31 18:49 UTC (permalink / raw)
To: Andi Kleen; +Cc: Datoda, gdb-patches
On Tue, Oct 31, 2006 at 07:40:38PM +0100, Andi Kleen wrote:
> On Tuesday 31 October 2006 19:22, Daniel Jacobowitz wrote:
> > Andi, have you got any opinion on this? The problem arises when GDB
> > sets %orig_rax to -1 to indicate that the interrupted syscall should
> > not be resumed, and then sets %rip to some other address; the kernel is
> > still changing %rcx on the way out to userspace. I think this sounds
> > like a kernel bug.
>
> You would need to complain to the x86 ISA designers.
>
> SYSRET requires us to trash %rcx, there is no other way to use it.
> This means IRET won't clobber any registers (and it is used in a few
> situations where this is critical), but it is significantly slower.
Oh dear. So if we set registers on the syscall exit path, the
kernel/ISA may just eat them. And we have no reliable way to know
whether we're stopped on the syscall exit path. There's gotta be a
better way, but I don't know what it might be...
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 18:49 ` Daniel Jacobowitz
@ 2006-10-31 19:11 ` Andi Kleen
2006-10-31 19:30 ` Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Andi Kleen @ 2006-10-31 19:11 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Datoda, gdb-patches
> Oh dear. So if we set registers on the syscall exit path, the
> kernel/ISA may just eat them. And we have no reliable way to know
> whether we're stopped on the syscall exit path.
If you're single stepping over it you can remember it from
one instruction before (check if the opcode is SYSCALL or SYSENTER,
these are unique 2 byte opcodes each)
If someone sets a breakpoint directly on the return point
and doesn't single step that wouldn't work, but then you shouldn't care about
the previous register state anyways.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 19:11 ` Andi Kleen
@ 2006-10-31 19:30 ` Daniel Jacobowitz
2006-10-31 19:33 ` Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-10-31 19:30 UTC (permalink / raw)
To: Andi Kleen; +Cc: Datoda, gdb-patches
On Tue, Oct 31, 2006 at 08:11:20PM +0100, Andi Kleen wrote:
>
> > Oh dear. So if we set registers on the syscall exit path, the
> > kernel/ISA may just eat them. And we have no reliable way to know
> > whether we're stopped on the syscall exit path.
>
> If you're single stepping over it you can remember it from
> one instruction before (check if the opcode is SYSCALL or SYSENTER,
> these are unique 2 byte opcodes each)
>
> If someone sets a breakpoint directly on the return point
> and doesn't single step that wouldn't work, but then you shouldn't care about
> the previous register state anyways.
This case is usually SIGINT while inside a syscall, e.g. nanosleep.
That gives us a prompt, and if the user changes $rcx there, we write
into the register - and later it gets overridden. i.e. we're at the
ptrace_stop call in kernel/signal.c:get_signal_to_deliver.
I'm not quite sure how we're getting into the problem case though?
I'd have guessed we were in sysret_signal and that uses iret.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-10-31 19:30 ` Daniel Jacobowitz
@ 2006-10-31 19:33 ` Daniel Jacobowitz
0 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-10-31 19:33 UTC (permalink / raw)
To: Andi Kleen, Datoda, gdb-patches
On Tue, Oct 31, 2006 at 02:30:35PM -0500, Daniel Jacobowitz wrote:
> On Tue, Oct 31, 2006 at 08:11:20PM +0100, Andi Kleen wrote:
> >
> > > Oh dear. So if we set registers on the syscall exit path, the
> > > kernel/ISA may just eat them. And we have no reliable way to know
> > > whether we're stopped on the syscall exit path.
> >
> > If you're single stepping over it you can remember it from
> > one instruction before (check if the opcode is SYSCALL or SYSENTER,
> > these are unique 2 byte opcodes each)
> >
> > If someone sets a breakpoint directly on the return point
> > and doesn't single step that wouldn't work, but then you shouldn't care about
> > the previous register state anyways.
>
> This case is usually SIGINT while inside a syscall, e.g. nanosleep.
> That gives us a prompt, and if the user changes $rcx there, we write
> into the register - and later it gets overridden. i.e. we're at the
> ptrace_stop call in kernel/signal.c:get_signal_to_deliver.
>
> I'm not quite sure how we're getting into the problem case though?
> I'd have guessed we were in sysret_signal and that uses iret.
Datoda, what kernel version were you using? I wonder if this fixed it
as a side effect:
Commit: 7bf36bbc5e0c09271f9efe22162f8cc3f8ebd3d2
Author: Andi Kleen <ak@suse.de> Fri, 07 Apr 2006 19:50:00 +0200
[PATCH] x86_64: When user could have changed RIP always force IRET
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
* [rfa] Handle amd64-linux %orig_rax
@ 2006-08-19 15:34 Daniel Jacobowitz
2006-08-19 15:46 ` Mark Kettenis
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-08-19 15:34 UTC (permalink / raw)
To: gdb-patches
x86_64-pc-linux-gnu has an %orig_rax "register", exactly parallel to the
i386-pc-linux-gnu %orig_eax. It's set to a syscall number to trigger
system call restarting, and has to be set to -1 when we want to prevent
restarting. It appears to be in every regard the same as the i386
version; this copies the i386 handling, and fits it into the existing
amd64 infrastructure.
Tested on x86_64-pc-linux-gnu; this fixes the interrupt.exp timeouts,
finally. I've known what this was for ages but never had the patience to
make the mechanical change before, and someone reported this as a bug on the
Eclipse CDT list recently.
Does this look OK?
--
Daniel Jacobowitz
CodeSourcery
2006-08-19 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (amd64_linux_tdep_h): New.
(amd64-linux-nat.o, amd64-linux-tdep.o): Update.
* amd64-linux-nat.c (amd64_linux_gregset64_reg_offset): Add
ORIG_RAX.
(_initialize_amd64_linux_nat): Set amd64_native_gregset64_num_regs.
* amd64-linux-tdep.c (amd64_linux_register_name)
(amd64_linux_register_type, amd64_linux_register_reggroup_p)
(amd64_linux_write_pc): New.
(amd64_linux_init_abi): Use them, and update num_regs.
* amd64-linux-tdep.h: New file.
* amd64-tdep.c (amd64_register_name, amd64_register_type): Make
public.
* amd64-tdep.h (amd64_register_name, amd64_register_type): New
prototypes.
* regformats/reg-x86-64-linux.dat: New file.
2006-08-19 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (clean): Clean reg-x86-64-linux.c.
(reg-x86-64-linux.o, reg-x86-64-linux.c): New.
* configure.srv (x86_64-*-linux*): Use reg-x86-64-linux.o.
* linux-x86-64-low.c (x86_64_regmap): Include ORIG_RAX.
(x86_64_fill_gregset, x86_64_store_gregset): Skip floating
point registers.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.838
diff -u -p -r1.838 Makefile.in
--- Makefile.in 8 Aug 2006 22:06:06 -0000 1.838
+++ Makefile.in 19 Aug 2006 04:13:56 -0000
@@ -638,6 +638,7 @@ ada_lang_h = ada-lang.h $(value_h) $(gdb
ada_lex_c = ada-lex.c $(gdb_string_h)
alphabsd_tdep_h = alphabsd-tdep.h
alpha_tdep_h = alpha-tdep.h
+amd64_linux_tdep_h = amd64-linux-tdep.h
amd64_nat_h = amd64-nat.h
amd64_tdep_h = amd64-tdep.h $(i386_tdep_h)
annotate_h = annotate.h $(symtab_h) $(gdbtypes_h)
@@ -1738,10 +1739,10 @@ amd64fbsd-tdep.o: amd64fbsd-tdep.c $(def
amd64-linux-nat.o: amd64-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) \
$(gdb_proc_service_h) $(gregset_h) $(amd64_tdep_h) \
- $(i386_linux_tdep_h) $(amd64_nat_h) $(target_h)
+ $(i386_linux_tdep_h) $(amd64_nat_h) $(target_h) $(amd64_linux_tdep_h)
amd64-linux-tdep.o: amd64-linux-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \
$(regcache_h) $(osabi_h) $(symtab_h) $(gdb_string_h) $(amd64_tdep_h) \
- $(solib_svr4_h)
+ $(solib_svr4_h) $(gdbtypes_h) $(reggroups_h) $(amd64_linux_tdep_h)
amd64-nat.o: amd64-nat.c $(defs_h) $(gdbarch_h) $(regcache_h) \
$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(amd64_tdep_h)
amd64nbsd-nat.o: amd64nbsd-nat.c $(defs_h) $(target_h) $(gdb_assert_h) \
Index: amd64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/amd64-linux-nat.c,v
retrieving revision 1.12
diff -u -p -r1.12 amd64-linux-nat.c
--- amd64-linux-nat.c 24 Mar 2006 23:08:16 -0000 1.12
+++ amd64-linux-nat.c 19 Aug 2006 04:13:56 -0000
@@ -26,6 +26,7 @@
#include "gdbcore.h"
#include "regcache.h"
#include "linux-nat.h"
+#include "amd64-linux-tdep.h"
#include "gdb_assert.h"
#include "gdb_string.h"
@@ -68,7 +69,12 @@ static int amd64_linux_gregset64_reg_off
RIP * 8, EFLAGS * 8, /* %rip, %eflags */
CS * 8, SS * 8, /* %cs, %ss */
DS * 8, ES * 8, /* %ds, %es */
- FS * 8, GS * 8 /* %fs, %gs */
+ FS * 8, GS * 8, /* %fs, %gs */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ ORIG_RAX * 8
};
\f
@@ -382,6 +388,7 @@ _initialize_amd64_linux_nat (void)
amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
+ amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
== amd64_native_gregset32_num_regs);
Index: amd64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/amd64-linux-tdep.c,v
retrieving revision 1.11
diff -u -p -r1.11 amd64-linux-tdep.c
--- amd64-linux-tdep.c 17 Dec 2005 22:33:59 -0000 1.11
+++ amd64-linux-tdep.c 19 Aug 2006 04:13:56 -0000
@@ -1,6 +1,6 @@
/* Target-dependent code for GNU/Linux x86-64.
- Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@@ -26,6 +26,9 @@
#include "regcache.h"
#include "osabi.h"
#include "symtab.h"
+#include "gdbtypes.h"
+#include "reggroups.h"
+#include "amd64-linux-tdep.h"
#include "gdb_string.h"
@@ -199,6 +202,61 @@ static int amd64_linux_sc_reg_offset[] =
-1 /* %gs */
};
+/* Replacement register functions which know about %orig_rax. */
+
+static const char *
+amd64_linux_register_name (int reg)
+{
+ if (reg == AMD64_LINUX_ORIG_RAX_REGNUM)
+ return "orig_rax";
+
+ return amd64_register_name (reg);
+}
+
+static struct type *
+amd64_linux_register_type (struct gdbarch *gdbarch, int reg)
+{
+ if (reg == AMD64_LINUX_ORIG_RAX_REGNUM)
+ return builtin_type_int64;
+
+ return amd64_register_type (gdbarch, reg);
+}
+
+static int
+amd64_linux_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
+{
+ if (regnum == AMD64_LINUX_ORIG_RAX_REGNUM)
+ return (group == system_reggroup
+ || group == save_reggroup
+ || group == restore_reggroup);
+ return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
+/* Set the program counter for process PTID to PC. */
+
+static void
+amd64_linux_write_pc (CORE_ADDR pc, ptid_t ptid)
+{
+ write_register_pid (AMD64_RIP_REGNUM, pc, ptid);
+
+ /* We must be careful with modifying the program counter. If we
+ just interrupted a system call, the kernel might try to restart
+ it when we resume the inferior. On restarting the system call,
+ the kernel will try backing up the program counter even though it
+ no longer points at the system call. This typically results in a
+ SIGSEGV or SIGILL. We can prevent this by writing `-1' in the
+ "orig_rax" pseudo-register.
+
+ Note that "orig_rax" is saved when setting up a dummy call frame.
+ This means that it is properly restored when that frame is
+ popped, and that the interrupted system call will be restarted
+ when we resume the inferior on return from a function call from
+ within GDB. In all other cases the system call will not be
+ restarted. */
+ write_register_pid (AMD64_LINUX_ORIG_RAX_REGNUM, -1, ptid);
+}
+
static void
amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -219,6 +277,13 @@ amd64_linux_init_abi (struct gdbarch_inf
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
+ /* Add the %orig_rax register used for syscall restarting. */
+ set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
+ set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
+ set_gdbarch_register_name (gdbarch, amd64_linux_register_name);
+ set_gdbarch_register_type (gdbarch, amd64_linux_register_type);
+ set_gdbarch_register_reggroup_p (gdbarch, amd64_linux_register_reggroup_p);
+
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
Index: amd64-linux-tdep.h
===================================================================
RCS file: amd64-linux-tdep.h
diff -N amd64-linux-tdep.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ amd64-linux-tdep.h 19 Aug 2006 04:13:56 -0000
@@ -0,0 +1,36 @@
+/* Target-dependent code for GNU/Linux AMD64.
+
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifndef AMD64_LINUX_TDEP_H
+#define AMD64_LINUX_TDEP_H
+
+/* Like for i386 GNU/Linux, there is an extra "register"
+ used to control syscall restarting. */
+
+/* Register number for the "orig_rax" register. If this register
+ contains a value >= 0 it is interpreted as the system call number
+ that the kernel is supposed to restart. */
+#define AMD64_LINUX_ORIG_RAX_REGNUM (AMD64_MXCSR_REGNUM + 1)
+
+/* Total number of registers for GNU/Linux. */
+#define AMD64_LINUX_NUM_REGS (AMD64_LINUX_ORIG_RAX_REGNUM + 1)
+
+#endif /* amd64-linux-tdep.h */
Index: amd64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/amd64-tdep.c,v
retrieving revision 1.31
diff -u -p -r1.31 amd64-tdep.c
--- amd64-tdep.c 29 Jan 2006 21:19:31 -0000 1.31
+++ amd64-tdep.c 19 Aug 2006 04:13:57 -0000
@@ -129,7 +129,7 @@ static struct amd64_register_info const
/* Return the name of register REGNUM. */
-static const char *
+const char *
amd64_register_name (int regnum)
{
if (regnum >= 0 && regnum < AMD64_NUM_REGS)
@@ -141,7 +141,7 @@ amd64_register_name (int regnum)
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. */
-static struct type *
+struct type *
amd64_register_type (struct gdbarch *gdbarch, int regnum)
{
gdb_assert (regnum >= 0 && regnum < AMD64_NUM_REGS);
Index: amd64-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/amd64-tdep.h,v
retrieving revision 1.6
diff -u -p -r1.6 amd64-tdep.h
--- amd64-tdep.h 17 Dec 2005 22:33:59 -0000 1.6
+++ amd64-tdep.h 19 Aug 2006 04:13:57 -0000
@@ -64,6 +64,12 @@ enum amd64_regnum
extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
+/* Functions from amd64-tdep.c which may be needed on architectures
+ with extra registers. */
+
+extern const char *amd64_register_name (int regnum);
+extern struct type *amd64_register_type (struct gdbarch *gdbarch, int regnum);
+
/* Fill register REGNUM in REGCACHE with the appropriate
floating-point or SSE register value from *FXSAVE. If REGNUM is
-1, do this for all registers. This function masks off any of the
Index: gdbserver/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/Makefile.in,v
retrieving revision 1.37
diff -u -p -r1.37 Makefile.in
--- gdbserver/Makefile.in 23 Jul 2006 03:52:15 -0000 1.37
+++ gdbserver/Makefile.in 19 Aug 2006 04:13:57 -0000
@@ -206,7 +206,7 @@ clean:
rm -f gdbserver gdbreplay core make.log
rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m32r.c reg-m68k.c reg-mips.c
rm -f reg-ppc.c reg-sh.c reg-x86-64.c reg-i386-linux.c
- rm -f reg-cris.c reg-crisv32.c
+ rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c
maintainer-clean realclean distclean: clean
rm -f nm.h tm.h xm.h config.status config.h stamp-h config.log
@@ -334,5 +334,8 @@ reg-sh.c : $(srcdir)/../regformats/reg-s
reg-x86-64.o : reg-x86-64.c $(regdef_h)
reg-x86-64.c : $(srcdir)/../regformats/reg-x86-64.dat $(regdat_sh)
sh $(regdat_sh) $(srcdir)/../regformats/reg-x86-64.dat reg-x86-64.c
+reg-x86-64-linux.o : reg-x86-64-linux.c $(regdef_h)
+reg-x86-64-linux.c : $(srcdir)/../regformats/reg-x86-64-linux.dat $(regdat_sh)
+ sh $(regdat_sh) $(srcdir)/../regformats/reg-x86-64-linux.dat reg-x86-64-linux.c
# This is the end of "Makefile.in".
Index: gdbserver/configure.srv
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure.srv,v
retrieving revision 1.15
diff -u -p -r1.15 configure.srv
--- gdbserver/configure.srv 23 Jul 2006 03:52:15 -0000 1.15
+++ gdbserver/configure.srv 19 Aug 2006 04:13:57 -0000
@@ -97,7 +97,7 @@ case "${target}" in
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
- x86_64-*-linux*) srv_regobj=reg-x86-64.o
+ x86_64-*-linux*) srv_regobj=reg-x86-64-linux.o
srv_tgtobj="linux-low.o linux-x86-64-low.o i387-fp.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
Index: gdbserver/linux-x86-64-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-x86-64-low.c,v
retrieving revision 1.12
diff -u -p -r1.12 linux-x86-64-low.c
--- gdbserver/linux-x86-64-low.c 15 Mar 2006 16:13:29 -0000 1.12
+++ gdbserver/linux-x86-64-low.c 19 Aug 2006 04:13:57 -0000
@@ -50,7 +50,12 @@ static int x86_64_regmap[] = {
R8 * 8, R9 * 8, R10 * 8, R11 * 8,
R12 * 8, R13 * 8, R14 * 8, R15 * 8,
RIP * 8, EFLAGS * 8, CS * 8, SS * 8,
- DS * 8, ES * 8, FS * 8, GS * 8
+ DS * 8, ES * 8, FS * 8, GS * 8,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ ORIG_RAX * 8
};
#define X86_64_NUM_GREGS (sizeof(x86_64_regmap)/sizeof(int))
@@ -83,7 +88,8 @@ x86_64_fill_gregset (void *buf)
int i;
for (i = 0; i < X86_64_NUM_GREGS; i++)
- collect_register (i, ((char *) buf) + x86_64_regmap[i]);
+ if (x86_64_regmap[i] != -1)
+ collect_register (i, ((char *) buf) + x86_64_regmap[i]);
}
static void
@@ -92,7 +98,8 @@ x86_64_store_gregset (const void *buf)
int i;
for (i = 0; i < X86_64_NUM_GREGS; i++)
- supply_register (i, ((char *) buf) + x86_64_regmap[i]);
+ if (x86_64_regmap[i] != -1)
+ supply_register (i, ((char *) buf) + x86_64_regmap[i]);
}
static void
Index: regformats/reg-x86-64-linux.dat
===================================================================
RCS file: regformats/reg-x86-64-linux.dat
diff -N regformats/reg-x86-64-linux.dat
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ regformats/reg-x86-64-linux.dat 19 Aug 2006 04:13:57 -0000
@@ -0,0 +1,60 @@
+name:x86_64_linux
+expedite:rbp,rsp,rip
+64:rax
+64:rbx
+64:rcx
+64:rdx
+64:rsi
+64:rdi
+64:rbp
+64:rsp
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:rip
+32:eflags
+32:cs
+32:ss
+32:ds
+32:es
+32:fs
+32:gs
+80:st0
+80:st1
+80:st2
+80:st3
+80:st4
+80:st5
+80:st6
+80:st7
+32:fctrl
+32:fstat
+32:ftag
+32:fiseg
+32:fioff
+32:foseg
+32:fooff
+32:fop
+128:xmm0
+128:xmm1
+128:xmm2
+128:xmm3
+128:xmm4
+128:xmm5
+128:xmm6
+128:xmm7
+128:xmm8
+128:xmm9
+128:xmm10
+128:xmm11
+128:xmm12
+128:xmm13
+128:xmm14
+128:xmm15
+32:mxcsr
+64:orig_rax
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [rfa] Handle amd64-linux %orig_rax
2006-08-19 15:34 Daniel Jacobowitz
@ 2006-08-19 15:46 ` Mark Kettenis
2006-08-19 15:57 ` Daniel Jacobowitz
0 siblings, 1 reply; 13+ messages in thread
From: Mark Kettenis @ 2006-08-19 15:46 UTC (permalink / raw)
To: drow; +Cc: gdb-patches
> Date: Sat, 19 Aug 2006 00:20:40 -0400
> From: Daniel Jacobowitz <drow@false.org>
>
> x86_64-pc-linux-gnu has an %orig_rax "register", exactly parallel to the
> i386-pc-linux-gnu %orig_eax. It's set to a syscall number to trigger
> system call restarting, and has to be set to -1 when we want to prevent
> restarting. It appears to be in every regard the same as the i386
> version; this copies the i386 handling, and fits it into the existing
> amd64 infrastructure.
>
> Tested on x86_64-pc-linux-gnu; this fixes the interrupt.exp timeouts,
> finally. I've known what this was for ages but never had the patience to
> make the mechanical change before, and someone reported this as a bug on the
> Eclipse CDT list recently.
>
> Does this look OK?
Looks good to me. I vaguely remember orig_rax not being available
through ptrace a couple of years ago, but that probably was before the
first official amd64 Linux distributions came out.
Mark
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [rfa] Handle amd64-linux %orig_rax
2006-08-19 15:46 ` Mark Kettenis
@ 2006-08-19 15:57 ` Daniel Jacobowitz
0 siblings, 0 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2006-08-19 15:57 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Sat, Aug 19, 2006 at 09:48:05AM +0200, Mark Kettenis wrote:
> Looks good to me. I vaguely remember orig_rax not being available
> through ptrace a couple of years ago, but that probably was before the
> first official amd64 Linux distributions came out.
Yeah, that's probably true. I checked back as far is the initial
2.5.5-era x86_64 merge (mid-2002), and it looked OK.
Thanks; checked in!
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2006-11-01 15:15 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-10-31 20:10 [rfa] Handle amd64-linux %orig_rax Datoda
2006-10-31 20:17 ` Andi Kleen
-- strict thread matches above, loose matches on Subject: below --
2006-11-01 15:10 Datoda
2006-11-01 15:15 ` Daniel Jacobowitz
2006-10-31 18:17 Datoda
2006-10-31 18:22 ` [rfa] " Daniel Jacobowitz
2006-10-31 18:40 ` Andi Kleen
2006-10-31 18:49 ` Daniel Jacobowitz
2006-10-31 19:11 ` Andi Kleen
2006-10-31 19:30 ` Daniel Jacobowitz
2006-10-31 19:33 ` Daniel Jacobowitz
2006-08-19 15:34 Daniel Jacobowitz
2006-08-19 15:46 ` Mark Kettenis
2006-08-19 15:57 ` Daniel Jacobowitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox