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.
This commit is contained in:
Hui Zhu 2009-09-21 05:57:09 +00:00
parent 8a2e0e28d0
commit cdfbdf303d
2 changed files with 131 additions and 24 deletions

View File

@ -1,3 +1,16 @@
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.
2009-09-21 Hui Zhu <teawater@gmail.com>
Michael Snyder <msnyder@vmware.com>

View File

@ -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".
/* Record all registers but IP register for process-record. */
Return -1 if something wrong. */
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;
static struct linux_record_tdep amd64_linux_record_tdep;
#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;
case amd64_sys_rt_sigreturn:
if (amd64_all_but_ip_registers_record (regcache))
return -1;
return 0;
break;
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;
case amd64_sys_arch_prctl:
if (syscall_native == amd64_sys_arch_prctl)
{
ULONGEST arg3;
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;
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