This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

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
 };
 
 
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]