diff options
author | Hui Zhu <teawater@gmail.com> | 2009-09-21 05:57:09 +0000 |
---|---|---|
committer | Hui Zhu <teawater@gmail.com> | 2009-09-21 05:57:09 +0000 |
commit | cdfbdf303db54c1ab1ef02a44872976e0f119530 (patch) | |
tree | dee4ff7d4fc65f0ab9b2a0b03ff48039f736bc5f /gdb/amd64-linux-tdep.c | |
parent | 8a2e0e28d090ca4c81c94ff69c930b9471928d61 (diff) | |
download | gdb-cdfbdf303db54c1ab1ef02a44872976e0f119530.zip gdb-cdfbdf303db54c1ab1ef02a44872976e0f119530.tar.gz gdb-cdfbdf303db54c1ab1ef02a44872976e0f119530.tar.bz2 |
2009-09-21 Hui Zhu <teawater@gmail.com>
Michael Snyder <msnyder@vmware.com>
* amd64-linux-tdep.c (amd64_all_but_ip_registers_record): New
function.
(amd64_linux_syscall_record): Call
amd64_all_but_ip_registers_record if syscall is
sys_rt_sigreturn.
(AMD64_LINUX_redzone, AMD64_LINUX_xstate,
AMD64_LINUX_frame_size): New macros.
(amd64_linux_record_signal): New function.
(amd64_linux_init_abi): Call set_gdbarch_process_record_signal.
Diffstat (limited to 'gdb/amd64-linux-tdep.c')
-rw-r--r-- | gdb/amd64-linux-tdep.c | 146 |
1 files changed, 120 insertions, 26 deletions
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index f527b7e..0955331 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -289,16 +289,48 @@ amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) regcache_cooked_write_unsigned (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, -1); } -/* Parse the arguments of current system call instruction and record - the values of the registers and memory that will be changed into - "record_arch_list". This instruction is "syscall". - - Return -1 if something wrong. */ +/* Record all registers but IP register for process-record. */ -static struct linux_record_tdep amd64_linux_record_tdep; +static int +amd64_all_but_ip_registers_record (struct regcache *regcache) +{ + if (record_arch_list_add_reg (regcache, AMD64_RAX_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RCX_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RDX_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RBX_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RSP_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RBP_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RSI_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_RDI_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R8_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R9_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R10_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R12_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R13_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R14_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_R15_REGNUM)) + return -1; + if (record_arch_list_add_reg (regcache, AMD64_EFLAGS_REGNUM)) + return -1; -#define RECORD_ARCH_GET_FS 0x1003 -#define RECORD_ARCH_GET_GS 0x1004 + return 0; +} /* amd64_canonicalize_syscall maps from the native amd64 Linux set of syscall ids into a canonical set of syscall ids used by @@ -1111,6 +1143,17 @@ amd64_canonicalize_syscall (enum amd64_syscall syscall) } } +/* Parse the arguments of current system call instruction and record + the values of the registers and memory that will be changed into + "record_arch_list". This instruction is "syscall". + + Return -1 if something wrong. */ + +static struct linux_record_tdep amd64_linux_record_tdep; + +#define RECORD_ARCH_GET_FS 0x1003 +#define RECORD_ARCH_GET_GS 0x1004 + static int amd64_linux_syscall_record (struct regcache *regcache) { @@ -1120,27 +1163,39 @@ amd64_linux_syscall_record (struct regcache *regcache) regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &syscall_native); - syscall_gdb = amd64_canonicalize_syscall (syscall_native); - - if (syscall_native == amd64_sys_arch_prctl) + switch (syscall_native) { - ULONGEST arg3; - - regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3, - &arg3); - if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS) - { - CORE_ADDR addr; - - regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg2, - &addr); - if (record_arch_list_add_mem (addr, - amd64_linux_record_tdep.size_ulong)) - return -1; - } - goto record_regs; + case amd64_sys_rt_sigreturn: + if (amd64_all_but_ip_registers_record (regcache)) + return -1; + return 0; + break; + + case amd64_sys_arch_prctl: + if (syscall_native == amd64_sys_arch_prctl) + { + ULONGEST arg3; + + regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3, + &arg3); + if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS) + { + CORE_ADDR addr; + + regcache_raw_read_unsigned (regcache, + amd64_linux_record_tdep.arg2, + &addr); + if (record_arch_list_add_mem (addr, + amd64_linux_record_tdep.size_ulong)) + return -1; + } + goto record_regs; + } + break; } + syscall_gdb = amd64_canonicalize_syscall (syscall_native); + if (syscall_gdb < 0) { printf_unfiltered (_("Process record and replay target doesn't " @@ -1163,6 +1218,44 @@ amd64_linux_syscall_record (struct regcache *regcache) if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM)) return -1; + return 0; +} + +#define AMD64_LINUX_redzone 128 +#define AMD64_LINUX_xstate 512 +#define AMD64_LINUX_frame_size 560 + +int +amd64_linux_record_signal (struct gdbarch *gdbarch, + struct regcache *regcache, + enum target_signal signal) +{ + ULONGEST rsp; + + if (amd64_all_but_ip_registers_record (regcache)) + return -1; + + if (record_arch_list_add_reg (regcache, AMD64_RIP_REGNUM)) + return -1; + + /* Record the change in the stack. */ + regcache_raw_read_unsigned (regcache, AMD64_RSP_REGNUM, &rsp); + /* redzone + sp -= 128; */ + rsp -= AMD64_LINUX_redzone; + /* This is for xstate. + sp -= sizeof (struct _fpstate); */ + rsp -= AMD64_LINUX_xstate; + /* This is for frame_size. + sp -= sizeof (struct rt_sigframe); */ + rsp -= AMD64_LINUX_frame_size; + if (record_arch_list_add_mem (rsp, AMD64_LINUX_redzone + + AMD64_LINUX_xstate + + AMD64_LINUX_frame_size)) + return -1; + + if (record_arch_list_add_end ()) + return -1; return 0; } @@ -1218,6 +1311,7 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); set_gdbarch_process_record (gdbarch, i386_process_record); + set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal); /* Initialize the amd64_linux_record_tdep. */ /* These values are the size of the type that will be used in a system |