From 037f56f95dc25af92e88784874d2e2e7b42e00fd Mon Sep 17 00:00:00 2001 From: drow Date: Sat, 19 Aug 2006 15:15:17 +0000 Subject: [PATCH] gdb/ * 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. gdb/testsuite/ * 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. --- gdb/ChangeLog | 19 +++++++++++ gdb/Makefile.in | 5 +-- gdb/amd64-linux-nat.c | 9 ++++- gdb/amd64-linux-tdep.c | 67 ++++++++++++++++++++++++++++++++++++- gdb/amd64-linux-tdep.h | 36 ++++++++++++++++++++ gdb/amd64-tdep.c | 4 +-- gdb/amd64-tdep.h | 6 ++++ gdb/gdbserver/ChangeLog | 9 +++++ gdb/gdbserver/Makefile.in | 5 ++- gdb/gdbserver/configure.srv | 2 +- gdb/gdbserver/linux-x86-64-low.c | 13 +++++-- gdb/regformats/reg-x86-64-linux.dat | 60 +++++++++++++++++++++++++++++++++ 12 files changed, 224 insertions(+), 11 deletions(-) create mode 100644 gdb/amd64-linux-tdep.h create mode 100644 gdb/regformats/reg-x86-64-linux.dat diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 908e7e4844..b3f306c0f7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2006-08-19 Daniel Jacobowitz + + * 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-18 Daniel Jacobowitz * infrun.c (handle_inferior_event): Check the current frame ID diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 797492046c..c51ac73161 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -638,6 +638,7 @@ ada_lang_h = ada-lang.h $(value_h) $(gdbtypes_h) $(breakpoint_h) 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 $(defs_h) $(arch_utils_h) $(frame_h) \ 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) \ diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index b4a71125a3..fca05c8a5a 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -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_offset[] = 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); diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 9fa01739bc..316b1f3faf 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -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_info info, struct gdbarch *gdbarch) 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); diff --git a/gdb/amd64-linux-tdep.h b/gdb/amd64-linux-tdep.h new file mode 100644 index 0000000000..4a5778d0ca --- /dev/null +++ b/gdb/amd64-linux-tdep.h @@ -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 */ diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 647edcd97b..b39c839e2a 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -129,7 +129,7 @@ static struct amd64_register_info const amd64_register_info[] = /* 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); diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index f2670af2f6..0fc0f5b11e 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -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 diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index a5a735a121..25b7ed5561 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,12 @@ +2006-08-19 Daniel Jacobowitz + + * 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. + 2006-08-08 Richard Sandiford * server.c (terminal_fd): New variable. diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 01642c802a..f443a28802 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -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-sh.dat $(regdat_sh) 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". diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 46383db58e..40805e5e53 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -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 diff --git a/gdb/gdbserver/linux-x86-64-low.c b/gdb/gdbserver/linux-x86-64-low.c index 43cd10b0b3..e067b9c5ed 100644 --- a/gdb/gdbserver/linux-x86-64-low.c +++ b/gdb/gdbserver/linux-x86-64-low.c @@ -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 diff --git a/gdb/regformats/reg-x86-64-linux.dat b/gdb/regformats/reg-x86-64-linux.dat new file mode 100644 index 0000000000..47d324a986 --- /dev/null +++ b/gdb/regformats/reg-x86-64-linux.dat @@ -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 -- 2.11.0