* x86-64-tdep.h (x86_64_num_regs, x86_64_num_gregs): Remove

variable declarations.
(x86_64_register_number, x86_64_register_name): Remove prototypes.
(x86_64_linux_frame_saved_pc, x86_64_linux+saved_pc_after_call,
x86_64_linux_in_sigtramp, x86_64_linux_frame_chain,
x86_64_init_frame_pc, x86_64_init_frame_pc,
x86_64_function_has_prologue): Remove prototypes.
(X86_64_NUM_GREGS): New define.
(x86_64_supply_fxsave, x86_64_fill_fxsave): New prototypes.
* x86-64-tdep.c: Don't include "dwarf2cfi.h".  Include
"dummy_frame.h", "frame.h", "frame-base.h", "frame-unwind.h".
(RAX_REGNUM, RDX_REGNUM, RDI_REGNUM, EFLAGS_REGNUM, ST0_REGNUM,
XMM1_REGNUM): Remove defines.
(X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM,
X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM,
X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM,
X86_64_XMM1_REGNUM): New defines.
(struct x86_64_register_info): Renamed from `struct
register_info'.  Remove `size' member.
(x86_64_register_info_table): Remove variable.
(x86_64_register_info): New variable.
(X86_64_NUM_REGS): New define.
(X86_64_NUM_GREGS): Remove define.
(x86_64_num_regs, x86_64_num_gregs): Remove variables.
(x86_64_dwarf2gdb_regno_map, x86_64_dwarf2gdb_regno_map_length):
Remove variables.
(x86_54_dwarf2_reg_to_regnum): Remove function.
(x86_64_dwarf_regmap, x86_64_dwarf_regmap_len): New variables.
(x86_64_dwarf_reg_to_regnum): New function.
(x86_64_register_name): Rewrite.
(x86_64_register_raw_size): Remove function.
(x86_64_register_byte_table): Remove variable.
(x86_64_register_byte): Remove function.
(x86_64_register_virtual_type): Remove function.
(x86_64_register_type): New function.
(x86_64_register_convertible, x86_64_register_convert_to_virtual,
x86_64_register_convert_to_raw): Remove functions.
(x86_64_push_return_address, x86_64_pop_frame): Remove functon.
(x86_64_use_struct_convention): Make static.  Adjust for renamed
defines.
(x86_64_frame_init_saved_regs): Remove function.
(x86_64_push_arguments): Make static.  Change to accept a regcache
as argument.
(x86_64_store_return_value, x86_64_extract_return_value): Make
static.  Rewrite based on i386 counterparts.
(x86_64_push_dummy_call): New function.
(X86_64_NUM_SAVED_REGS): New define.
(x86_64_register_number): Remove function.
(x86_64_store_struct_return): Remove function.
(x86_64_frameless_function_invocation,
x86_64_function_has_prologue): Remove functions.
(PROLOG_BUFSIZE): Remove define.
(struct x86_64_frame_cache): New structure.
(x86_64_alloc_frame_cache, x86_64_analyze_prologue,
x86_64_frame_cache, x86_64_frame_this_id,
x86_64_frame_prev_register, x86_64_frame_p,
x86_64_sigtramp_frame_cache, x86_64_sigtramp_frame_this_id,
x86_64_sigtramp_frame_prev_register, x86_sigtramp_frame_p): New
functions.
(x86_64_frame_unwind, x86_64_sigtramp_frame_unwind): New
variables.
(x86_64_skip_prologue): Rewrite in terms of
x86_64_analyze_prologue.
(x86_64_frame_base_address): New function.
(x86_64_frame_base): New variable.
(x86_64_save_dummy_frame_tos, x86_64_unwind_dummy_id): Rewrite.
(x86_64_init_abi): Set register_type and push_dummy_call.  Don't
set deprecated_fp_regnum, deprecated_register_size,
deprecated_register_bytes, register_raw_size, register_byte,
register_virtual_type, register_convertiable,
register_convert_to_virtual, convert_to_raw,
deprecated_get_saved_register, deprecated_target_read_fp,
deprecated_push_arguments, deprecated_push_return_address,
deprecated_pop_frame, deprecated_store_struct_return,
deprecated_frame_init_saved_regs, deprecated_frame_chain,
frameless_function_invocation, deprecated_frame_saved_pc,
deprecated_saved_pc_after_call, frame_num_args, pc_in_sigtramp,
dwarf2_build_frame_info, deprecated_init_extra_frame_info,
deprecated_init_frame_pc and virtual_frame_pointer.  Call
frame_unwind_append_predicate to register x86_64_sigtramp_frame_p
and x86_64_frame_p.  Call frame_base_set_default to register
x86_64_frame_base.
(I387_FISEG_REGNUM, I387_FOSEG_REGNUM): New defines.
(x86_64_supply_fxsave, x86_64_fill_fxsave): New functions.
(_initialize_x86_64_tdep): Remove function.
* x86-64-linux-tdep.c: Don't include "dwarf2cfi.h".
(LINUX_SIGINFO_SIZE, LINUX_UCONTEXT_SIGCONTEXT_OFFSET,
LINUX_SIGCONTEXT_PC_OFFSET, LINUX_SIGCONTEXT_FP_OFFSET): Don't
define.
(X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Define.
(x86_64_linux_sigcontext_addr): Rewrite.
(x86_64_linux_sigtramp_saved_pc, x86_64_linux_saved_pc_after_call,
x86_64_linux_frame_saved_pc): Remove functions.
(x86_64_linux_pc_in_sigtramp): Renamed from
x86_64_linux_in_sigtramp.  Try harder to recognize a signal
trampoline.
(x86_64_linux_frame_chain, x86_64_init_frame_pc):
Remove_functions.
(x86_64_linux_init_abi): Set pc_in_sigtramp.  Initialize
TDEP->sigcontext_addr, TDEP->sc_pc_offset and TDEP->sc_sp_offset.
* x86-64-linux-nat.c: Sync with i386-linux-tdep.c.
(x86_64_regmap): Rename to regmap.
(GETREGS_SUPPLIES): Use X86_64_NUM_GREGS instead of
x86_64_num_gregs.
(supply_gregset, fill_gregset): Likewise.  Use regmap instead of
x86_64_regmap.
(x86_64_fxsave_offset): Remove function.
(supply_fpregset): Simply call x86_64_supply_fxsave.
(fill_fpregset): Simply call x86_64_fill_fxsave.
(fetch_inferior_registers, store_inferior_registers): Avoid
asignment in if-statement.
(LINUX_SYSCALL_LEN, LINUX_SYSCALL_REGNUM, SYS_Sigreturn,
SYS_rt_sigreturn, LINUX_SIGCONTEXT_EFLAGS_OFFSET,
LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Remove defines.
(fetch_core_registers): Remove function.
(linux_elf_core_fns): Remove.
(offsetoff): Don't define.
(_initialize_x86_64_linux_nat, kernel_u_size): Remove functions.
* config/i386/x86-64linux.mt (TDEPFILES): Add i386-linux-tdep.o.
* config/i386/x86-64linux.mh (NATDEPFILES): Remove core-aout.o,
add core-regset.o.
* config/i386/nm-x86-64linux.h: Use NM_X86_64_LINUX_H for
protection against multiple includes instead of NM_X86_64_h.  Add
various comments.  Include "config/nm-linux.h".  Don't include
<signal.h>.
(REGISTER_U_ADDR, KERNEL_U_SIZE, U_REGS_OFFSET, KERN_U_ADDR,
GET_THREAD_SIGNALS): Remove defines.
(x86_64_register_u_addr, kernel_u_size,
lin_thread_get_thread_signals): Remove prototypes.
(PTRACE_ARG3_TYPE, PTRACE_XFER_TYPE): Define to `long'.
[HAVE_LINK_H]: Don't include "solib.h".
[HAVE_LINK_H] (SVR4_SHARED_LIBS): Remove define.
* config/i386/tm-x86-64linux.h: Fix comments.
* Makefile.in (x86-64-linux-nat.o, x86_64-linux-tdep.o,
x86-64-tdep.o): Update dependencies.
This commit is contained in:
Mark Kettenis 2003-05-31 08:15:38 +00:00
parent f2c822e386
commit c4f35dd8e1
10 changed files with 1109 additions and 1008 deletions

View File

@ -1,3 +1,141 @@
2003-05-31 Mark Kettenis <kettenis@gnu.org>
* x86-64-tdep.h (x86_64_num_regs, x86_64_num_gregs): Remove
variable declarations.
(x86_64_register_number, x86_64_register_name): Remove prototypes.
(x86_64_linux_frame_saved_pc, x86_64_linux+saved_pc_after_call,
x86_64_linux_in_sigtramp, x86_64_linux_frame_chain,
x86_64_init_frame_pc, x86_64_init_frame_pc,
x86_64_function_has_prologue): Remove prototypes.
(X86_64_NUM_GREGS): New define.
(x86_64_supply_fxsave, x86_64_fill_fxsave): New prototypes.
* x86-64-tdep.c: Don't include "dwarf2cfi.h". Include
"dummy_frame.h", "frame.h", "frame-base.h", "frame-unwind.h".
(RAX_REGNUM, RDX_REGNUM, RDI_REGNUM, EFLAGS_REGNUM, ST0_REGNUM,
XMM1_REGNUM): Remove defines.
(X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, X86_64_RDI_REGNUM,
X86_64_RBP_REGNUM, X86_64_RSP_REGNUM, X86_64_RIP_REGNUM,
X86_64_EFLAGS_REGNUM, X86_64_ST0_REGNUM, X86_64_XMM0_REGNUM,
X86_64_XMM1_REGNUM): New defines.
(struct x86_64_register_info): Renamed from `struct
register_info'. Remove `size' member.
(x86_64_register_info_table): Remove variable.
(x86_64_register_info): New variable.
(X86_64_NUM_REGS): New define.
(X86_64_NUM_GREGS): Remove define.
(x86_64_num_regs, x86_64_num_gregs): Remove variables.
(x86_64_dwarf2gdb_regno_map, x86_64_dwarf2gdb_regno_map_length):
Remove variables.
(x86_54_dwarf2_reg_to_regnum): Remove function.
(x86_64_dwarf_regmap, x86_64_dwarf_regmap_len): New variables.
(x86_64_dwarf_reg_to_regnum): New function.
(x86_64_register_name): Rewrite.
(x86_64_register_raw_size): Remove function.
(x86_64_register_byte_table): Remove variable.
(x86_64_register_byte): Remove function.
(x86_64_register_virtual_type): Remove function.
(x86_64_register_type): New function.
(x86_64_register_convertible, x86_64_register_convert_to_virtual,
x86_64_register_convert_to_raw): Remove functions.
(x86_64_push_return_address, x86_64_pop_frame): Remove functon.
(x86_64_use_struct_convention): Make static. Adjust for renamed
defines.
(x86_64_frame_init_saved_regs): Remove function.
(x86_64_push_arguments): Make static. Change to accept a regcache
as argument.
(x86_64_store_return_value, x86_64_extract_return_value): Make
static. Rewrite based on i386 counterparts.
(x86_64_push_dummy_call): New function.
(X86_64_NUM_SAVED_REGS): New define.
(x86_64_register_number): Remove function.
(x86_64_store_struct_return): Remove function.
(x86_64_frameless_function_invocation,
x86_64_function_has_prologue): Remove functions.
(PROLOG_BUFSIZE): Remove define.
(struct x86_64_frame_cache): New structure.
(x86_64_alloc_frame_cache, x86_64_analyze_prologue,
x86_64_frame_cache, x86_64_frame_this_id,
x86_64_frame_prev_register, x86_64_frame_p,
x86_64_sigtramp_frame_cache, x86_64_sigtramp_frame_this_id,
x86_64_sigtramp_frame_prev_register, x86_sigtramp_frame_p): New
functions.
(x86_64_frame_unwind, x86_64_sigtramp_frame_unwind): New
variables.
(x86_64_skip_prologue): Rewrite in terms of
x86_64_analyze_prologue.
(x86_64_frame_base_address): New function.
(x86_64_frame_base): New variable.
(x86_64_save_dummy_frame_tos, x86_64_unwind_dummy_id): Rewrite.
(x86_64_init_abi): Set register_type and push_dummy_call. Don't
set deprecated_fp_regnum, deprecated_register_size,
deprecated_register_bytes, register_raw_size, register_byte,
register_virtual_type, register_convertiable,
register_convert_to_virtual, convert_to_raw,
deprecated_get_saved_register, deprecated_target_read_fp,
deprecated_push_arguments, deprecated_push_return_address,
deprecated_pop_frame, deprecated_store_struct_return,
deprecated_frame_init_saved_regs, deprecated_frame_chain,
frameless_function_invocation, deprecated_frame_saved_pc,
deprecated_saved_pc_after_call, frame_num_args, pc_in_sigtramp,
dwarf2_build_frame_info, deprecated_init_extra_frame_info,
deprecated_init_frame_pc and virtual_frame_pointer. Call
frame_unwind_append_predicate to register x86_64_sigtramp_frame_p
and x86_64_frame_p. Call frame_base_set_default to register
x86_64_frame_base.
(I387_FISEG_REGNUM, I387_FOSEG_REGNUM): New defines.
(x86_64_supply_fxsave, x86_64_fill_fxsave): New functions.
(_initialize_x86_64_tdep): Remove function.
* x86-64-linux-tdep.c: Don't include "dwarf2cfi.h".
(LINUX_SIGINFO_SIZE, LINUX_UCONTEXT_SIGCONTEXT_OFFSET,
LINUX_SIGCONTEXT_PC_OFFSET, LINUX_SIGCONTEXT_FP_OFFSET): Don't
define.
(X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Define.
(x86_64_linux_sigcontext_addr): Rewrite.
(x86_64_linux_sigtramp_saved_pc, x86_64_linux_saved_pc_after_call,
x86_64_linux_frame_saved_pc): Remove functions.
(x86_64_linux_pc_in_sigtramp): Renamed from
x86_64_linux_in_sigtramp. Try harder to recognize a signal
trampoline.
(x86_64_linux_frame_chain, x86_64_init_frame_pc):
Remove_functions.
(x86_64_linux_init_abi): Set pc_in_sigtramp. Initialize
TDEP->sigcontext_addr, TDEP->sc_pc_offset and TDEP->sc_sp_offset.
* x86-64-linux-nat.c: Sync with i386-linux-tdep.c.
(x86_64_regmap): Rename to regmap.
(GETREGS_SUPPLIES): Use X86_64_NUM_GREGS instead of
x86_64_num_gregs.
(supply_gregset, fill_gregset): Likewise. Use regmap instead of
x86_64_regmap.
(x86_64_fxsave_offset): Remove function.
(supply_fpregset): Simply call x86_64_supply_fxsave.
(fill_fpregset): Simply call x86_64_fill_fxsave.
(fetch_inferior_registers, store_inferior_registers): Avoid
asignment in if-statement.
(LINUX_SYSCALL_LEN, LINUX_SYSCALL_REGNUM, SYS_Sigreturn,
SYS_rt_sigreturn, LINUX_SIGCONTEXT_EFLAGS_OFFSET,
LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Remove defines.
(fetch_core_registers): Remove function.
(linux_elf_core_fns): Remove.
(offsetoff): Don't define.
(_initialize_x86_64_linux_nat, kernel_u_size): Remove functions.
* config/i386/x86-64linux.mt (TDEPFILES): Add i386-linux-tdep.o.
* config/i386/x86-64linux.mh (NATDEPFILES): Remove core-aout.o,
add core-regset.o.
* config/i386/nm-x86-64linux.h: Use NM_X86_64_LINUX_H for
protection against multiple includes instead of NM_X86_64_h. Add
various comments. Include "config/nm-linux.h". Don't include
<signal.h>.
(REGISTER_U_ADDR, KERNEL_U_SIZE, U_REGS_OFFSET, KERN_U_ADDR,
GET_THREAD_SIGNALS): Remove defines.
(x86_64_register_u_addr, kernel_u_size,
lin_thread_get_thread_signals): Remove prototypes.
(PTRACE_ARG3_TYPE, PTRACE_XFER_TYPE): Define to `long'.
[HAVE_LINK_H]: Don't include "solib.h".
[HAVE_LINK_H] (SVR4_SHARED_LIBS): Remove define.
* config/i386/tm-x86-64linux.h: Fix comments.
* Makefile.in (x86-64-linux-nat.o, x86_64-linux-tdep.o,
x86-64-tdep.o): Update dependencies.
2003-05-30 Andrew Cagney <cagney@redhat.com>
* config/sparc/tm-sparc.h (sparc_extract_struct_value_address):

View File

@ -2350,13 +2350,15 @@ wince.o: wince.c $(defs_h) $(frame_h) $(inferior_h) $(target_h) $(gdbcore_h) \
$(regcache_h)
wrapper.o: wrapper.c $(defs_h) $(value_h) $(wrapper_h)
x86-64-linux-nat.o: x86-64-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(regcache_h) $(gdb_assert_h) $(x86_64_tdep_h)
$(regcache_h) $(gdb_assert_h) $(gdb_string_h) $(gregset_h) \
$(x86_64_tdep_h)
x86-64-linux-tdep.o: x86-64-linux-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(gdb_string_h) $(regcache_h) $(x86_64_tdep_h) $(dwarf2cfi_h) \
$(osabi_h)
x86-64-tdep.o: x86-64-tdep.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(gdbcmd_h) $(arch_utils_h) $(regcache_h) $(symfile_h) $(objfiles_h) \
$(x86_64_tdep_h) $(dwarf2cfi_h) $(gdb_assert_h) $(block_h)
$(regcache_h) $(osabi_h) $(gdb_string_h) $(x86_64_tdep_h)
x86-64-tdep.o: x86-64-tdep.c $(defs_h) \
$(inferior_h) $(gdbcore_h) $(arch_utils_h) $(block_h) \
$(dummy_frame_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
$(inferior_h) $(gdbcmd_h) $(gdbcode_h) $(objfiles_h) $(regcache_h) \
$(symfile_h) $(gdb_assert_h) $(x86_64_tdep_h) $(i387_tdep_h)
xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
$(coff_internal_h) $(libcoff_h) $(coff_xcoff_h) $(libxcoff_h) \
$(coff_rs6000_h) $(symtab_h) $(gdbtypes_h) $(symfile_h) \

View File

@ -1,7 +1,8 @@
/* Native support for GNU/Linux x86-64.
Copyright 2001, 2002 Free Software Foundation, Inc. Contributed by
Jiri Smid, SuSE Labs.
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@ -20,15 +21,16 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef NM_X86_64_H
#define NM_X86_64_H
#ifndef NM_X86_64_LINUX_H
#define NM_X86_64_LINUX_H
/* GNU/Linux supports the i386 hardware debugging registers. */
#define I386_USE_GENERIC_WATCHPOINTS
#include "i386/nm-i386.h"
#include "config/nm-linux.h"
#define I386_USE_GENERIC_WATCHPOINTS
#include "i386/nm-i386.h"
/* Support for 8-byte wide hw watchpoints. */
/* Support for 8-byte wide hardware watchpoints. */
#define TARGET_HAS_DR_LEN_8 1
/* Provide access to the i386 hardware debugging registers. */
@ -50,41 +52,17 @@ extern unsigned long x86_64_linux_dr_get_status (void);
x86_64_linux_dr_get_status ()
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = x86_64_register_u_addr ((blockend),(regno));
CORE_ADDR x86_64_register_u_addr (CORE_ADDR, int);
/* Type of the third argument to the `ptrace' system call. */
#define PTRACE_ARG3_TYPE long
/* Return the size of the user struct. */
#define KERNEL_U_SIZE kernel_u_size()
extern int kernel_u_size (void);
/* Offset of the registers within the user area. */
#define U_REGS_OFFSET 0
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR 0x0
#define PTRACE_ARG3_TYPE void*
#define PTRACE_XFER_TYPE unsigned long
/* We define this if link.h is available, because with ELF we use SVR4 style
shared libraries. */
#ifdef HAVE_LINK_H
#define SVR4_SHARED_LIBS
#include "solib.h" /* Support for shared libraries. */
#endif
/* Type of the fourth argument to the `ptrace' system call. */
#define PTRACE_XFER_TYPE long
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
#define FETCH_INFERIOR_REGISTERS
/* FIXME: kettenis/20030416: Why? */
#undef PREPARE_TO_PROCEED
#include <signal.h>
extern void lin_thread_get_thread_signals (sigset_t * mask);
#define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask)
#endif /* NM_X86_64.h */
#endif /* NM_X86_64_LINUX_H */

View File

@ -1,6 +1,6 @@
/* Definitions to target GDB to GNU/Linux on x86-64.
Copyright 2002 Free Software Foundation, Inc.
Copyright 2002, 2003 Free Software Foundation, Inc.
Contributed by Michal Ludvig, SuSE Labs.
@ -25,10 +25,10 @@
#define TM_X86_64LINUX_H
/* We define SVR4_SHARED_LIBS unconditionally, on the assumption that
* link.h is available on all linux platforms. For I386 and SH3/4,
* we hard-code the information rather than use link.h anyway (for
* the benefit of cross-debugging). We may move to doing that for
* other architectures as well. */
link.h is available on all linux platforms. For I386 and SH3/4, we
hard-code the information rather than use link.h anyway (for the
benefit of cross-debugging). We may move to doing that for other
architectures as well. */
#define SVR4_SHARED_LIBS
#include "solib.h" /* Support for shared libraries. */

View File

@ -4,8 +4,9 @@ XM_FILE= xm-i386.h
NAT_FILE= nm-x86-64linux.h
NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
core-aout.o i386-nat.o x86-64-linux-nat.o \
proc-service.o thread-db.o lin-lwp.o \
linux-proc.o gcore.o
core-regset.o i386-nat.o x86-64-linux-nat.o \
proc-service.o thread-db.o lin-lwp.o linux-proc.o gcore.o
# The dynamically loaded libthread_db needs access to symbols in the
# gdb executable.
LOADLIBES = -ldl -rdynamic

View File

@ -1,6 +1,6 @@
# Target: AMD x86-64 running GNU/Linux
TDEPFILES= x86-64-tdep.o x86-64-linux-tdep.o dwarf2cfi.o \
i386-tdep.o i387-tdep.o \
TDEPFILES= x86-64-tdep.o x86-64-linux-tdep.o \
i386-tdep.o i387-tdep.o i386-linux-tdep.o \
solib.o solib-svr4.o solib-legacy.o
GDB_MULTI_ARCH=GDB_MULTI_ARCH_TM

View File

@ -25,20 +25,30 @@
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "x86-64-tdep.h"
#include <sys/ptrace.h>
#include <sys/debugreg.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <sys/reg.h>
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
#include "x86-64-tdep.h"
/* The register sets used in GNU/Linux ELF core-dumps are identical to
the register sets used by `ptrace'. The corresponding types are
`elf_gregset_t' for the general-purpose registers (with
`elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
for the floating-point registers.
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register array layout. */
static int x86_64_regmap[] = {
static int regmap[] =
{
RAX, RBX, RCX, RDX,
RSI, RDI, RBP, RSP,
R8, R9, R10, R11,
@ -47,6 +57,209 @@ static int x86_64_regmap[] = {
DS, ES, FS, GS
};
/* Which ptrace request retrieves which registers?
These apply to the corresponding SET requests as well. */
#define GETREGS_SUPPLIES(regno) \
(0 <= (regno) && (regno) < X86_64_NUM_GREGS)
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
/* Transfering the general-purpose registers between GDB, inferiors
and core files. */
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
void
supply_gregset (elf_gregset_t *gregsetp)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
for (i = 0; i < X86_64_NUM_GREGS; i++)
supply_register (i, regp + regmap[i]);
}
/* Fill register REGNO (if it is a general-purpose register) in
*GREGSETPS with the value in GDB's register array. If REGNO is -1,
do this for all registers. */
void
fill_gregset (elf_gregset_t *gregsetp, int regno)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
for (i = 0; i < X86_64_NUM_GREGS; i++)
if (regno == -1 || regno == i)
regcache_collect (i, regp + regmap[i]);
}
/* Fetch all general-purpose registers from process/thread TID and
store their values in GDB's register array. */
static void
fetch_regs (int tid)
{
elf_gregset_t regs;
if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't get registers");
supply_gregset (&regs);
}
/* Store all valid general-purpose registers in GDB's register array
into the process/thread specified by TID. */
static void
store_regs (int tid, int regno)
{
elf_gregset_t regs;
if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't get registers");
fill_gregset (&regs, regno);
if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't write registers");
}
/* Transfering floating-point registers between GDB, inferiors and cores. */
/* Fill GDB's register array with the floating-point and SSE register
values in *FPREGSETP. */
void
supply_fpregset (elf_fpregset_t *fpregsetp)
{
x86_64_supply_fxsave ((char *) fpregsetp);
}
/* Fill register REGNUM (if it is a floating-point or SSE register) in
*FPREGSETP with the value in GDB's register array. If REGNUM is
-1, do this for all registers. */
void
fill_fpregset (elf_fpregset_t *fpregsetp, int regnum)
{
x86_64_fill_fxsave ((char *) fpregsetp, regnum);
}
/* Fetch all floating-point registers from process/thread TID and store
thier values in GDB's register array. */
static void
fetch_fpregs (int tid)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't get floating point status");
supply_fpregset (&fpregs);
}
/* Store all valid floating-point registers in GDB's register array
into the process/thread specified by TID. */
static void
store_fpregs (int tid, int regno)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't get floating point status");
fill_fpregset (&fpregs, regno);
if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't write floating point status");
}
/* Transferring arbitrary registers between GDB and inferior. */
/* Fetch register REGNO from the child process. If REGNO is -1, do
this for all registers (including the floating point and SSE
registers). */
void
fetch_inferior_registers (int regno)
{
int tid;
/* GNU/Linux LWP ID's are process ID's. */
tid = TIDGET (inferior_ptid);
if (tid == 0)
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
fetch_regs (tid);
fetch_fpregs (tid);
return;
}
if (GETREGS_SUPPLIES (regno))
{
fetch_regs (tid);
return;
}
if (GETFPREGS_SUPPLIES (regno))
{
fetch_fpregs (tid);
return;
}
internal_error (__FILE__, __LINE__,
"Got request for bad register number %d.", regno);
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating-point and SSE
registers). */
void
store_inferior_registers (int regno)
{
int tid;
/* GNU/Linux LWP ID's are process ID's. */
tid = TIDGET (inferior_ptid);
if (tid == 0)
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
store_regs (tid, regno);
store_fpregs (tid, regno);
return;
}
if (GETREGS_SUPPLIES (regno))
{
store_regs (tid, regno);
return;
}
if (GETFPREGS_SUPPLIES (regno))
{
store_fpregs (tid, regno);
return;
}
internal_error (__FILE__, __LINE__,
"Got request to store bad register number %d.", regno);
}
static unsigned long
x86_64_linux_dr_get (int regnum)
{
@ -119,374 +332,3 @@ x86_64_linux_dr_get_status (void)
{
return x86_64_linux_dr_get (DR_STATUS);
}
/* The register sets used in GNU/Linux ELF core-dumps are identical to
the register sets used by `ptrace'. */
#define GETREGS_SUPPLIES(regno) \
(0 <= (regno) && (regno) < x86_64_num_gregs)
#define GETFPREGS_SUPPLIES(regno) \
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
/* Transfering the general-purpose registers between GDB, inferiors
and core files. */
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
void
supply_gregset (elf_gregset_t * gregsetp)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
for (i = 0; i < x86_64_num_gregs; i++)
supply_register (i, (char *) (regp + x86_64_regmap[i]));
}
/* Fill register REGNO (if it is a general-purpose register) in
*GREGSETPS with the value in GDB's register array. If REGNO is -1,
do this for all registers. */
void
fill_gregset (elf_gregset_t * gregsetp, int regno)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
for (i = 0; i < x86_64_num_gregs; i++)
if ((regno == -1 || regno == i))
regcache_collect (i, (char *) (regp + x86_64_regmap[i]));
}
/* Fetch all general-purpose registers from process/thread TID and
store their values in GDB's register array. */
static void
fetch_regs (int tid)
{
elf_gregset_t regs;
if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't get registers");
supply_gregset (&regs);
}
/* Store all valid general-purpose registers in GDB's register array
into the process/thread specified by TID. */
static void
store_regs (int tid, int regno)
{
elf_gregset_t regs;
if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't get registers");
fill_gregset (&regs, regno);
if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
perror_with_name ("Couldn't write registers");
}
/* Transfering floating-point registers between GDB, inferiors and cores. */
static void *
x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum)
{
const char *reg_name;
int reg_index;
gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs);
reg_name = x86_64_register_name (regnum);
if (reg_name[0] == 's' && reg_name[1] == 't')
{
reg_index = reg_name[2] - '0';
return &fxsave->st_space[reg_index * 2];
}
if (reg_name[0] == 'x' && reg_name[1] == 'm' && reg_name[2] == 'm')
{
reg_index = reg_name[3] - '0';
return &fxsave->xmm_space[reg_index * 4];
}
if (strcmp (reg_name, "mxcsr") == 0)
return &fxsave->mxcsr;
return NULL;
}
/* Fill GDB's register array with the floating-point and SSE register
values in *FXSAVE. This function masks off any of the reserved
bits in *FXSAVE. */
void
supply_fpregset (elf_fpregset_t * fxsave)
{
int i, reg_st0, reg_mxcsr;
reg_st0 = x86_64_register_number ("st0");
reg_mxcsr = x86_64_register_number ("mxcsr");
gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0);
for (i = reg_st0; i <= reg_mxcsr; i++)
supply_register (i, x86_64_fxsave_offset (fxsave, i));
}
/* Fill register REGNUM (if it is a floating-point or SSE register) in
*FXSAVE with the value in GDB's register array. If REGNUM is -1, do
this for all registers. This function doesn't touch any of the
reserved bits in *FXSAVE. */
void
fill_fpregset (elf_fpregset_t * fxsave, int regnum)
{
int i, last_regnum = MXCSR_REGNUM;
void *ptr;
if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
last_regnum = FOP_REGNUM;
for (i = FP0_REGNUM; i <= last_regnum; i++)
if (regnum == -1 || regnum == i)
{
ptr = x86_64_fxsave_offset (fxsave, i);
if (ptr)
regcache_collect (i, ptr);
}
}
/* Fetch all floating-point registers from process/thread TID and store
thier values in GDB's register array. */
static void
fetch_fpregs (int tid)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't get floating point status");
supply_fpregset (&fpregs);
}
/* Store all valid floating-point registers in GDB's register array
into the process/thread specified by TID. */
static void
store_fpregs (int tid, int regno)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't get floating point status");
fill_fpregset (&fpregs, regno);
if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
perror_with_name ("Couldn't write floating point status");
}
/* Transferring arbitrary registers between GDB and inferior. */
/* Fetch register REGNO from the child process. If REGNO is -1, do
this for all registers (including the floating point and SSE
registers). */
void
fetch_inferior_registers (int regno)
{
int tid;
/* GNU/Linux LWP ID's are process ID's. */
if ((tid = TIDGET (inferior_ptid)) == 0)
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
fetch_regs (tid);
fetch_fpregs (tid);
return;
}
if (GETREGS_SUPPLIES (regno))
{
fetch_regs (tid);
return;
}
if (GETFPREGS_SUPPLIES (regno))
{
fetch_fpregs (tid);
return;
}
internal_error (__FILE__, __LINE__,
"Got request for bad register number %d.", regno);
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
void
store_inferior_registers (int regno)
{
int tid;
/* GNU/Linux LWP ID's are process ID's. */
if ((tid = TIDGET (inferior_ptid)) == 0)
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
if (regno == -1)
{
store_regs (tid, regno);
store_fpregs (tid, regno);
return;
}
if (GETREGS_SUPPLIES (regno))
{
store_regs (tid, regno);
return;
}
if (GETFPREGS_SUPPLIES (regno))
{
store_fpregs (tid, regno);
return;
}
internal_error (__FILE__, __LINE__,
"Got request to store bad register number %d.", regno);
}
static const unsigned char linux_syscall[] = { 0x0f, 0x05 };
#define LINUX_SYSCALL_LEN (sizeof linux_syscall)
/* The system call number is stored in the %rax register. */
#define LINUX_SYSCALL_REGNUM 0 /* %rax */
/* We are specifically interested in the sigreturn and rt_sigreturn
system calls. */
#ifndef SYS_sigreturn
#define SYS_sigreturn __NR_sigreturn
#endif
#ifndef SYS_rt_sigreturn
#define SYS_rt_sigreturn __NR_rt_sigreturn
#endif
/* Offset to saved processor flags, from <asm/sigcontext.h>. */
#define LINUX_SIGCONTEXT_EFLAGS_OFFSET (152)
/* Offset to saved processor registers from <asm/ucontext.h> */
#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36)
/* Interpreting register set info found in core files. */
/* Provide registers to GDB from a core file.
CORE_REG_SECT points to an array of bytes, which are the contents
of a `note' from a core file which BFD thinks might contain
register contents. CORE_REG_SIZE is its size.
WHICH says which register set corelow suspects this is:
0 --- the general-purpose register set, in elf_gregset_t format
2 --- the floating-point register set, in elf_fpregset_t format
REG_ADDR isn't used on GNU/Linux. */
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
elf_gregset_t gregset;
elf_fpregset_t fpregset;
switch (which)
{
case 0:
if (core_reg_size != sizeof (gregset))
warning ("Wrong size gregset in core file.");
else
{
memcpy (&gregset, core_reg_sect, sizeof (gregset));
supply_gregset (&gregset);
}
break;
case 2:
if (core_reg_size != sizeof (fpregset))
warning ("Wrong size fpregset in core file.");
else
{
memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
supply_fpregset (&fpregset);
}
break;
default:
/* We've covered all the kinds of registers we know about here,
so this must be something we wouldn't know what to do with
anyway. Just ignore it. */
break;
}
}
/* Register that we are able to handle GNU/Linux ELF core file formats. */
static struct core_fns linux_elf_core_fns = {
bfd_target_elf_flavour, /* core_flavour */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
#if !defined (offsetof)
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#endif
/* Return the address of register REGNUM. BLOCKEND is the value of
u.u_ar0, which should point to the registers. */
CORE_ADDR
x86_64_register_u_addr (CORE_ADDR blockend, int regnum)
{
struct user u;
CORE_ADDR fpstate;
CORE_ADDR ubase;
ubase = blockend;
if (IS_FP_REGNUM (regnum))
{
fpstate = ubase + ((char *) &u.i387.st_space - (char *) &u);
return (fpstate + 16 * (regnum - FP0_REGNUM));
}
else if (IS_SSE_REGNUM (regnum))
{
fpstate = ubase + ((char *) &u.i387.xmm_space - (char *) &u);
return (fpstate + 16 * (regnum - XMM0_REGNUM));
}
else
return (ubase + 8 * x86_64_regmap[regnum]);
}
void
_initialize_x86_64_linux_nat (void)
{
add_core_fns (&linux_elf_core_fns);
}
int
kernel_u_size (void)
{
return (sizeof (struct user));
}

View File

@ -24,19 +24,21 @@
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "gdb_string.h"
#include "regcache.h"
#include "x86-64-tdep.h"
#include "dwarf2cfi.h"
#include "osabi.h"
#define LINUX_SIGTRAMP_INSN0 (0x48) /* mov $NNNNNNNN,%rax */
#define LINUX_SIGTRAMP_OFFSET0 (0)
#define LINUX_SIGTRAMP_INSN1 (0x0f) /* syscall */
#define LINUX_SIGTRAMP_OFFSET1 (7)
#include "gdb_string.h"
static const unsigned char linux_sigtramp_code[] = {
/* mov $__NR_rt_sigreturn,%rax */
#include "x86-64-tdep.h"
#define LINUX_SIGTRAMP_INSN0 0x48 /* mov $NNNNNNNN, %rax */
#define LINUX_SIGTRAMP_OFFSET0 0
#define LINUX_SIGTRAMP_INSN1 0x0f /* syscall */
#define LINUX_SIGTRAMP_OFFSET1 7
static const unsigned char linux_sigtramp_code[] =
{
/* mov $__NR_rt_sigreturn, %rax */
LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
/* syscall */
LINUX_SIGTRAMP_INSN1, 0x05
@ -51,6 +53,14 @@ static CORE_ADDR
x86_64_linux_sigtramp_start (CORE_ADDR pc)
{
unsigned char buf[LINUX_SIGTRAMP_LEN];
/* We only recognize a signal trampoline if PC is at the start of
one of the two instructions. We optimize for finding the PC at
the start, as will be the case when the trampoline is not the
first frame on the stack. We assume that in the case where the
PC is not at the start of the instruction sequence, there will be
a few trailing readable bytes on the stack. */
if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
return 0;
@ -71,133 +81,61 @@ x86_64_linux_sigtramp_start (CORE_ADDR pc)
return pc;
}
#define LINUX_SIGINFO_SIZE 0
/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
#define LINUX_SIGCONTEXT_PC_OFFSET 128
#define LINUX_SIGCONTEXT_FP_OFFSET 120
/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
address of the associated sigcontext structure. */
static CORE_ADDR
x86_64_linux_sigcontext_addr (struct frame_info *frame)
{
CORE_ADDR pc;
ULONGEST rsp;
pc = x86_64_linux_sigtramp_start (get_frame_pc (frame));
if (pc)
{
if (get_next_frame (frame))
/* If this isn't the top frame, the next frame must be for the
signal handler itself. The sigcontext structure is part of
the user context. */
return get_frame_base (get_next_frame (frame)) + LINUX_SIGINFO_SIZE +
LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
/* This is the top frame. */
rsp = read_register (SP_REGNUM);
return rsp + LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
}
error ("Couldn't recognize signal trampoline.");
return 0;
}
/* Assuming FRAME is for a GNU/Linux sigtramp routine, return the
saved program counter. */
static CORE_ADDR
x86_64_linux_sigtramp_saved_pc (struct frame_info *frame)
{
CORE_ADDR addr;
addr = x86_64_linux_sigcontext_addr (frame);
return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
}
/* Immediately after a function call, return the saved pc. */
CORE_ADDR
x86_64_linux_saved_pc_after_call (struct frame_info *frame)
{
if ((get_frame_type (frame) == SIGTRAMP_FRAME))
return x86_64_linux_sigtramp_saved_pc (frame);
return read_memory_integer (read_register (SP_REGNUM), 8);
}
/* Saved Pc. Get it from sigcontext if within sigtramp. */
CORE_ADDR
x86_64_linux_frame_saved_pc (struct frame_info *frame)
{
if ((get_frame_type (frame) == SIGTRAMP_FRAME))
return x86_64_linux_sigtramp_saved_pc (frame);
return cfi_get_ra (frame);
}
/* Return whether PC is in a GNU/Linux sigtramp routine. */
int
x86_64_linux_in_sigtramp (CORE_ADDR pc, char *name)
static int
x86_64_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
if (name)
return strcmp ("__restore_rt", name) == 0;
/* If we have NAME, we can optimize the search. The trampoline is
named __restore_rt. However, it isn't dynamically exported from
the shared C library, so the trampoline may appear to be part of
the preceding function. This should always be sigaction,
__sigaction, or __libc_sigaction (all aliases to the same
function). */
if (name == NULL || strstr (name, "sigaction") != NULL)
return (x86_64_linux_sigtramp_start (pc) != 0);
return (x86_64_linux_sigtramp_start (pc) != 0);
return (strcmp ("__restore_rt", name) == 0);
}
CORE_ADDR
x86_64_linux_frame_chain (struct frame_info *fi)
/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
#define X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40
/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
routine, return the address of the associated sigcontext structure. */
static CORE_ADDR
x86_64_linux_sigcontext_addr (struct frame_info *next_frame)
{
ULONGEST addr;
CORE_ADDR fp, pc;
CORE_ADDR sp;
char buf[8];
if (!(get_frame_type (fi) == SIGTRAMP_FRAME))
{
fp = cfi_frame_chain (fi);
if (fp)
return fp;
else
addr = get_frame_base (fi);
}
else
addr = get_frame_base (get_next_frame (fi));
frame_unwind_register (next_frame, SP_REGNUM, buf);
sp = extract_unsigned_integer (buf, 8);
addr += LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
fp = read_memory_integer (addr + LINUX_SIGCONTEXT_FP_OFFSET, 8) + 8;
return fp;
}
CORE_ADDR
x86_64_init_frame_pc (int fromleaf, struct frame_info *fi)
{
CORE_ADDR addr;
if (get_next_frame (fi)
&& (get_frame_type (get_next_frame (fi)) == SIGTRAMP_FRAME))
{
addr = get_frame_base (get_next_frame (get_next_frame (fi)))
+ LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 8);
}
else
return cfi_init_frame_pc (fromleaf, fi);
/* The sigcontext structure is part of the user context. A pointer
to the user context is passed as the third argument to the signal
handler, i.e. in %rdx. Unfortunately %rdx isn't preserved across
function calls so we can't use it. Fortunately the user context
is part of the signal frame and the unwound %rsp directly points
at it. */
return sp + X86_64_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
}
static void
x86_64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
x86_64_init_abi (info, gdbarch);
set_gdbarch_pc_in_sigtramp (gdbarch, x86_64_linux_pc_in_sigtramp);
tdep->sigcontext_addr = x86_64_linux_sigcontext_addr;
tdep->sc_pc_offset = 16 * 8; /* From <asm/sigcontext.h>. */
tdep->sc_sp_offset = 15 * 8;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
extern void _initialize_x86_64_linux_tdep (void);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
/* Target-dependent code for GDB, the GNU debugger.
Copyright 2001
/* Target-dependent code for the x86-64.
Copyright 2001, 2003
Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
This file is part of GDB.
@ -28,19 +30,22 @@ struct frame_info;
#include "i386-tdep.h"
extern int x86_64_num_regs;
extern int x86_64_num_gregs;
int x86_64_register_number (const char *name);
const char *x86_64_register_name (int reg_nr);
gdbarch_deprecated_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
gdbarch_deprecated_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;
gdbarch_pc_in_sigtramp_ftype x86_64_linux_in_sigtramp;
CORE_ADDR x86_64_linux_frame_chain (struct frame_info *fi);
CORE_ADDR x86_64_init_frame_pc (int fromleaf, struct frame_info *fi);
int x86_64_function_has_prologue (CORE_ADDR pc);
/* Number of general purpose registers. */
#define X86_64_NUM_GREGS 22
void x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
#endif
/* Fill GDB's register array with the floating-point and SSE register
values in *FXSAVE. This function masks off any of the reserved
bits in *FXSAVE. */
void x86_64_supply_fxsave (char *fxsave);
/* Fill register REGNUM (if it is a floating-point or SSE register) in
*FXSAVE with the value in GDB's register array. If REGNUM is -1, do
this for all registers. This function doesn't touch any of the
reserved bits in *FXSAVE. */
void x86_64_fill_fxsave (char *fxsave, int regnum);
#endif /* x86-64-tdep.h */