This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[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
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