This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GDB record patch 0.1.3.1 for GDB-6.8 release


Hi Michael and Thiago,

most part of GDB record patch 0.1.3.1 is same with GDB record patch
0.1.3 (http://sourceware.org/ml/gdb-patches/2008-04/msg00300.html). I
just did some change according to your mail. I must express the
particularly grateful to you.

Thanks,
teawater
Patch to make make I386-Linux GDB support Reversible Debugging (http://sourceforge.net/projects/record/)
---
 Makefile.in       |    6 
 gdbarch.c         |   46 
 gdbarch.h         |   13 
 i386-linux-tdep.c | 2533 +++++++++++++++++++++++++++++++++++++++++++++++++
 i386-tdep.c       | 2769 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 i386-tdep.h       |    3 
 infcmd.c          |   47 
 inferior.h        |    6 
 infrun.c          |  130 ++
 mips-tdep.c       |  734 ++++++++++++++
 record.c          |  606 +++++++++++
 record.h          |   81 +
 target.c          |   15 
 target.h          |    3 
 14 files changed, 6859 insertions(+), 133 deletions(-)

--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -230,6 +230,8 @@ struct gdbarch
   gdbarch_core_read_description_ftype *core_read_description;
   gdbarch_static_transform_name_ftype *static_transform_name;
   int sofun_address_maybe_missing;
+  gdbarch_record_ftype *record;
+  gdbarch_record_dasm_ftype *record_dasm;
 };
 
 
@@ -352,6 +354,8 @@ struct gdbarch startup_gdbarch =
   0,  /* core_read_description */
   0,  /* static_transform_name */
   0,  /* sofun_address_maybe_missing */
+  NULL,
+  NULL,
   /* startup_gdbarch() */
 };
 
@@ -3391,6 +3395,48 @@ deprecated_current_gdbarch_select_hack (
   reinit_frame_cache ();
 }
 
+
+int
+gdbarch_record_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return (gdbarch->record != NULL);
+}
+
+int
+gdbarch_record (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->record != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_record called\n");
+  return (gdbarch->record (gdbarch));
+}
+
+void
+set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype * record)
+{
+  gdbarch->record = record;
+}
+
+void
+gdbarch_record_dasm (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->record_dasm != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_record_dasm called\n");
+  gdbarch->record_dasm (gdbarch);
+}
+
+void
+set_gdbarch_record_dasm (struct gdbarch *gdbarch,
+			 gdbarch_record_dasm_ftype * record_dasm)
+{
+  gdbarch->record_dasm = record_dasm;
+}
+
+
 extern void _initialize_gdbarch (void);
 
 void
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -900,4 +900,17 @@ extern int gdbarch_debug;
 
 extern void gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file);
 
+
+extern int gdbarch_record_p (struct gdbarch *gdbarch);
+typedef int (gdbarch_record_ftype) (struct gdbarch *gdbarch);
+extern int gdbarch_record (struct gdbarch *gdbarch);
+extern void set_gdbarch_record (struct gdbarch *gdbarch,
+				gdbarch_record_ftype * record);
+
+typedef void (gdbarch_record_dasm_ftype) (struct gdbarch *gdbarch);
+extern void gdbarch_record_dasm (struct gdbarch *gdbarch);
+extern void set_gdbarch_record_dasm (struct gdbarch *gdbarch,
+				     gdbarch_record_dasm_ftype * record_dasm);
+
+
 #endif
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -35,6 +35,9 @@
 #include "solib-svr4.h"
 #include "symtab.h"
 
+#include "record.h"
+#include <stdint.h>
+
 /* Return the name of register REG.  */
 
 static const char *
@@ -335,6 +338,2533 @@ i386_linux_write_pc (struct regcache *re
      restarted.  */
   regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
 }
+
+
+/* These macros are the size of the type that will be use in system call. The values of
+   these macros are gotten from Linux Kernel source. */
+#define I386_RECORD_SIZE__old_kernel_stat	32
+#define I386_RECORD_SIZE_tms			16
+#define I386_RECORD_SIZE_loff_t			8
+#define I386_RECORD_SIZE_flock			16
+#define I386_RECORD_SIZE_oldold_utsname		45
+#define I386_RECORD_SIZE_ustat			20
+#define I386_RECORD_SIZE_old_sigaction		140
+#define I386_RECORD_SIZE_old_sigset_t		128
+#define I386_RECORD_SIZE_rlimit			8
+#define I386_RECORD_SIZE_rusage			72
+#define I386_RECORD_SIZE_timeval		8
+#define I386_RECORD_SIZE_timezone		8
+#define I386_RECORD_SIZE_old_gid_t		2
+#define I386_RECORD_SIZE_old_uid_t		2
+#define I386_RECORD_SIZE_fd_set			128
+#define I386_RECORD_SIZE_dirent			268
+#define I386_RECORD_SIZE_dirent64		276
+#define I386_RECORD_SIZE_statfs			64
+#define I386_RECORD_SIZE_statfs64		84
+#define I386_RECORD_SIZE_sockaddr		16
+#define I386_RECORD_SIZE_int			4
+#define I386_RECORD_SIZE_long			4
+#define I386_RECORD_SIZE_ulong			4
+#define I386_RECORD_SIZE_msghdr			28
+#define I386_RECORD_SIZE_itimerval		16
+#define I386_RECORD_SIZE_stat			88
+#define I386_RECORD_SIZE_old_utsname		325
+#define I386_RECORD_SIZE_rusage			72
+#define I386_RECORD_SIZE_sysinfo		64
+#define I386_RECORD_SIZE_msqid_ds		88
+#define I386_RECORD_SIZE_shmid_ds		84
+#define I386_RECORD_SIZE_new_utsname		390
+#define I386_RECORD_SIZE_timex			128
+#define I386_RECORD_SIZE_mem_dqinfo		24
+#define I386_RECORD_SIZE_if_dqblk		68
+#define I386_RECORD_SIZE_fs_quota_stat		68
+#define I386_RECORD_SIZE_timespec		8
+#define I386_RECORD_SIZE_pollfd			8
+#define I386_RECORD_SIZE_NFS_FHSIZE		32
+#define I386_RECORD_SIZE_knfsd_fh		132
+#define I386_RECORD_SIZE_TASK_COMM_LEN		16
+#define I386_RECORD_SIZE_sigaction		140
+#define I386_RECORD_SIZE_sigset_t		8
+#define I386_RECORD_SIZE_siginfo_t		128
+#define I386_RECORD_SIZE_cap_user_data_t	12
+#define I386_RECORD_SIZE_stack_t		12
+#define I386_RECORD_SIZE_off_t			I386_RECORD_SIZE_long
+#define I386_RECORD_SIZE_stat64			96
+#define I386_RECORD_SIZE_gid_t			2
+#define I386_RECORD_SIZE_uid_t			2
+#define I386_RECORD_SIZE_uid_t			2
+#define I386_RECORD_SIZE_PAGE_SIZE		4096
+#define I386_RECORD_SIZE_flock64		24
+#define I386_RECORD_SIZE_user_desc		16
+#define I386_RECORD_SIZE_io_event		32
+#define I386_RECORD_SIZE_iocb			64
+#define I386_RECORD_SIZE_epoll_event		12
+#define I386_RECORD_SIZE_itimerspec		(I386_RECORD_SIZE_timespec * 2)
+#define I386_RECORD_SIZE_mq_attr		32
+#define I386_RECORD_SIZE_siginfo		128
+#define I386_RECORD_SIZE_rusage			72
+
+/* These macros are the values of the first argument of system call
+   "sys_ptrace". The values of these macros are gotten from Linux Kernel
+   source. */
+#define I386_RECORD_PTRACE_PEEKTEXT	1
+#define I386_RECORD_PTRACE_PEEKDATA	2
+#define I386_RECORD_PTRACE_PEEKUSR	3
+
+/* These macros are the values of the second argument of system call
+   "sys_ioctl". The values of these macros are gotten from Linux Kernel
+   source. */
+#define I386_RECORD_FIONCLEX	0x5450
+#define I386_RECORD_FIOCLEX	0x5451
+#define I386_RECORD_FIONBIO	0x5421
+#define I386_RECORD_FIOASYNC	0x5452
+#define I386_RECORD_FIOQSIZE	0x5460
+
+/* These macros are the values of the first argument of system call
+   "sys_socketcall". The values of these macros are gotten from Linux Kernel
+   source. */
+#define I386_RECORD_SYS_SOCKET		1
+#define I386_RECORD_SYS_BIND		2
+#define I386_RECORD_SYS_CONNECT	3
+#define I386_RECORD_SYS_LISTEN		4
+#define I386_RECORD_SYS_ACCEPT		5
+#define I386_RECORD_SYS_GETSOCKNAME	6
+#define I386_RECORD_SYS_GETPEERNAME	7
+#define I386_RECORD_SYS_SOCKETPAIR	8
+#define I386_RECORD_SYS_SEND		9
+#define I386_RECORD_SYS_RECV		10
+#define I386_RECORD_SYS_SENDTO		11
+#define I386_RECORD_SYS_RECVFROM	12
+#define I386_RECORD_SYS_SHUTDOWN	13
+#define I386_RECORD_SYS_SETSOCKOPT	14
+#define I386_RECORD_SYS_GETSOCKOPT	15
+#define I386_RECORD_SYS_SENDMSG	16
+#define I386_RECORD_SYS_RECVMSG	17
+
+/* These macros are the values of the first argument of system call
+   "sys_ipc". The values of these macros are gotten from Linux Kernel source. */
+#define I386_RECORD_SEMOP		1
+#define I386_RECORD_SEMGET		2
+#define I386_RECORD_SEMCTL		3
+#define I386_RECORD_SEMTIMEDOP		4
+#define I386_RECORD_MSGSND		11
+#define I386_RECORD_MSGRCV		12
+#define I386_RECORD_MSGGET		13
+#define I386_RECORD_MSGCTL		14
+#define I386_RECORD_SHMAT		21
+#define I386_RECORD_SHMDT		22
+#define I386_RECORD_SHMGET		23
+#define I386_RECORD_SHMCTL		24
+
+/* These macros are the values of the first argument of system call
+   "sys_quotactl". The values of these macros are gotten from Linux Kernel
+   source. */
+#define I386_RECORD_Q_GETFMT		0x800004
+#define I386_RECORD_Q_GETINFO		0x800005
+#define I386_RECORD_Q_GETQUOTA		0x800007
+#define I386_RECORD_Q_XGETQSTAT	(('5'<<8)+(5))
+#define I386_RECORD_Q_XGETQUOTA	(('3'<<8)+(3))
+
+/* Parse the arguments of current system call instruction and record the
+   values of the registers and memory that will be changed in current system
+   call instruction to "record_arch_list". This instruction is "int 0x80" (Linux
+   Kernel2.4) or "sysenter" (Linux Kernel 2.6).
+   Return -1 if something wrong. */
+static int
+i386_linux_intx80_sysenter_record (void)
+{
+  uint32_t tmpu32;
+
+  regcache_raw_read (record_regcache, I386_EAX_REGNUM, (gdb_byte *) & tmpu32);
+  switch (tmpu32)
+    {
+      /* sys_restart_syscall */
+    case 0:
+      {
+	int q;
+	target_terminal_ours ();
+	q =
+	  yquery (_
+		  ("The next instruction is syscall restart. It will restart the computer. Do you want to pause the program."));
+	target_terminal_inferior ();
+	if (q)
+	  {
+	    return (1);
+	  }
+      }
+      break;
+
+      /* sys_exit */
+    case 1:
+      {
+	int q;
+	target_terminal_ours ();
+	q =
+	  yquery (_
+		  ("The next instruction is syscall exit. It will make the program exit. Do you want to pause the program."));
+	target_terminal_inferior ();
+	if (q)
+	  {
+	    return (1);
+	  }
+      }
+      break;
+
+      /* sys_fork */
+    case 2:
+      break;
+
+      /* sys_read */
+    case 3:
+      {
+	uint32_t addr, count;
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & addr);
+	regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			   (gdb_byte *) & count);
+	if (record_arch_list_add_mem (addr, count))
+	  {
+	    return (-1);
+	  }
+      }
+      break;
+
+      /* sys_write */
+    case 4:
+      /* sys_open */
+    case 5:
+      /* sys_close */
+    case 6:
+      /* sys_waitpid */
+    case 7:
+      /* sys_creat */
+    case 8:
+      /* sys_link */
+    case 9:
+      /* sys_unlink */
+    case 10:
+      /* sys_execve */
+    case 11:
+      /* sys_chdir */
+    case 12:
+      /* sys_time */
+    case 13:
+      /* sys_mknod */
+    case 14:
+      /* sys_chmod */
+    case 15:
+      /* sys_lchown16 */
+    case 16:
+      /* sys_ni_syscall */
+    case 17:
+      break;
+
+      /* sys_stat */
+    case 18:
+      /* sys_fstat */
+    case 28:
+      /* sys_lstat */
+    case 84:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE__old_kernel_stat))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_lseek */
+    case 19:
+      /* sys_getpid */
+    case 20:
+      /* sys_mount */
+    case 21:
+      /* sys_oldumount */
+    case 22:
+      /* sys_setuid16 */
+    case 23:
+      /* sys_getuid16 */
+    case 24:
+      /* sys_stime */
+    case 25:
+      break;
+
+      /* sys_ptrace */
+    case 26:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32 == I386_RECORD_PTRACE_PEEKTEXT
+	  || tmpu32 == I386_RECORD_PTRACE_PEEKDATA
+	  || tmpu32 == I386_RECORD_PTRACE_PEEKUSR)
+	{
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, 4))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_alarm */
+    case 27:
+      /* sys_pause */
+    case 29:
+      /* sys_utime    */
+    case 30:
+      /* sys_ni_syscall */
+    case 31:
+      /* sys_ni_syscall */
+    case 32:
+      /* sys_access */
+    case 33:
+      /* sys_nice */
+    case 34:
+      /* sys_ni_syscall */
+    case 35:
+      /* sys_sync */
+    case 36:
+      /* sys_kill */
+    case 37:
+      /* sys_rename */
+    case 38:
+      /* sys_mkdir */
+    case 39:
+      /* sys_rmdir */
+    case 40:
+      /* sys_dup */
+    case 41:
+      /* sys_pipe */
+    case 42:
+      break;
+
+      /* sys_times */
+    case 43:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_tms))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 44:
+      /* sys_brk */
+    case 45:
+      /* sys_setgid16 */
+    case 46:
+      /* sys_getgid16 */
+    case 47:
+      /* sys_signal */
+    case 48:
+      /* sys_geteuid16 */
+    case 49:
+      /* sys_getegid16 */
+    case 50:
+      /* sys_acct */
+    case 51:
+      /* sys_umount */
+    case 52:
+      /* sys_ni_syscall */
+    case 53:
+      break;
+
+      /* sys_ioctl */
+    case 54:
+      /* XXX */
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case I386_RECORD_FIOCLEX:
+	case I386_RECORD_FIONCLEX:
+	case I386_RECORD_FIONBIO:
+	case I386_RECORD_FIOASYNC:
+	  break;
+	case I386_RECORD_FIOQSIZE:
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_loff_t))
+	    {
+	      return (-1);
+	    }
+	  break;
+	default:
+	  printf_unfiltered (_
+			     ("record: record and reverse function don't support ioctl request 0x%08x\n"),
+			     tmpu32);
+	  return (-1);
+	  break;
+	}
+      break;
+
+      /* sys_fcntl */
+    case 55:
+      /* XXX */
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+    sys_fcntl:
+      if (tmpu32 == F_GETLK)
+	{
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_flock))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 56:
+      /* sys_setpgid */
+    case 57:
+      /* sys_ni_syscall */
+    case 58:
+      break;
+
+      /* sys_olduname */
+    case 59:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_oldold_utsname))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_umask */
+    case 60:
+      /* sys_chroot */
+    case 61:
+      break;
+
+      /* sys_ustat */
+    case 62:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_ustat))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_dup2 */
+    case 63:
+      /* sys_getppid */
+    case 64:
+      /* sys_getpgrp */
+    case 65:
+      /* sys_setsid */
+    case 66:
+      break;
+
+      /* sys_sigaction */
+    case 67:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_sigaction))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_sgetmask */
+    case 68:
+      /* sys_ssetmask */
+    case 69:
+      /* sys_setreuid16 */
+    case 70:
+      /* sys_setregid16 */
+    case 71:
+      /* sys_sigsuspend */
+    case 72:
+      break;
+
+      /* sys_sigpending */
+    case 73:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_sigset_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_sethostname */
+    case 74:
+      /* sys_setrlimit */
+    case 75:
+      break;
+
+      /* sys_old_getrlimit */
+    case 76:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_rlimit))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_getrusage */
+    case 77:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_rusage))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_gettimeofday */
+    case 78:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timeval))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timezone))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_settimeofday */
+    case 79:
+      break;
+
+      /* sys_getgroups16 */
+    case 80:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_gid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_setgroups16 */
+    case 81:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_gid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* old_select */
+    case 82:
+      {
+	/*
+	   struct sel_arg_struct {
+	   unsigned long n;
+	   fd_set *inp;
+	   fd_set *outp;
+	   fd_set *exp;
+	   struct timeval *tvp;
+	   };
+	 */
+	struct sel_arg_struct
+	{
+	  uint32_t n;
+	  uint32_t inp;
+	  uint32_t outp;
+	  uint32_t exp;
+	  uint32_t tvp;
+	} sel;
+
+	regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			   (gdb_byte *) & tmpu32);
+	if (tmpu32)
+	  {
+	    if (target_read_memory (tmpu32, (gdb_byte *) & sel, sizeof (sel)))
+	      {
+		fprintf_unfiltered (gdb_stdlog,
+				    "record: read memory addr = 0x%s len = %d error.\n",
+				    paddr_nz (tmpu32), sizeof (sel));
+		return (-1);
+	      }
+	    if (record_arch_list_add_mem (sel.inp, I386_RECORD_SIZE_fd_set))
+	      {
+		return (-1);
+	      }
+	    if (record_arch_list_add_mem (sel.outp, I386_RECORD_SIZE_fd_set))
+	      {
+		return (-1);
+	      }
+	    if (record_arch_list_add_mem (sel.exp, I386_RECORD_SIZE_fd_set))
+	      {
+		return (-1);
+	      }
+	    if (record_arch_list_add_mem (sel.tvp, I386_RECORD_SIZE_timeval))
+	      {
+		return (-1);
+	      }
+	  }
+      }
+      break;
+
+      /* sys_symlink */
+    case 83:
+      break;
+
+      /* sys_readlink */
+    case 85:
+      {
+	uint32_t len;
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			   (gdb_byte *) & len);
+	if (record_arch_list_add_mem (tmpu32, len))
+	  {
+	    return (-1);
+	  }
+      }
+      break;
+
+      /* sys_uselib */
+    case 86:
+      /* sys_swapon */
+    case 87:
+      break;
+
+      /* sys_reboot */
+    case 88:
+      {
+	int q;
+	target_terminal_ours ();
+	q =
+	  yquery (_
+		  ("The next instruction is syscall reboot. It will restart the computer. Do you want to pause the program."));
+	target_terminal_inferior ();
+	if (q)
+	  {
+	    return (1);
+	  }
+      }
+      break;
+
+      /* old_readdir */
+    case 89:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_dirent))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* old_mmap */
+    case 90:
+      break;
+
+      /* sys_munmap */
+    case 91:
+      {
+	int q;
+	uint32_t len;
+
+	regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			   (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & len);
+	target_terminal_ours ();
+	q =
+	  yquery (_
+		  ("The next instruction is syscall munmap. It will free the memory addr = 0x%s len = %d. Do you want to pause the program."),
+		  paddr_nz (tmpu32), len);
+	target_terminal_inferior ();
+	if (q)
+	  {
+	    return (1);
+	  }
+      }
+      break;
+
+      /* sys_truncate */
+    case 92:
+      /* sys_ftruncate */
+    case 93:
+      /* sys_fchmod */
+    case 94:
+      /* sys_fchown16 */
+    case 95:
+      /* sys_getpriority */
+    case 96:
+      /* sys_setpriority */
+    case 97:
+      /* sys_ni_syscall */
+    case 98:
+      break;
+
+      /* sys_statfs */
+    case 99:
+      /* sys_fstatfs */
+    case 100:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_statfs))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ioperm */
+    case 101:
+      break;
+
+      /* sys_socketcall */
+    case 102:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case I386_RECORD_SYS_SOCKET:
+	case I386_RECORD_SYS_BIND:
+	case I386_RECORD_SYS_CONNECT:
+	case I386_RECORD_SYS_LISTEN:
+	  break;
+	case I386_RECORD_SYS_ACCEPT:
+	case I386_RECORD_SYS_GETSOCKNAME:
+	case I386_RECORD_SYS_GETPEERNAME:
+	  {
+	    uint32_t a[3];
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (a[1], I386_RECORD_SIZE_sockaddr))
+		  {
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (a[2], I386_RECORD_SIZE_int))
+		  {
+		    return (-1);
+		  }
+	      }
+	  }
+	  break;
+
+	case I386_RECORD_SYS_SOCKETPAIR:
+	  {
+	    uint32_t a[4];
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (a[3], I386_RECORD_SIZE_int))
+		  {
+		    return (-1);
+		  }
+	      }
+	  }
+	  break;
+	case I386_RECORD_SYS_SEND:
+	case I386_RECORD_SYS_SENDTO:
+	  break;
+	case I386_RECORD_SYS_RECV:
+	  {
+	    uint32_t a[3];
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (a[2])
+		  {
+		    if (target_read_memory
+			(a[2], (gdb_byte *) & (a[2]), sizeof (a[2])))
+		      {
+			fprintf_unfiltered (gdb_stdlog,
+					    "record: read memory addr = 0x%s len = %d error.\n",
+					    paddr_nz (a[2]), sizeof (a[2]));
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[1], a[2]))
+		      {
+			return (-1);
+		      }
+		  }
+	      }
+	  }
+	  break;
+	case I386_RECORD_SYS_RECVFROM:
+	  {
+	    uint32_t a[6];
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (a[2])
+		  {
+		    if (target_read_memory
+			(a[2], (gdb_byte *) & (a[2]), sizeof (a[2])))
+		      {
+			fprintf_unfiltered (gdb_stdlog,
+					    "record: read memory addr = 0x%s len = %d error.\n",
+					    paddr_nz (a[2]), sizeof (a[2]));
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[1], a[2]))
+		      {
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[4], I386_RECORD_SIZE_sockaddr))
+		      {
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[5], I386_RECORD_SIZE_int))
+		      {
+			return (-1);
+		      }
+		  }
+	      }
+	  }
+	  break;
+	case I386_RECORD_SYS_SHUTDOWN:
+	case I386_RECORD_SYS_SETSOCKOPT:
+	  break;
+	case I386_RECORD_SYS_GETSOCKOPT:
+	  {
+	    uint32_t a[5];
+	    uint32_t av;
+
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (a[4])
+		  {
+		    if (target_read_memory
+			(a[4], (gdb_byte *) & av, sizeof (av)))
+		      {
+			fprintf_unfiltered (gdb_stdlog,
+					    "record: read memory addr = 0x%s len = %d error.\n",
+					    paddr_nz (a[4]), sizeof (av));
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[3], av))
+		      {
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem (a[4], I386_RECORD_SIZE_int))
+		      {
+			return (-1);
+		      }
+		  }
+	      }
+	  }
+	  break;
+	case I386_RECORD_SYS_SENDMSG:
+	  break;
+	case I386_RECORD_SYS_RECVMSG:
+	  {
+	    uint32_t a[2], i;
+	    struct record_msghdr
+	    {
+	      uint32_t msg_name;
+	      uint32_t msg_namelen;
+	      uint32_t msg_iov;
+	      uint32_t msg_iovlen;
+	      uint32_t msg_control;
+	      uint32_t msg_controllen;
+	      uint32_t msg_flags;
+	    } rec;
+	    struct record_iovec
+	    {
+	      uint32_t iov_base;
+	      uint32_t iov_len;
+	    } iov;
+
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if (tmpu32)
+	      {
+		if (target_read_memory (tmpu32, (gdb_byte *) a, sizeof (a)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (tmpu32), sizeof (a));
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (a[1], I386_RECORD_SIZE_msghdr))
+		  {
+		    return (-1);
+		  }
+		if (a[1])
+		  {
+		    if (target_read_memory
+			(a[1], (gdb_byte *) & rec, sizeof (rec)))
+		      {
+			fprintf_unfiltered (gdb_stdlog,
+					    "record: read memory addr = 0x%s len = %d error.\n",
+					    paddr_nz (a[1]), sizeof (rec));
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem
+			(rec.msg_name, rec.msg_namelen))
+		      {
+			return (-1);
+		      }
+		    if (record_arch_list_add_mem
+			(rec.msg_control, rec.msg_controllen))
+		      {
+			return (-1);
+		      }
+		    if (rec.msg_iov)
+		      {
+			for (i = 0; i < rec.msg_iovlen; i++)
+			  {
+			    if (target_read_memory
+				(rec.msg_iov, (gdb_byte *) & iov,
+				 sizeof (iov)))
+			      {
+				fprintf_unfiltered (gdb_stdlog,
+						    "record: read memory addr = 0x%s len = %d error.\n",
+						    paddr_nz (rec.msg_iov),
+						    sizeof (iov));
+				return (-1);
+			      }
+			    if (record_arch_list_add_mem
+				(iov.iov_base, iov.iov_len))
+			      {
+				return (-1);
+			      }
+			    rec.msg_iov += sizeof (struct record_iovec);
+			  }
+		      }
+		  }
+	      }
+	  }
+	  break;
+	default:
+	  printf_unfiltered (_
+			     ("record: record and reverse function don't support socketcall call 0x%08x\n"),
+			     tmpu32);
+	  return (-1);
+	  break;
+	}
+      break;
+
+      /* sys_syslog */
+    case 103:
+      break;
+
+      /* sys_setitimer */
+    case 104:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_itimerval))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_getitimer */
+    case 105:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_itimerval))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_newstat */
+    case 106:
+      /* sys_newlstat */
+    case 107:
+      /* sys_newfstat */
+    case 108:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_stat))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_uname */
+    case 109:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_utsname))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_iopl */
+    case 110:
+      /* sys_vhangup */
+    case 111:
+      /* sys_ni_syscall */
+    case 112:
+      /* sys_vm86old */
+    case 113:
+      break;
+
+      /* sys_wait4 */
+    case 114:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_rusage))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_swapoff */
+    case 115:
+      break;
+
+      /* sys_sysinfo */
+    case 116:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_sysinfo))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ipc */
+    case 117:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case I386_RECORD_MSGRCV:
+	  {
+	    int32_t second;
+	    uint32_t ptr;
+	    regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			       (gdb_byte *) & second);
+	    regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			       (gdb_byte *) & ptr);
+	    if (record_arch_list_add_mem (ptr, second + I386_RECORD_SIZE_long))
+	      {
+		return (-1);
+	      }
+	  }
+	  break;
+	case I386_RECORD_MSGCTL:
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_msqid_ds))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case I386_RECORD_SHMAT:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_ulong))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case I386_RECORD_SHMCTL:
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_shmid_ds))
+	    {
+	      return (-1);
+	    }
+	  break;
+	}
+      break;
+
+      /* sys_fsync */
+    case 118:
+      /* sys_sigreturn */
+    case 119:
+      /* sys_clone */
+    case 120:
+      /* sys_setdomainname */
+    case 121:
+      break;
+
+      /* sys_newuname */
+    case 122:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_new_utsname))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_modify_ldt */
+    case 123:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32 == 0 || tmpu32 == 2)
+	{
+	  uint32_t ptr, bytecount;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & ptr);
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & bytecount);
+	  if (record_arch_list_add_mem (ptr, bytecount))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_adjtimex */
+    case 124:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timex))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_mprotect */
+    case 125:
+      break;
+
+      /* sys_sigprocmask */
+    case 126:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_sigset_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 127:
+      /* sys_init_module */
+    case 128:
+      /* sys_delete_module */
+    case 129:
+      /* sys_ni_syscall */
+    case 130:
+      break;
+
+      /* sys_quotactl */
+    case 131:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case I386_RECORD_Q_GETFMT:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, 4))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case I386_RECORD_Q_GETINFO:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_mem_dqinfo))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case I386_RECORD_Q_GETQUOTA:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_if_dqblk))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case I386_RECORD_Q_XGETQSTAT:
+	case I386_RECORD_Q_XGETQUOTA:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fs_quota_stat))
+	    {
+	      return (-1);
+	    }
+	  break;
+	}
+      break;
+
+      /* sys_getpgid */
+    case 132:
+      /* sys_fchdir */
+    case 133:
+      /* sys_bdflush */
+    case 134:
+      break;
+
+      /* sys_sysfs */
+    case 135:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32 == 2)
+	{
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  /*XXX the size of memory is not very clear */
+	  if (record_arch_list_add_mem (tmpu32, 10))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_personality */
+    case 136:
+      /* sys_ni_syscall */
+    case 137:
+      /* sys_setfsuid16 */
+    case 138:
+      /* sys_setfsgid16 */
+    case 139:
+      break;
+
+      /* sys_llseek */
+    case 140:
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_loff_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_getdents */
+    case 141:
+      {
+	uint32_t count;
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			   (gdb_byte *) & count);
+	if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_dirent * count))
+	  {
+	    return (-1);
+	  }
+      }
+      break;
+
+      /* sys_select */
+    case 142:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timeval))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_flock */
+    case 143:
+      /* sys_msync */
+    case 144:
+      break;
+
+      /* sys_readv */
+    case 145:
+      {
+	uint32_t vec;
+	uint32_t vlen;
+	struct record_iovec
+	{
+	  uint32_t iov_base;
+	  uint32_t iov_len;
+	} iov;
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & vec);
+	if (vec)
+	  {
+	    regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			       (gdb_byte *) & vlen);
+	    for (tmpu32 = 0; tmpu32 < vlen; tmpu32++)
+	      {
+		if (target_read_memory
+		    (vec, (gdb_byte *) & iov, sizeof (struct record_iovec)))
+		  {
+		    fprintf_unfiltered (gdb_stdlog,
+					"record: read memory addr = 0x%s len = %d error.\n",
+					paddr_nz (vec),
+					sizeof (struct record_iovec));
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (iov.iov_base, iov.iov_len))
+		  {
+		    return (-1);
+		  }
+		vec += sizeof (struct record_iovec);
+	      }
+	  }
+      }
+      break;
+
+      /* sys_writev */
+    case 146:
+      /* sys_getsid */
+    case 147:
+      /* sys_fdatasync */
+    case 148:
+      /* sys_sysctl */
+    case 149:
+      /* sys_mlock */
+    case 150:
+      /* sys_munlock */
+    case 151:
+      /* sys_mlockall */
+    case 152:
+      /* sys_munlockall */
+    case 153:
+      /* sys_sched_setparam */
+    case 154:
+      break;
+
+      /* sys_sched_getparam */
+    case 155:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_sched_setscheduler */
+    case 156:
+      /* sys_sched_getscheduler */
+    case 157:
+      /* sys_sched_yield */
+    case 158:
+      /* sys_sched_get_priority_max */
+    case 159:
+      /* sys_sched_get_priority_min */
+    case 160:
+      break;
+
+      /* sys_sched_rr_get_interval */
+    case 161:
+      /* sys_nanosleep */
+    case 162:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_mremap */
+    case 163:
+      /* sys_setresuid16 */
+    case 164:
+      break;
+
+      /* sys_getresuid16 */
+    case 165:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_uid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_uid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_uid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_vm86 */
+    case 166:
+      /* sys_ni_syscall */
+    case 167:
+      break;
+
+      /* sys_poll */
+    case 168:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t nfds;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & nfds);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_pollfd * nfds))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_nfsservctl */
+    case 169:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32 == 7 || tmpu32 == 8)
+	{
+	  uint32_t rsize;
+	  if (tmpu32 == 7)
+	    {
+	      rsize = I386_RECORD_SIZE_NFS_FHSIZE;
+	    }
+	  else
+	    {
+	      rsize = I386_RECORD_SIZE_knfsd_fh;
+	    }
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, rsize))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_setresgid16 */
+    case 170:
+      break;
+
+      /* sys_getresgid16 */
+    case 171:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_gid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_gid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_old_gid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_prctl */
+    case 172:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case 2:
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case 16:
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_TASK_COMM_LEN))
+	    {
+	      return (-1);
+	    }
+	  break;
+	}
+      break;
+
+      /* sys_rt_sigreturn */
+    case 173:
+      break;
+
+      /* sys_rt_sigaction */
+    case 174:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_sigaction))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_rt_sigprocmask */
+    case 175:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_sigset_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_rt_sigpending */
+    case 176:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t sigsetsize;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & sigsetsize);
+	  if (record_arch_list_add_mem (tmpu32, sigsetsize))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_rt_sigtimedwait */
+    case 177:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_siginfo_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_rt_sigqueueinfo */
+    case 178:
+      /* sys_rt_sigsuspend */
+    case 179:
+      break;
+
+      /* sys_pread64 */
+    case 180:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t count;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & count);
+	  if (record_arch_list_add_mem (tmpu32, count))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_pwrite64 */
+    case 181:
+      /* sys_chown16 */
+    case 182:
+      break;
+
+      /* sys_getcwd */
+    case 183:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t size;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & size);
+	  if (record_arch_list_add_mem (tmpu32, size))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_capget */
+    case 184:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_cap_user_data_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_capset */
+    case 185:
+      break;
+
+      /* sys_sigaltstack */
+    case 186:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_stack_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_sendfile */
+    case 187:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_off_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 188:
+      /* sys_ni_syscall */
+    case 189:
+      /* sys_vfork */
+    case 190:
+      break;
+
+      /* sys_getrlimit */
+    case 191:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_rlimit))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_mmap2 */
+    case 192:
+      break;
+
+      /* sys_truncate64 */
+    case 193:
+      /* sys_ftruncate64 */
+    case 194:
+      break;
+
+      /* sys_stat64 */
+    case 195:
+      /* sys_lstat64 */
+    case 196:
+      /* sys_fstat64 */
+    case 197:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_stat64))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_lchown */
+    case 198:
+      /* sys_getuid */
+    case 199:
+      /* sys_getgid */
+    case 200:
+      /* sys_geteuid */
+    case 201:
+      /* sys_getegid */
+    case 202:
+      /* sys_setreuid */
+    case 203:
+      /* sys_setregid */
+    case 204:
+      break;
+
+      /* sys_getgroups */
+    case 205:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int gidsetsize;
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & gidsetsize);
+	  if (record_arch_list_add_mem
+	      (tmpu32, I386_RECORD_SIZE_gid_t * gidsetsize))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_setgroups */
+    case 206:
+      /* sys_fchown */
+    case 207:
+      /* sys_setresuid */
+    case 208:
+      break;
+
+      /* sys_getresuid */
+    case 209:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_uid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_uid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_uid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_setresgid */
+    case 210:
+      break;
+
+      /* sys_getresgid */
+    case 211:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_gid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_gid_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_gid_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_chown */
+    case 212:
+      /* sys_setuid */
+    case 213:
+      /* sys_setgid */
+    case 214:
+      /* sys_setfsuid */
+    case 215:
+      /* sys_setfsgid */
+    case 216:
+      /* sys_pivot_root */
+    case 217:
+      break;
+
+      /* sys_mincore */
+    case 218:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_PAGE_SIZE))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_madvise */
+    case 219:
+      break;
+
+      /* sys_getdents64 */
+    case 220:
+      {
+	uint32_t count;
+	regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			   (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			   (gdb_byte *) & count);
+	if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_dirent64 * count))
+	  {
+	    return (-1);
+	  }
+      }
+      break;
+
+      /* sys_fcntl64 */
+    case 221:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      switch (tmpu32)
+	{
+	case F_GETLK64:
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_flock64))
+	    {
+	      return (-1);
+	    }
+	  break;
+	case F_SETLK64:
+	case F_SETLKW64:
+	  break;
+	default:
+	  goto sys_fcntl;
+	  break;
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 222:
+      /* sys_ni_syscall */
+    case 223:
+      /* sys_gettid */
+    case 224:
+      /* sys_readahead */
+    case 225:
+      /* sys_setxattr */
+    case 226:
+      /* sys_lsetxattr */
+    case 227:
+      /* sys_fsetxattr */
+    case 228:
+      break;
+
+      /* sys_getxattr */
+    case 229:
+      /* sys_lgetxattr */
+    case 230:
+      /* sys_fgetxattr */
+    case 231:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t size;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & size);
+	  if (record_arch_list_add_mem (tmpu32, size))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_listxattr */
+    case 232:
+      /* sys_llistxattr */
+    case 233:
+      /* sys_flistxattr */
+    case 234:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t size;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & size);
+	  if (record_arch_list_add_mem (tmpu32, size))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_removexattr */
+    case 235:
+      /* sys_lremovexattr */
+    case 236:
+      /* sys_fremovexattr */
+    case 237:
+      /* sys_tkill */
+    case 238:
+      break;
+
+      /* sys_sendfile64 */
+    case 239:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_loff_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_futex */
+    case 240:
+      /* sys_sched_setaffinity */
+    case 241:
+      break;
+
+      /* sys_sched_getaffinity */
+    case 242:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t len;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & len);
+	  if (record_arch_list_add_mem (tmpu32, len))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_set_thread_area */
+    case 243:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_get_thread_area */
+    case 244:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_user_desc))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_io_setup */
+    case 245:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_long))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_io_destroy */
+    case 246:
+      break;
+
+      /* sys_io_getevents */
+    case 247:
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int32_t nr;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & nr);
+	  if (record_arch_list_add_mem (tmpu32, nr * I386_RECORD_SIZE_io_event))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_io_submit */
+    case 248:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int32_t i, nr;
+	  uint32_t *iocbp;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & nr);
+	  iocbp = (uint32_t *) alloca (nr * I386_RECORD_SIZE_int);
+	  if (target_read_memory
+	      (tmpu32, (gdb_byte *) iocbp, nr * I386_RECORD_SIZE_int))
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: read memory addr = 0x%s len = %d error.\n",
+				  paddr_nz (tmpu32), nr * I386_RECORD_SIZE_int);
+	      return (-1);
+	    }
+	  for (i = 0; i < nr; i++)
+	    {
+	      if (record_arch_list_add_mem (iocbp[i], I386_RECORD_SIZE_iocb))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      break;
+
+      /* sys_io_cancel */
+    case 249:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_io_event))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_fadvise64 */
+    case 250:
+      /* sys_ni_syscall */
+    case 251:
+      break;
+
+      /* sys_exit_group */
+    case 252:
+      {
+	int q;
+	target_terminal_ours ();
+	q =
+	  yquery (_
+		  ("The next instruction is syscall exit_group. It will make the program exit. Do you want to pause the program."));
+	target_terminal_inferior ();
+	if (q)
+	  {
+	    return (1);
+	  }
+      }
+      break;
+
+      /* sys_lookup_dcookie */
+    case 253:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t len;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & len);
+	  if (record_arch_list_add_mem (tmpu32, len))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_epoll_create */
+    case 254:
+      /* sys_epoll_ctl */
+    case 255:
+      break;
+
+      /* sys_epoll_wait */
+    case 256:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int32_t maxevents;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & maxevents);
+	  if (record_arch_list_add_mem
+	      (tmpu32, maxevents * I386_RECORD_SIZE_epoll_event))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_remap_file_pages */
+    case 257:
+      /* sys_set_tid_address */
+    case 258:
+      break;
+
+      /* sys_timer_create */
+    case 259:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_timer_settime */
+    case 260:
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_itimerspec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_timer_gettime */
+    case 261:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_itimerspec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_timer_getoverrun */
+    case 262:
+      /* sys_timer_delete */
+    case 263:
+      /* sys_clock_settime */
+    case 264:
+      break;
+
+      /* sys_clock_gettime */
+    case 265:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_clock_getres */
+    case 266:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_clock_nanosleep */
+    case 267:
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_statfs64 */
+    case 268:
+      /* sys_fstatfs64 */
+    case 269:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_statfs64))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_tgkill */
+    case 270:
+      /* sys_utimes */
+    case 271:
+      /* sys_fadvise64_64 */
+    case 272:
+      /* sys_ni_syscall */
+    case 273:
+      /* sys_mbind */
+    case 274:
+      break;
+
+      /* sys_get_mempolicy */
+    case 275:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t maxnode;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & maxnode);
+	  if (record_arch_list_add_mem (tmpu32, maxnode * I386_RECORD_SIZE_long))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_set_mempolicy */
+    case 276:
+      /* sys_mq_open */
+    case 277:
+      /* sys_mq_unlink */
+    case 278:
+      /* sys_mq_timedsend */
+    case 279:
+      break;
+
+      /* sys_mq_timedreceive */
+    case 280:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t msg_len;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & msg_len);
+	  if (record_arch_list_add_mem (tmpu32, msg_len))
+	    {
+	      return (-1);
+	    }
+	}
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_mq_notify */
+    case 281:
+      break;
+
+      /* sys_mq_getsetattr */
+    case 282:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_mq_attr))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_kexec_load */
+    case 283:
+      break;
+
+      /* sys_waitid */
+    case 284:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_siginfo))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_rusage))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ni_syscall */
+    case 285:
+      /* sys_add_key */
+    case 286:
+      /* sys_request_key */
+    case 287:
+      break;
+
+      /* sys_keyctl */
+    case 288:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32 == 6 || tmpu32 == 11)
+	{
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32)
+	    {
+	      uint32_t buflen;
+	      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+				 (gdb_byte *) & buflen);
+	      if (record_arch_list_add_mem (tmpu32, buflen))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      break;
+
+      /* sys_ioprio_set */
+    case 289:
+      /* sys_ioprio_get */
+    case 290:
+      /* sys_inotify_init */
+    case 291:
+      /* sys_inotify_add_watch */
+    case 292:
+      /* sys_inotify_rm_watch */
+    case 293:
+      /* sys_migrate_pages */
+    case 294:
+      /* sys_openat */
+    case 295:
+      /* sys_mkdirat */
+    case 296:
+      /* sys_mknodat */
+    case 297:
+      /* sys_fchownat */
+    case 298:
+      /* sys_futimesat */
+    case 299:
+      break;
+
+      /* sys_fstatat64 */
+    case 300:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_stat64))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_unlinkat */
+    case 301:
+      /* sys_renameat */
+    case 302:
+      /* sys_linkat */
+    case 303:
+      /* sys_symlinkat */
+    case 304:
+      break;
+
+      /* sys_readlinkat */
+    case 305:
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int32_t bufsiz;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & bufsiz);
+	  if (record_arch_list_add_mem (tmpu32, bufsiz))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_fchmodat */
+    case 306:
+      /* sys_faccessat */
+    case 307:
+      break;
+
+      /* sys_pselect6 */
+    case 308:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_fd_set))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_ppoll */
+    case 309:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t nfds;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & nfds);
+	  if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_pollfd * nfds))
+	    {
+	      return (-1);
+	    }
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_timespec))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_unshare */
+    case 310:
+      /* sys_set_robust_list */
+    case 311:
+      break;
+
+      /* sys_get_robust_list */
+    case 312:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_splice */
+    case 313:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_loff_t))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_loff_t))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_sync_file_range */
+    case 314:
+      /* sys_tee */
+    case 315:
+      /* sys_vmsplice */
+    case 316:
+      break;
+
+      /* sys_move_pages */
+    case 317:
+      regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  uint32_t nr_pages;
+	  regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			     (gdb_byte *) & nr_pages);
+	  if (record_arch_list_add_mem (tmpu32, nr_pages * I386_RECORD_SIZE_int))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* sys_getcpu */
+    case 318:
+      regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_int))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem (tmpu32, I386_RECORD_SIZE_ulong * 2))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sys_epoll_pwait */
+    case 319:
+      regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (tmpu32)
+	{
+	  int32_t maxevents;
+	  regcache_raw_read (record_regcache, I386_EDX_REGNUM,
+			     (gdb_byte *) & maxevents);
+	  if (record_arch_list_add_mem
+	      (tmpu32, maxevents * I386_RECORD_SIZE_epoll_event))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+    default:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support syscall number 0x%08x\n"),
+			 tmpu32);
+      return (-1);
+      break;
+    }
+  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+    {
+      return (-1);
+    }
+
+  return (0);
+}
+
 
 
 /* The register sets used in GNU/Linux ELF core-dumps are identical to
@@ -429,6 +2959,9 @@ i386_linux_init_abi (struct gdbarch_info
   tdep->sc_reg_offset = i386_linux_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
 
+  tdep->i386_intx80_record = i386_linux_intx80_sysenter_record;
+  tdep->i386_sysenter_record = i386_linux_intx80_sysenter_record;
+
   /* N_FUN symbols in shared libaries have 0 for their values and need
      to be relocated. */
   set_gdbarch_sofun_address_maybe_missing (gdbarch, 1);
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -49,6 +49,9 @@
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
+#include "record.h"
+#include <stdint.h>
+
 /* Register names.  */
 
 static char *i386_register_names[] =
@@ -2315,154 +2318,2682 @@ i386_fetch_pointer_argument (struct fram
   return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4);
 }
 
-
-static struct gdbarch *
-i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-{
-  struct gdbarch_tdep *tdep;
-  struct gdbarch *gdbarch;
 
-  /* If there is already a candidate, use it.  */
-  arches = gdbarch_list_lookup_by_info (arches, &info);
-  if (arches != NULL)
-    return arches->gdbarch;
+#define PREFIX_REPZ	0x01
+#define PREFIX_REPNZ	0x02
+#define PREFIX_LOCK	0x04
+#define PREFIX_DATA	0x08
+#define PREFIX_ADDR	0x10
+
+/* operand size */
+enum
+{
+  OT_BYTE = 0,
+  OT_WORD,
+  OT_LONG,
+};
 
-  /* Allocate space for the new architecture.  */
-  tdep = XCALLOC (1, struct gdbarch_tdep);
-  gdbarch = gdbarch_alloc (&info, tdep);
+/* i386 arith/logic operations */
+enum
+{
+  OP_ADDL,
+  OP_ORL,
+  OP_ADCL,
+  OP_SBBL,
+  OP_ANDL,
+  OP_SUBL,
+  OP_XORL,
+  OP_CMPL,
+};
 
-  /* General-purpose registers.  */
-  tdep->gregset = NULL;
-  tdep->gregset_reg_offset = NULL;
-  tdep->gregset_num_regs = I386_NUM_GREGS;
-  tdep->sizeof_gregset = 0;
+static int aflag = 1;
+static int dflag = 1;
+static int override = 0;
+static uint8_t modrm;
+static uint8_t mod, reg, rm;
+static int ot;
+static CORE_ADDR i386_record_pc;
 
-  /* Floating-point registers.  */
-  tdep->fpregset = NULL;
-  tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+/* Parse "modrm" part in current memory address that i386_record_pc point to.
+   Return -1 if something wrong. */
+static int
+i386_record_modrm (void)
+{
+  if (target_read_memory (i386_record_pc, &modrm, 1))
+    {
+      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+			 paddr_nz (i386_record_pc));
+      return (-1);
+    }
+  i386_record_pc++;
+  mod = (modrm >> 6) & 3;
+  reg = (modrm >> 3) & 7;
+  rm = modrm & 7;
 
-  /* The default settings include the FPU registers, the MMX registers
-     and the SSE registers.  This can be overridden for a specific ABI
-     by adjusting the members `st0_regnum', `mm0_regnum' and
-     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
-     will show up in the output of "info all-registers".  Ideally we
-     should try to autodetect whether they are available, such that we
-     can prevent "info all-registers" from displaying registers that
-     aren't available.
+  return (0);
+}
 
-     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
-     [the SSE registers] always (even when they don't exist) or never
-     showing them to the user (even when they do exist), I prefer the
-     former over the latter.  */
+/* Get the memory address that current instruction  write to and set it to
+   the argument "addr".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm_addr (uint32_t * addr)
+{
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+
+  *addr = 0;
+  if (aflag)
+    {
+      /* 32 bits */
+      int havesib = 0;
+      uint8_t scale = 0;
+      uint8_t index = 0;
+      uint8_t base = rm;
 
-  tdep->st0_regnum = I386_ST0_REGNUM;
+      if (base == 4)
+	{
+	  havesib = 1;
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				 paddr_nz (i386_record_pc));
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  scale = (tmpu8 >> 6) & 3;
+	  index = ((tmpu8 >> 3) & 7);
+	  base = (tmpu8 & 7);
+	}
 
-  /* The MMX registers are implemented as pseudo-registers.  Put off
-     calculating the register number for %mm0 until we know the number
-     of raw registers.  */
-  tdep->mm0_regnum = 0;
+      switch (mod)
+	{
+	case 0:
+	  if ((base & 7) == 5)
+	    {
+	      base = 0xff;
+	      if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+		{
+		  printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				     paddr_nz (i386_record_pc));
+		  return (-1);
+		}
+	      i386_record_pc += 4;
+	    }
+	  else
+	    {
+	      *addr = 0;
+	    }
+	  break;
+	case 1:
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				 paddr_nz (i386_record_pc));
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  *addr = (int8_t) tmpu8;
+	  break;
+	case 2:
+	  if (target_read_memory (i386_record_pc, (gdb_byte *) addr, 4))
+	    {
+	      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				 paddr_nz (i386_record_pc));
+	      return (-1);
+	    }
+	  i386_record_pc += 4;
+	  break;
+	}
 
-  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
-  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+      if (base != 0xff)
+	{
+	  regcache_raw_read (record_regcache, base, (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	}
 
-  tdep->jb_pc_offset = -1;
-  tdep->struct_return = pcc_struct_return;
-  tdep->sigtramp_start = 0;
-  tdep->sigtramp_end = 0;
-  tdep->sigtramp_p = i386_sigtramp_p;
-  tdep->sigcontext_addr = NULL;
-  tdep->sc_reg_offset = NULL;
-  tdep->sc_pc_offset = -1;
-  tdep->sc_sp_offset = -1;
+      /* XXX: index == 4 is always invalid */
+      if (havesib && (index != 4 || scale != 0))
+	{
+	  regcache_raw_read (record_regcache, index, (gdb_byte *) & tmpu32);
+	  *addr += tmpu32 << scale;
+	}
+    }
+  else
+    {
+      /* 16 bits */
+      switch (mod)
+	{
+	case 0:
+	  if (rm == 6)
+	    {
+	      if (target_read_memory
+		  (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+		{
+		  printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				     paddr_nz (i386_record_pc));
+		  return (-1);
+		}
+	      i386_record_pc += 2;
+	      *addr = (int16_t) tmpu16;
+	      rm = 0;
+	      goto no_rm;
+	    }
+	  else
+	    {
+	      *addr = 0;
+	    }
+	  break;
+	case 1:
+	  if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	    {
+	      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				 paddr_nz (i386_record_pc));
+	      return (-1);
+	    }
+	  i386_record_pc++;
+	  *addr = (int8_t) tmpu8;
+	  break;
+	case 2:
+	  if (target_read_memory (i386_record_pc, (gdb_byte *) & tmpu16, 2))
+	    {
+	      printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				 paddr_nz (i386_record_pc));
+	      return (-1);
+	    }
+	  i386_record_pc += 2;
+	  *addr = (int16_t) tmpu16;
+	  break;
+	}
 
-  /* The format used for `long double' on almost all i386 targets is
-     the i387 extended floating-point format.  In fact, of all targets
-     in the GCC 2.95 tree, only OSF/1 does it different, and insists
-     on having a `long double' that's not `long' at all.  */
-  set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
+      switch (rm)
+	{
+	case 0:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 1:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 2:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 3:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 4:
+	  regcache_raw_read (record_regcache, I386_ESI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 5:
+	  regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 6:
+	  regcache_raw_read (record_regcache, I386_EBP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	case 7:
+	  regcache_raw_read (record_regcache, I386_EBX_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	  break;
+	}
+      *addr &= 0xffff;
+    }
 
-  /* Although the i387 extended floating-point has only 80 significant
-     bits, a `long double' actually takes up 96, probably to enforce
-     alignment.  */
-  set_gdbarch_long_double_bit (gdbarch, 96);
+no_rm:
+  return (0);
+}
 
-  /* The default ABI includes general-purpose registers, 
-     floating-point registers, and the SSE registers.  */
-  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
-  set_gdbarch_register_name (gdbarch, i386_register_name);
-  set_gdbarch_register_type (gdbarch, i386_register_type);
+/* Record the value of the memory that willbe changed in current instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_record_lea_modrm (void)
+{
+  uint32_t addr;
 
-  /* Register numbers of various important registers.  */
-  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
-  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
-  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
-  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
+  if (override)
+    {
+      printf_unfiltered (_
+			 ("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"),
+			 paddr_nz (read_pc ()));
+      return (0);
+    }
 
-  /* NOTE: kettenis/20040418: GCC does have two possible register
-     numbering schemes on the i386: dbx and SVR4.  These schemes
-     differ in how they number %ebp, %esp, %eflags, and the
-     floating-point registers, and are implemented by the arrays
-     dbx_register_map[] and svr4_dbx_register_map in
-     gcc/config/i386.c.  GCC also defines a third numbering scheme in
-     gcc/config/i386.c, which it designates as the "default" register
-     map used in 64bit mode.  This last register numbering scheme is
-     implemented in dbx64_register_map, and is used for AMD64; see
-     amd64-tdep.c.
+  if (i386_record_lea_modrm_addr (&addr))
+    {
+      return (-1);
+    }
 
-     Currently, each GCC i386 target always uses the same register
-     numbering scheme across all its supported debugging formats
-     i.e. SDB (COFF), stabs and DWARF 2.  This is because
-     gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
-     DBX_REGISTER_NUMBER macro which is defined by each target's
-     respective config header in a manner independent of the requested
-     output debugging format.
+  if (record_arch_list_add_mem (addr, 1 << ot))
+    {
+      return (-1);
+    }
 
-     This does not match the arrangement below, which presumes that
-     the SDB and stabs numbering schemes differ from the DWARF and
-     DWARF 2 ones.  The reason for this arrangement is that it is
-     likely to get the numbering scheme for the target's
-     default/native debug format right.  For targets where GCC is the
-     native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
-     targets where the native toolchain uses a different numbering
-     scheme for a particular debug format (stabs-in-ELF on Solaris)
-     the defaults below will have to be overridden, like
-     i386_elf_init_abi() does.  */
+  return (0);
+}
 
-  /* Use the dbx register numbering scheme for stabs and COFF.  */
-  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
-  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+i386_record (struct gdbarch *gdbarch)
+{
+  int prefixes = 0;
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+  uint32_t opcode;
+  int need_dasm = 0;
 
-  /* Use the SVR4 register numbering scheme for DWARF and DWARF 2.  */
-  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+  i386_record_pc = read_pc ();
+  aflag = 1;
+  dflag = 1;
+  override = 0;
 
-  /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
-     be in use on any of the supported i386 targets.  */
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: i386_record pc = 0x%s\n",
+			  paddr_nz (i386_record_pc));
+    }
 
-  set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+  /* prefixes */
+  while (1)
+    {
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	{
+	  printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+			     paddr_nz (i386_record_pc));
+	  return (-1);
+	}
+      i386_record_pc++;
+      switch (tmpu8)
+	{
+	case 0xf3:
+	  prefixes |= PREFIX_REPZ;
+	  break;
+	case 0xf2:
+	  prefixes |= PREFIX_REPNZ;
+	  break;
+	case 0xf0:
+	  prefixes |= PREFIX_LOCK;
+	  break;
+	case 0x2e:
+	  override = I386_CS_REGNUM;
+	  break;
+	case 0x36:
+	  override = I386_SS_REGNUM;
+	  break;
+	case 0x3e:
+	  override = I386_DS_REGNUM;
+	  break;
+	case 0x26:
+	  override = I386_ES_REGNUM;
+	  break;
+	case 0x64:
+	  override = I386_FS_REGNUM;
+	  break;
+	case 0x65:
+	  override = I386_GS_REGNUM;
+	  break;
+	case 0x66:
+	  prefixes |= PREFIX_DATA;
+	  break;
+	case 0x67:
+	  prefixes |= PREFIX_ADDR;
+	  break;
+	default:
+	  goto out_prefixes;
+	  break;
+	}
+    }
+out_prefixes:
+  if (prefixes & PREFIX_DATA)
+    {
+      dflag ^= 1;
+    }
+  if (prefixes & PREFIX_ADDR)
+    {
+      aflag ^= 1;
+    }
 
-  set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
+  /* now check op code */
+  opcode = (uint32_t) tmpu8;
+reswitch:
+  switch (opcode)
+    {
+    case 0x0f:
+      if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	{
+	  printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+			     paddr_nz (i386_record_pc));
+	  return (-1);
+	}
+      i386_record_pc++;
+      opcode = (uint16_t) tmpu8 | 0x0f00;
+      goto reswitch;
+      break;
 
-  /* Call dummy code.  */
-  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
+      /* arith & logic */
+    case 0x00 ... 0x05:
+    case 0x08 ... 0x0d:
+    case 0x10 ... 0x15:
+    case 0x18 ... 0x1d:
+    case 0x20 ... 0x25:
+    case 0x28 ... 0x2d:
+    case 0x30 ... 0x35:
+    case 0x38 ... 0x3d:
+      if (((opcode >> 3) & 7) != OP_CMPL)
+	{
+	  if ((opcode & 1) == 0)
+	    {
+	      ot = OT_BYTE;
+	    }
+	  else
+	    {
+	      ot = dflag + OT_WORD;
+	    }
 
-  set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
-  set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
-  set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
+	  switch ((opcode >> 1) & 3)
+	    {
+	      /* OP Ev, Gv */
+	    case 0:
+	      if (i386_record_modrm ())
+		{
+		  return (-1);
+		}
+	      if (mod != 3)
+		{
+		  if (i386_record_lea_modrm ())
+		    {
+		      return (-1);
+		    }
+		}
+	      else
+		{
+		  if (ot == OT_BYTE)
+		    {
+		      rm &= 0x3;
+		    }
+		  if (record_arch_list_add_reg (rm))
+		    {
+		      return (-1);
+		    }
+		}
+	      break;
+	      /* OP Gv, Ev */
+	    case 1:
+	      if (i386_record_modrm ())
+		{
+		  return (-1);
+		}
+	      if (ot == OT_BYTE)
+		{
+		  reg &= 0x3;
+		}
+	      if (record_arch_list_add_reg (reg))
+		{
+		  return (-1);
+		}
+	      break;
+	      /* OP A, Iv */
+	    case 2:
+	      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+		{
+		  return (-1);
+		}
+	      break;
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
 
-  set_gdbarch_return_value (gdbarch, i386_return_value);
+      /* GRP1 */
+    case 0x80 ... 0x83:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
 
-  set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
+      if (reg != OP_CMPL)
+	{
+	  if ((opcode & 1) == 0)
+	    {
+	      ot = OT_BYTE;
+	    }
+	  else
+	    {
+	      ot = dflag + OT_WORD;
+	    }
 
-  /* Stack grows downward.  */
-  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  reg &= 0x3;
+		}
+	      if (record_arch_list_add_reg (reg))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
 
-  set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
-  set_gdbarch_decr_pc_after_break (gdbarch, 1);
+      /* inv */
+    case 0x40 ... 0x47:
+      /* dec */
+    case 0x48 ... 0x4f:
+      if (record_arch_list_add_reg (opcode & 7))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
 
-  set_gdbarch_frame_args_skip (gdbarch, 8);
+      /* GRP3 */
+    case 0xf6:
+    case 0xf7:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
 
-  /* Wire in the MMX registers.  */
+      switch (reg)
+	{
+	  /* test */
+	case 0:
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* not */
+	case 2:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* neg */
+	case 3:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* mul */
+	case 4:
+	  /* imul */
+	case 5:
+	  /* div */
+	case 6:
+	  /* idiv */
+	case 7:
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (ot != OT_BYTE)
+	    {
+	      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* GRP4 */
+    case 0xfe:
+      /* GRP5 */
+    case 0xff:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg >= 2 && opcode == 0xfe)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      switch (reg)
+	{
+	  /* inc */
+	case 0:
+	  /* dec */
+	case 1:
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (ot == OT_BYTE)
+		{
+		  rm &= 0x3;
+		}
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* call */
+	case 2:
+	  /* push */
+	case 6:
+	  if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem
+	      ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* lcall */
+	case 3:
+	  if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (record_arch_list_add_reg (I386_CS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			     (gdb_byte *) & tmpu32);
+	  if (record_arch_list_add_mem
+	      ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* jmp */
+	case 4:
+	  /* ljmp */
+	case 5:
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* test */
+    case 0x84:
+    case 0x85:
+    case 0xa8:
+    case 0xa9:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* CWDE/CBW */
+    case 0x98:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* CDQ/CWD */
+    case 0x99:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* imul */
+    case 0x0faf:
+    case 0x69:
+    case 0x6b:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xadd */
+    case 0x0fc0:
+    case 0x0fc1:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpxchg */
+    case 0x0fb0:
+    case 0x0fb1:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (ot == OT_BYTE)
+	    {
+	      reg &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (reg))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpxchg8b */
+    case 0x0fc7:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (i386_record_lea_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* push */
+    case 0x50 ... 0x57:
+    case 0x68:
+    case 0x6a:
+      /* push es */
+    case 0x06:
+      /* push cs */
+    case 0x0e:
+      /* push ss */
+    case 0x16:
+      /* push ds */
+    case 0x1e:
+      /* push fs */
+    case 0x0fa0:
+      /* push gs */
+    case 0x0fa8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop */
+    case 0x58 ... 0x5f:
+      ot = dflag + OT_WORD;
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (ot == OT_BYTE)
+	{
+	  opcode &= 0x3;
+	}
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pusha */
+    case 0x60:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 4)), (1 << (dflag + 4))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* popa */
+    case 0x61:
+      for (tmpu8 = I386_EAX_REGNUM; tmpu8 <= I386_EDI_REGNUM; tmpu8++)
+	{
+	  if (record_arch_list_add_reg (tmpu8))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* pop */
+    case 0x8f:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* enter */
+    case 0xc8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* leave */
+    case 0xc9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBP_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop es */
+    case 0x07:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ES_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop ss */
+    case 0x17:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_SS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop ds */
+    case 0x1f:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_DS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop fs */
+    case 0x0fa1:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_FS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* pop gs */
+    case 0x0fa9:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_GS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov */
+    case 0x88:
+    case 0x89:
+    case 0xc6:
+    case 0xc7:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod != 3)
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+      /* mov */
+    case 0x8a:
+    case 0x8b:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov seg */
+    case 0x8e:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      switch (reg)
+	{
+	case 0:
+	  tmpu8 = I386_ES_REGNUM;
+	  break;
+	case 2:
+	  tmpu8 = I386_SS_REGNUM;
+	  break;
+	case 3:
+	  tmpu8 = I386_DS_REGNUM;
+	  break;
+	case 4:
+	  tmpu8 = I386_FS_REGNUM;
+	  break;
+	case 5:
+	  tmpu8 = I386_GS_REGNUM;
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      if (record_arch_list_add_reg (tmpu8))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov seg */
+    case 0x8c:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg > 5)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  ot = OT_WORD;
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* movzbS */
+    case 0x0fb6:
+      /* movzwS */
+    case 0x0fb7:
+      /* movsbS */
+    case 0x0fbe:
+      /* movswS */
+    case 0x0fbf:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lea */
+    case 0x8d:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      ot = dflag;
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov EAX */
+    case 0xa0:
+    case 0xa1:
+      /* xlat */
+    case 0xd7:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov EAX */
+    case 0xa2:
+    case 0xa3:
+      {
+	uint32_t addr;
+
+	if ((opcode & 1) == 0)
+	  {
+	    ot = OT_BYTE;
+	  }
+	else
+	  {
+	    ot = dflag + OT_WORD;
+	  }
+	if (aflag)
+	  {
+	    if (target_read_memory (i386_record_pc, (gdb_byte *) & addr, 4))
+	      {
+		printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				   paddr_nz (i386_record_pc));
+		return (-1);
+	      }
+	    i386_record_pc += 4;
+	  }
+	else
+	  {
+	    if (target_read_memory (i386_record_pc, (gdb_byte *) & tmpu16, 4))
+	      {
+		printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+				   paddr_nz (i386_record_pc));
+		return (-1);
+	      }
+	    i386_record_pc += 2;
+	    addr = tmpu16;
+	  }
+	if (record_arch_list_add_mem (addr, 1 << ot))
+	  {
+	    return (-1);
+	  }
+      }
+      break;
+
+      /* mov R, Ib */
+    case 0xb0 ... 0xb7:
+      if (record_arch_list_add_reg ((opcode & 0x7) & 0x3))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* mov R, Iv */
+    case 0xb8 ... 0xbf:
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xchg R, EAX */
+    case 0x91 ... 0x97:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (opcode & 0x7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* xchg Ev, Gv */
+    case 0x86:
+    case 0x87:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod == 3)
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (ot == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* les Gv */
+    case 0xc4:
+      /* lds Gv */
+    case 0xc5:
+      /* lss Gv */
+    case 0x0fb2:
+      /* lfs Gv */
+    case 0x0fb4:
+      /* lgs Gv */
+    case 0x0fb5:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (opcode > 0xff)
+	    {
+	      i386_record_pc -= 3;
+	    }
+	  else
+	    {
+	      i386_record_pc -= 2;
+	    }
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+
+      switch (opcode)
+	{
+	  /* les Gv */
+	case 0xc4:
+	  tmpu8 = I386_ES_REGNUM;
+	  break;
+	  /* lds Gv */
+	case 0xc5:
+	  tmpu8 = I386_DS_REGNUM;
+	  break;
+	  /* lss Gv */
+	case 0x0fb2:
+	  tmpu8 = I386_SS_REGNUM;
+	  break;
+	  /* lfs Gv */
+	case 0x0fb4:
+	  tmpu8 = I386_FS_REGNUM;
+	  break;
+	  /* lgs Gv */
+	case 0x0fb5:
+	  tmpu8 = I386_GS_REGNUM;
+	  break;
+	}
+      if (record_arch_list_add_reg (tmpu8))
+	{
+	  return (-1);
+	}
+
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* shifts */
+    case 0xc0:
+    case 0xc1:
+    case 0xd0:
+    case 0xd1:
+    case 0xd2:
+    case 0xd3:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (mod != 3 && (opcode == 0xd2 || opcode == 0xd3))
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (ot == OT_BYTE)
+	    {
+	      rm &= 0x3;
+	    }
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0x0fa4:
+    case 0x0fa5:
+    case 0x0fac:
+    case 0x0fad:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* floats */
+      /* XXX */
+
+      /* string ops */
+      /* movsS */
+    case 0xa4:
+    case 0xa5:
+      /* stosS */
+    case 0xaa:
+    case 0xab:
+      /* insS */
+    case 0x6c:
+    case 0x6d:
+      {
+	uint32_t addr;
+
+	if ((opcode & 1) == 0)
+	  {
+	    ot = OT_BYTE;
+	  }
+	else
+	  {
+	    ot = dflag + OT_WORD;
+	  }
+	if (opcode == 0xa4 || opcode == 0xa5)
+	  {
+	    if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	      {
+		return (-1);
+	      }
+	  }
+	if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	  {
+	    return (-1);
+	  }
+
+	regcache_raw_read (record_regcache, I386_EDI_REGNUM,
+			   (gdb_byte *) & addr);
+	if (!aflag)
+	  {
+	    addr &= 0xffff;
+	    /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */
+	    printf_unfiltered (_
+			       ("record: cann't get the value of the segment register.\n"));
+	    return (-1);
+	  }
+
+	if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	  {
+	    uint32_t count;
+
+	    regcache_raw_read (record_regcache, I386_ECX_REGNUM,
+			       (gdb_byte *) & count);
+	    if (!aflag)
+	      {
+		count &= 0xffff;
+	      }
+
+	    regcache_raw_read (record_regcache, I386_EFLAGS_REGNUM,
+			       (gdb_byte *) & tmpu32);
+	    if ((tmpu32 >> 10) & 0x1)
+	      {
+		addr -= (count - 1) * (1 << ot);
+	      }
+
+	    if (record_arch_list_add_mem (addr, count * (1 << ot)))
+	      {
+		return (-1);
+	      }
+
+	    if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	      {
+		return (-1);
+	      }
+	  }
+	else
+	  {
+	    if (record_arch_list_add_mem (addr, 1 << ot))
+	      {
+		return (-1);
+	      }
+	  }
+      }
+      break;
+
+      /* lodsS */
+    case 0xac:
+    case 0xad:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* outsS */
+    case 0x6e:
+    case 0x6f:
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* scasS */
+    case 0xae:
+    case 0xaf:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* cmpsS */
+    case 0xa6:
+    case 0xa7:
+      if (record_arch_list_add_reg (I386_EDI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESI_REGNUM))
+	{
+	  return (-1);
+	}
+      if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))
+	{
+	  if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* port I/O */
+    case 0xe4:
+    case 0xe5:
+    case 0xec:
+    case 0xed:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0xe6:
+    case 0xe7:
+    case 0xee:
+    case 0xef:
+      break;
+
+      /* control */
+      /* ret im */
+    case 0xc2:
+      /* ret */
+    case 0xc3:
+      /* lret im */
+    case 0xca:
+      /* lret */
+    case 0xcb:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* iret */
+    case 0xcf:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* call im */
+    case 0xe8:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lcall im */
+    case 0x9a:
+      if (record_arch_list_add_reg (I386_CS_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 2)), (1 << (dflag + 2))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* jmp im */
+    case 0xe9:
+      /* ljmp im */
+    case 0xea:
+      /* jmp Jb */
+    case 0xeb:
+      /* jcc Jb */
+    case 0x70 ... 0x7f:
+      /* jcc Jv */
+    case 0x0f80 ... 0x0f8f:
+      break;
+
+      /* setcc Gv */
+    case 0x0f90 ... 0x0f9f:
+      ot = OT_BYTE;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod == 3)
+	{
+	  if (record_arch_list_add_reg (rm & 0x3))
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* cmov Gv, Ev */
+    case 0x0f40 ... 0x0f4f:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (dflag == OT_BYTE)
+	{
+	  reg &= 0x3;
+	}
+      if (record_arch_list_add_reg (reg & 0x3))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* flags */
+      /* pushf */
+    case 0x9c:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      regcache_raw_read (record_regcache, I386_ESP_REGNUM,
+			 (gdb_byte *) & tmpu32);
+      if (record_arch_list_add_mem
+	  ((CORE_ADDR) tmpu32 - (1 << (dflag + 1)), (1 << (dflag + 1))))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* popf */
+    case 0x9d:
+      if (record_arch_list_add_reg (I386_ESP_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* sahf */
+    case 0x9e:
+      /* cmc */
+    case 0xf5:
+      /* clc */
+    case 0xf8:
+      /* stc */
+    case 0xf9:
+      /* cld */
+    case 0xfc:
+      /* std */
+    case 0xfd:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lahf */
+    case 0x9f:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bit operations */
+      /* bt/bts/btr/btc Gv, im */
+    case 0x0fba:
+      /* bts */
+    case 0x0fab:
+      /* btr */
+    case 0x0fb3:
+      /* btc */
+    case 0x0fbb:
+      ot = dflag + OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (reg < 4)
+	{
+	  i386_record_pc -= 3;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      reg -= 4;
+      if (reg != 0)
+	{
+	  if (mod != 3)
+	    {
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bt Gv, Ev */
+    case 0x0fa3:
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bsf */
+    case 0x0fbc:
+      /* bsr */
+    case 0x0fbd:
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* bcd */
+      /* daa */
+    case 0x27:
+      /* das */
+    case 0x2f:
+      /* aaa */
+    case 0x37:
+      /* aas */
+    case 0x3f:
+      /* aam */
+    case 0xd4:
+      /* aad */
+    case 0xd5:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* misc */
+      /* nop */
+    case 0x90:
+      if (prefixes & PREFIX_LOCK)
+	{
+	  i386_record_pc -= 1;
+	  goto no_support;
+	}
+      break;
+
+      /* fwait */
+      /* XXX */
+    case 0x9b:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction fwait.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int3 */
+      /* XXX */
+    case 0xcc:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction int3.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* int */
+      /* XXX */
+    case 0xcd:
+      {
+	int ret;
+	if (target_read_memory (i386_record_pc, &tmpu8, 1))
+	  {
+	    printf_unfiltered (_("record: read memeory 0x%s error.\n"),
+			       paddr_nz (i386_record_pc));
+	    return (-1);
+	  }
+	i386_record_pc++;
+	if (tmpu8 != 0x80
+	    || gdbarch_tdep (gdbarch)->i386_intx80_record == NULL)
+	  {
+	    printf_unfiltered (_
+			       ("record: record and reverse function don't support instruction int 0x%02x.\n"),
+			       tmpu8);
+	    i386_record_pc -= 2;
+	    goto no_support;
+	  }
+	ret = gdbarch_tdep (gdbarch)->i386_intx80_record ();
+	if (ret)
+	  {
+	    return (ret);
+	  }
+      }
+      break;
+
+      /* into */
+      /* XXX */
+    case 0xce:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction into.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* cli */
+    case 0xfa:
+      /* sti */
+    case 0xfb:
+      break;
+
+      /* bound */
+    case 0x62:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction bound.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+      /* bswap reg */
+    case 0x0fc8 ... 0x0fcf:
+      if (record_arch_list_add_reg (opcode & 7))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* salc */
+    case 0xd6:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* loopnz */
+    case 0xe0:
+      /* loopz */
+    case 0xe1:
+      /* loop */
+    case 0xe2:
+      /* jecxz */
+    case 0xe3:
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* wrmsr */
+    case 0x0f30:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction wrmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdmsr */
+    case 0x0f32:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction rdmsr.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* rdtsc */
+    case 0x0f31:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction rdtsc.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* sysenter */
+    case 0x0f34:
+      {
+	int ret;
+	if (gdbarch_tdep (gdbarch)->i386_sysenter_record == NULL)
+	  {
+	    printf_unfiltered (_
+			       ("record: record and reverse function don't support instruction sysenter.\n"));
+	    i386_record_pc -= 2;
+	    goto no_support;
+	  }
+	ret = gdbarch_tdep (gdbarch)->i386_sysenter_record ();
+	if (ret)
+	  {
+	    return (ret);
+	  }
+      }
+      break;
+
+      /* sysexit */
+    case 0x0f35:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction sysexit.\n"));
+      i386_record_pc -= 2;
+      goto no_support;
+      break;
+
+      /* cpuid */
+    case 0x0fa2:
+      if (record_arch_list_add_reg (I386_EAX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_ECX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EDX_REGNUM))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EBX_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* hlt */
+    case 0xf4:
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support instruction hlt.\n"));
+      i386_record_pc -= 1;
+      goto no_support;
+      break;
+
+    case 0x0f00:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      switch (reg)
+	{
+	  /* sldt */
+	case 0:
+	  /* str */
+	case 1:
+	  if (mod == 3)
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      ot = OT_WORD;
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* lldt */
+	case 2:
+	  /* ltr */
+	case 3:
+	  break;
+	  /* verr */
+	case 4:
+	  /* verw */
+	case 5:
+	  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	    {
+	      return (-1);
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 3;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+    case 0x0f01:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      switch (reg)
+	{
+	  /* sgdt */
+	case 0:
+	  {
+	    uint32_t addr;
+
+	    if (mod == 3)
+	      {
+		i386_record_pc -= 3;
+		opcode = opcode << 8 | modrm;
+		goto no_support;
+	      }
+
+	    if (override)
+	      {
+		printf_unfiltered (_
+				   ("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"),
+				   paddr_nz (read_pc ()));
+	      }
+	    else
+	      {
+		if (i386_record_lea_modrm_addr (&addr))
+		  {
+		    return (-1);
+		  }
+		if (record_arch_list_add_mem (addr, 2))
+		  {
+		    return (-1);
+		  }
+		addr += 2;
+		if (record_arch_list_add_mem (addr, 4))
+		  {
+		    return (-1);
+		  }
+	      }
+	  }
+	  break;
+	case 1:
+	  if (mod == 3)
+	    {
+	      switch (rm)
+		{
+		  /* monitor */
+		case 0:
+		  break;
+		  /* mwait */
+		case 1:
+		  if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+		    {
+		      return (-1);
+		    }
+		  break;
+		default:
+		  i386_record_pc -= 3;
+		  opcode = opcode << 8 | modrm;
+		  goto no_support;
+		  break;
+		}
+	    }
+	  else
+	    {
+	      /* sidt */
+	      if (override)
+		{
+		  printf_unfiltered (_
+				     ("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"),
+				     paddr_nz (read_pc ()));
+		}
+	      else
+		{
+		  uint32_t addr;
+
+		  if (i386_record_lea_modrm_addr (&addr))
+		    {
+		      return (-1);
+		    }
+		  if (record_arch_list_add_mem (addr, 2))
+		    {
+		      return (-1);
+		    }
+		  addr += 2;
+		  if (record_arch_list_add_mem (addr, 4))
+		    {
+		      return (-1);
+		    }
+		}
+	    }
+	  break;
+	  /* lgdt */
+	case 2:
+	  /* lidt */
+	case 3:
+	  /* invlpg */
+	case 7:
+	default:
+	  if (mod == 3)
+	    {
+	      i386_record_pc -= 3;
+	      opcode = opcode << 8 | modrm;
+	      goto no_support;
+	    }
+	  break;
+	  /* smsw */
+	case 4:
+	  if (mod == 3)
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  else
+	    {
+	      ot = OT_WORD;
+	      if (i386_record_lea_modrm ())
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	  /* lmsw */
+	case 6:
+	  break;
+	}
+      break;
+
+      /* invd */
+    case 0x0f08:
+      /* wbinvd */
+    case 0x0f09:
+      break;
+
+      /* arpl */
+    case 0x63:
+      ot = dflag ? OT_LONG : OT_WORD;
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (mod != 3)
+	{
+	  if (i386_record_lea_modrm ())
+	    {
+	      return (-1);
+	    }
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+      /* lar */
+    case 0x0f02:
+      /* lsl */
+    case 0x0f03:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (reg))
+	{
+	  return (-1);
+	}
+      if (record_arch_list_add_reg (I386_EFLAGS_REGNUM))
+	{
+	  return (-1);
+	}
+      break;
+
+    case 0x0f18:
+      break;
+
+      /* nop (multi byte) */
+    case 0x0f19 ... 0x0f1f:
+      break;
+
+      /* mov reg, crN */
+    case 0x0f20:
+      /* mov crN, reg */
+    case 0x0f22:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if ((modrm & 0xc0) != 0xc0)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      switch (reg)
+	{
+	case 0:
+	case 2:
+	case 3:
+	case 4:
+	case 8:
+	  if (opcode & 2)
+	    {
+	    }
+	  else
+	    {
+	      if (record_arch_list_add_reg (rm))
+		{
+		  return (-1);
+		}
+	    }
+	  break;
+	default:
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* mov reg, drN */
+    case 0x0f21:
+      /* mov drN, reg */
+    case 0x0f23:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+      if ((modrm & 0xc0) != 0xc0 || reg == 4 || reg == 5 || reg >= 8)
+	{
+	  i386_record_pc -= 2;
+	  opcode = opcode << 8 | modrm;
+	  goto no_support;
+	}
+      if (opcode & 2)
+	{
+	}
+      else
+	{
+	  if (record_arch_list_add_reg (rm))
+	    {
+	      return (-1);
+	    }
+	}
+      break;
+
+      /* clts */
+    case 0x0f06:
+      break;
+
+      /* MMX/SSE/SSE2/PNI support */
+      /* XXX */
+
+    default:
+      if (opcode > 0xff)
+	{
+	  i386_record_pc -= 2;
+	}
+      else
+	{
+	  i386_record_pc -= 1;
+	}
+      goto no_support;
+      break;
+    }
+
+  if (!need_dasm)
+    {
+      if (record_arch_list_add_reg (I386_EIP_REGNUM))
+	{
+	  return (-1);
+	}
+    }
+  if (record_arch_list_add_end (need_dasm))
+    {
+      return (-1);
+    }
+
+  return (0);
+
+no_support:
+  printf_unfiltered (_
+		     ("record: record and reverse function don't support instruction 0x%02x at address 0x%s.\n"),
+		     (unsigned int) (opcode), paddr_nz (i386_record_pc));
+  return (-1);
+}
+
+
+static struct gdbarch *
+i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  struct gdbarch_tdep *tdep;
+  struct gdbarch *gdbarch;
+
+  /* If there is already a candidate, use it.  */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
+
+  /* Allocate space for the new architecture.  */
+  tdep = XCALLOC (1, struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
+
+  /* General-purpose registers.  */
+  tdep->gregset = NULL;
+  tdep->gregset_reg_offset = NULL;
+  tdep->gregset_num_regs = I386_NUM_GREGS;
+  tdep->sizeof_gregset = 0;
+
+  /* Floating-point registers.  */
+  tdep->fpregset = NULL;
+  tdep->sizeof_fpregset = I387_SIZEOF_FSAVE;
+
+  /* The default settings include the FPU registers, the MMX registers
+     and the SSE registers.  This can be overridden for a specific ABI
+     by adjusting the members `st0_regnum', `mm0_regnum' and
+     `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
+     will show up in the output of "info all-registers".  Ideally we
+     should try to autodetect whether they are available, such that we
+     can prevent "info all-registers" from displaying registers that
+     aren't available.
+
+     NOTE: kevinb/2003-07-13: ... if it's a choice between printing
+     [the SSE registers] always (even when they don't exist) or never
+     showing them to the user (even when they do exist), I prefer the
+     former over the latter.  */
+
+  tdep->st0_regnum = I386_ST0_REGNUM;
+
+  /* The MMX registers are implemented as pseudo-registers.  Put off
+     calculating the register number for %mm0 until we know the number
+     of raw registers.  */
+  tdep->mm0_regnum = 0;
+
+  /* I386_NUM_XREGS includes %mxcsr, so substract one.  */
+  tdep->num_xmm_regs = I386_NUM_XREGS - 1;
+
+  tdep->jb_pc_offset = -1;
+  tdep->struct_return = pcc_struct_return;
+  tdep->sigtramp_start = 0;
+  tdep->sigtramp_end = 0;
+  tdep->sigtramp_p = i386_sigtramp_p;
+  tdep->sigcontext_addr = NULL;
+  tdep->sc_reg_offset = NULL;
+  tdep->sc_pc_offset = -1;
+  tdep->sc_sp_offset = -1;
+
+  /* The format used for `long double' on almost all i386 targets is
+     the i387 extended floating-point format.  In fact, of all targets
+     in the GCC 2.95 tree, only OSF/1 does it different, and insists
+     on having a `long double' that's not `long' at all.  */
+  set_gdbarch_long_double_format (gdbarch, floatformats_i387_ext);
+
+  /* Although the i387 extended floating-point has only 80 significant
+     bits, a `long double' actually takes up 96, probably to enforce
+     alignment.  */
+  set_gdbarch_long_double_bit (gdbarch, 96);
+
+  /* The default ABI includes general-purpose registers, 
+     floating-point registers, and the SSE registers.  */
+  set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS);
+  set_gdbarch_register_name (gdbarch, i386_register_name);
+  set_gdbarch_register_type (gdbarch, i386_register_type);
+
+  /* Register numbers of various important registers.  */
+  set_gdbarch_sp_regnum (gdbarch, I386_ESP_REGNUM); /* %esp */
+  set_gdbarch_pc_regnum (gdbarch, I386_EIP_REGNUM); /* %eip */
+  set_gdbarch_ps_regnum (gdbarch, I386_EFLAGS_REGNUM); /* %eflags */
+  set_gdbarch_fp0_regnum (gdbarch, I386_ST0_REGNUM); /* %st(0) */
+
+  /* NOTE: kettenis/20040418: GCC does have two possible register
+     numbering schemes on the i386: dbx and SVR4.  These schemes
+     differ in how they number %ebp, %esp, %eflags, and the
+     floating-point registers, and are implemented by the arrays
+     dbx_register_map[] and svr4_dbx_register_map in
+     gcc/config/i386.c.  GCC also defines a third numbering scheme in
+     gcc/config/i386.c, which it designates as the "default" register
+     map used in 64bit mode.  This last register numbering scheme is
+     implemented in dbx64_register_map, and is used for AMD64; see
+     amd64-tdep.c.
+
+     Currently, each GCC i386 target always uses the same register
+     numbering scheme across all its supported debugging formats
+     i.e. SDB (COFF), stabs and DWARF 2.  This is because
+     gcc/sdbout.c, gcc/dbxout.c and gcc/dwarf2out.c all use the
+     DBX_REGISTER_NUMBER macro which is defined by each target's
+     respective config header in a manner independent of the requested
+     output debugging format.
+
+     This does not match the arrangement below, which presumes that
+     the SDB and stabs numbering schemes differ from the DWARF and
+     DWARF 2 ones.  The reason for this arrangement is that it is
+     likely to get the numbering scheme for the target's
+     default/native debug format right.  For targets where GCC is the
+     native compiler (FreeBSD, NetBSD, OpenBSD, GNU/Linux) or for
+     targets where the native toolchain uses a different numbering
+     scheme for a particular debug format (stabs-in-ELF on Solaris)
+     the defaults below will have to be overridden, like
+     i386_elf_init_abi() does.  */
+
+  /* Use the dbx register numbering scheme for stabs and COFF.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+  set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum);
+
+  /* Use the SVR4 register numbering scheme for DWARF and DWARF 2.  */
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
+
+  /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to
+     be in use on any of the supported i386 targets.  */
+
+  set_gdbarch_print_float_info (gdbarch, i387_print_float_info);
+
+  set_gdbarch_get_longjmp_target (gdbarch, i386_get_longjmp_target);
+
+  /* Call dummy code.  */
+  set_gdbarch_push_dummy_call (gdbarch, i386_push_dummy_call);
+
+  set_gdbarch_convert_register_p (gdbarch, i386_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch,  i386_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
+
+  set_gdbarch_return_value (gdbarch, i386_return_value);
+
+  set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+  set_gdbarch_breakpoint_from_pc (gdbarch, i386_breakpoint_from_pc);
+  set_gdbarch_decr_pc_after_break (gdbarch, 1);
+
+  set_gdbarch_frame_args_skip (gdbarch, 8);
+
+  /* Wire in the MMX registers.  */
   set_gdbarch_num_pseudo_regs (gdbarch, i386_num_mmx_regs);
   set_gdbarch_pseudo_register_read (gdbarch, i386_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, i386_pseudo_register_write);
@@ -2503,6 +5034,8 @@ i386_gdbarch_init (struct gdbarch_info i
   if (tdep->mm0_regnum == 0)
     tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
 
+  set_gdbarch_record (gdbarch, i386_record);
+
   return gdbarch;
 }
 
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -106,6 +106,9 @@ struct gdbarch_tdep
   /* ISA-specific data types.  */
   struct type *i386_mmx_type;
   struct type *i386_sse_type;
+
+  int (*i386_intx80_record) (void);
+  int (*i386_sysenter_record) (void);
 };
 
 /* Floating-point registers.  */
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -49,6 +49,8 @@
 #include "target-descriptions.h"
 #include "user-regs.h"
 
+#include "record.h"
+
 /* Functions exported for general use, in inferior.h: */
 
 void all_registers_info (char *, int);
@@ -189,6 +191,12 @@ CORE_ADDR step_range_end;	/* Exclusive *
 
 struct frame_id step_frame_id;
 
+/* Prev stack frame address of "step_frame_id".
+   When GDB is in the reverse debug mode, it is used to make sure if inferior return to
+   the prev function. */
+
+struct frame_id step_prev_frame_id;
+
 enum step_over_calls_kind step_over_calls;
 
 /* If stepping, nonzero means step count is > 1
@@ -738,6 +746,19 @@ step_1 (int skip_subroutines, int single
 	    error (_("No current frame"));
 	  step_frame_id = get_frame_id (frame);
 
+	  if (gdb_is_reverse)
+	    {
+	      frame = get_prev_frame (frame);
+	      if (frame)
+	        {
+		  step_prev_frame_id = get_frame_id (frame);
+	        }
+	      else
+	        {
+		  step_prev_frame_id = null_frame_id;
+	        }
+	    }
+
 	  if (!single_inst)
 	    {
 	      find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
@@ -837,6 +858,19 @@ step_once (int skip_subroutines, int sin
 	error (_("No current frame"));
       step_frame_id = get_frame_id (frame);
 
+      if (gdb_is_reverse)
+        {
+          frame = get_prev_frame (frame);
+          if (frame)
+            {
+              step_prev_frame_id = get_frame_id (frame);
+            }
+          else
+            {
+              step_prev_frame_id = null_frame_id;
+            }
+        }
+
       if (!single_inst)
 	{
 	  find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
@@ -1089,6 +1123,19 @@ until_next_command (int from_tty)
   step_over_calls = STEP_OVER_ALL;
   step_frame_id = get_frame_id (frame);
 
+  if (gdb_is_reverse)
+    {
+      frame = get_prev_frame (frame);
+      if (frame)
+        {
+          step_prev_frame_id = get_frame_id (frame);
+        }
+      else
+        {
+	  step_prev_frame_id = null_frame_id;
+        }
+    }
+
   step_multi = 0;		/* Only one call to proceed */
 
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -318,6 +318,12 @@ extern CORE_ADDR step_range_end;	/* Excl
 
 extern struct frame_id step_frame_id;
 
+/* Prev stack frame address of "step_frame_id".
+   When GDB is in the reverse debug mode, it is used to make sure if inferior return to
+   the prev function. */
+
+extern struct frame_id step_prev_frame_id;
+
 /* 1 means step over all subroutine calls.
    -1 means step over calls to undebuggable functions.  */
 
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -49,6 +49,12 @@
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 
+#include "record.h"
+
+/* When the record function want inferior step before call "keep_going",
+   "record_resume_step" will be set to 1. After that, it will be set back to 0. */
+static int record_resume_step = 0;
+
 /* Prototypes for local functions */
 
 static void signals_info (char *, int);
@@ -518,6 +524,21 @@ resume (int step, enum target_signal sig
     fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d)\n",
 			step, sig);
 
+  if (gdb_is_recording)
+    {
+      if (record_list && (record_list->next || gdb_is_reverse))
+        {
+          discard_cleanups (old_cleanups);
+          record_wait_step = step;
+          return;
+        }
+      else
+        {
+          step = 1;
+          record_message (current_gdbarch);
+        }
+    }
+
   /* FIXME: calling breakpoint_here_p (read_pc ()) three times! */
 
 
@@ -1026,10 +1047,18 @@ wait_for_inferior (int treat_exec_as_sig
 
   while (1)
     {
-      if (deprecated_target_wait_hook)
-	ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
+      if (record_list && (record_list->next || gdb_is_reverse))
+	{
+	  ecs->ptid = record_wait (current_gdbarch, ecs->waiton_ptid, ecs->wp);
+	}
       else
-	ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
+	{
+	  if (deprecated_target_wait_hook)
+	    ecs->ptid =
+	      deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
+	  else
+	    ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
+	}
 
       if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
         {
@@ -2004,10 +2033,19 @@ handle_inferior_event (struct execution_
          SPARC.  */
 
       if (stop_signal == TARGET_SIGNAL_TRAP)
-	ecs->random_signal
-	  = !(bpstat_explains_signal (stop_bpstat)
-	      || stepping_over_breakpoint
-	      || (step_range_end && step_resume_breakpoint == NULL));
+	{
+	  if (gdb_is_reverse || gdb_is_recording)
+	    {
+	      ecs->random_signal = 0;
+	    }
+	  else
+	    {
+	      ecs->random_signal
+		= !(bpstat_explains_signal (stop_bpstat)
+		    || stepping_over_breakpoint
+		    || (step_range_end && step_resume_breakpoint == NULL));
+	    }
+	}
       else
 	{
 	  ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
@@ -2489,6 +2527,15 @@ process_event_stop_test:
 	  /* We're doing a "next", set a breakpoint at callee's return
 	     address (the address at which the caller will
 	     resume).  */
+
+	  if (gdb_is_reverse || gdb_is_recording)
+	    {
+	      record_resume_step = 1;
+	      keep_going (ecs);
+	      record_resume_step = 0;
+	      return;
+	    }
+
 	  insert_step_resume_breakpoint_at_caller (get_current_frame ());
 	  keep_going (ecs);
 	  return;
@@ -2551,6 +2598,15 @@ process_event_stop_test:
 	  return;
 	}
 
+	if ((gdb_is_reverse || gdb_is_recording)
+	    && step_over_calls == STEP_OVER_UNDEBUGGABLE)
+	  {
+	    record_resume_step = 1;
+	    keep_going (ecs);
+	    record_resume_step = 0;
+	    return;
+	  }
+
       /* Set a breakpoint at callee's return address (the address at
          which the caller will resume).  */
       insert_step_resume_breakpoint_at_caller (get_current_frame ());
@@ -2605,6 +2661,14 @@ process_event_stop_test:
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
 
+      if (gdb_is_reverse || gdb_is_recording)
+	{
+	  record_resume_step = 1;
+	  keep_going (ecs);
+	  record_resume_step = 0;
+	  return;
+	}
+
       /* The inferior just stepped into, or returned to, an
          undebuggable function (where there is no debugging information
          and no line number corresponding to the address where the
@@ -2654,15 +2718,58 @@ process_event_stop_test:
          or can this happen as a result of a return or longjmp?).  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
+
+      if ((step_over_calls == STEP_OVER_ALL && gdb_is_reverse)
+	  || gdb_is_recording)
+	{
+	  record_resume_step = 1;
+	  keep_going (ecs);
+	  record_resume_step = 0;
+	  return;
+	}
+
       stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
     }
 
-  if ((stop_pc == ecs->sal.pc)
-      && (ecs->current_line != ecs->sal.line
-	  || ecs->current_symtab != ecs->sal.symtab))
+    if (gdb_is_reverse
+	&& frame_id_eq (get_frame_id (get_current_frame ()),
+			step_prev_frame_id))
+      {
+	if (debug_infrun)
+	  {
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: return to the prev function\n");
+	  }
+	stop_step = 1;
+	print_stop_reason (END_STEPPING_RANGE, 0);
+	stop_stepping (ecs);
+	return;
+      }
+
+    if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id)
+	&& (gdb_is_reverse || gdb_is_recording))
+      {
+	if ((stop_pc != ecs->sal.pc && gdb_is_reverse)
+	    || (step_over_calls == STEP_OVER_ALL && gdb_is_recording))
+	  {
+	    if (debug_infrun)
+	      fprintf_unfiltered (gdb_stdlog,
+				  "infrun: maybe stepped into subroutine\n");
+	    record_resume_step = 1;
+	    keep_going (ecs);
+	    record_resume_step = 0;
+	    return;
+	  }
+      }
+
+    if (((stop_pc == ecs->sal.pc && !gdb_is_reverse)
+	 || (stop_pc >= ecs->sal.pc && stop_pc < ecs->sal.end
+	     && gdb_is_reverse)) && (ecs->current_line != ecs->sal.line
+				     || ecs->current_symtab !=
+				     ecs->sal.symtab))
     {
       /* We are at the start of a different line.  So stop.  Note that
          we don't stop if we step into the middle of a different line.
@@ -2670,6 +2777,7 @@ process_event_stop_test:
          better.  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
+
       stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
@@ -2730,7 +2838,7 @@ currently_stepping (struct execution_con
 	   && ((step_range_end && step_resume_breakpoint == NULL)
 	       || stepping_over_breakpoint))
 	  || ecs->stepping_through_solib_after_catch
-	  || bpstat_should_step ());
+	  || bpstat_should_step () || record_resume_step);
 }
 
 /* Subroutine call with source code we should not step over.  Do step
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -633,7 +633,8 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	user-regs.c \
 	valarith.c valops.c valprint.c value.c varobj.c vec.c \
 	wrapper.c \
-	xml-tdesc.c xml-support.c
+	xml-tdesc.c xml-support.c \
+	record.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -1072,7 +1073,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	tramp-frame.o \
 	solib.o solib-null.o \
 	prologue-value.o memory-map.o xml-support.o \
-	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+	record.o
 
 TSOBS = inflow.o
 
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -58,6 +58,9 @@
 #include "dwarf2-frame.h"
 #include "user-regs.h"
 
+#include "record.h"
+#include <stdint.h>
+
 static const struct objfile_data *mips_pdr_data;
 
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
@@ -5213,6 +5216,734 @@ value_of_mips_user_reg (struct frame_inf
   return value_of_register (*reg_p, frame);
 }
 
+/* When "record_delay_slot" is true (mean that the prev instruction has delay
+   slot), GDB  need to deal with instrction in the delay slot that address is
+   "mips_delay_slot_addr" and the instruction in target of delay slot
+   instruction that address is "mips_target_addr". */
+static CORE_ADDR mips_delay_slot_addr;
+static CORE_ADDR mips_target_addr;
+
+/* Record the value of the memory that willbe changed in current 32 bits instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+mips_record_32 (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  uint32_t insn = (uint32_t) mips_fetch_instruction (pc);
+  uint32_t opcode;
+  const struct mips_regnum *regnum = mips_regnum (gdbarch);
+  int add_pc = 1;
+  uint32_t tmpu32;
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "record: mips_record_32 insn = 0x%08x\n",
+			  (unsigned int) insn);
+    }
+
+  opcode = insn >> 26;
+  switch (opcode)
+    {
+    case 0x00:
+      switch ((insn >> 0) & 0x3f)
+	{
+	  /* sll */
+	case 0x00:
+	  /* srl */
+	case 0x02:
+	  /* sra */
+	case 0x03:
+	  /* sllv */
+	case 0x04:
+	  /* srlv */
+	case 0x06:
+	  /* srav */
+	case 0x07:
+	  /* movz */
+	case 0x0a:
+	  /* movn */
+	case 0x0b:
+	  /* mfhi */
+	case 0x10:
+	  /* mflo */
+	case 0x12:
+	  /* add */
+	case 0x20:
+	  /* addu */
+	case 0x21:
+	  /* sub */
+	case 0x22:
+	  /* subu */
+	case 0x23:
+	  /* and */
+	case 0x24:
+	  /* or */
+	case 0x25:
+	  /* xor */
+	case 0x26:
+	  /* nor */
+	case 0x27:
+	  /* slt */
+	case 0x2a:
+	  /* sltu */
+	case 0x2b:
+	  goto set_rd;
+	  break;
+	  /* jr */
+	case 0x08:
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & mips_target_addr);
+	  goto set_delay_slot_pc;
+	  break;
+	  /* jalr */
+	case 0x09:
+	  {
+	    uint32_t rd = (insn >> 11) & 0x1f;
+	    if (rd != 0)
+	      {
+		if (record_arch_list_add_reg (rd))
+		  {
+		    return (-1);
+		  }
+	      }
+	    regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			       (gdb_byte *) & mips_target_addr);
+	    goto set_delay_slot_pc;
+	  }
+	  break;
+	  /* sync */
+	case 0x0f:
+	  break;
+	  /* mthi */
+	case 0x11:
+	  if (record_arch_list_add_reg (regnum->hi))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* mtlo */
+	case 0x13:
+	  if (record_arch_list_add_reg (regnum->lo))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* mult */
+	case 0x18:
+	  /* multu */
+	case 0x19:
+	  /* div */
+	case 0x1a:
+	  /* divu */
+	case 0x1b:
+	  goto set_hi_lo;
+	  break;
+	default:
+	  goto no_support;
+	  break;
+	}
+      break;
+
+    case 0x01:
+      switch ((insn >> 16) & 0x1f)
+	{
+	  /* bltz */
+	case 0x00:
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 < 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  break;
+	  /* bgez */
+	case 0x01:
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 >= 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  break;
+	  /* bltzl */
+	case 0x02:
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 < 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  else
+	    {
+	      goto set_pc;
+	    }
+	  break;
+	  /* bgezl */
+	case 0x03:
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 >= 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  else
+	    {
+	      goto set_pc;
+	    }
+	  break;
+	  /* bltzal */
+	case 0x10:
+	  if (record_arch_list_add_reg (31))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 < 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  break;
+	  /* bgezal */
+	case 0x11:
+	  if (record_arch_list_add_reg (31))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 >= 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  break;
+	  /* bltzall */
+	case 0x12:
+	  if (record_arch_list_add_reg (31))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 < 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  else
+	    {
+	      goto set_pc;
+	    }
+	  break;
+	  /* bgezall */
+	case 0x13:
+	  if (record_arch_list_add_reg (31))
+	    {
+	      return (-1);
+	    }
+	  regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			     (gdb_byte *) & tmpu32);
+	  if (tmpu32 >= 0)
+	    {
+	      goto set_imm_delay_slot_pc;
+	    }
+	  else
+	    {
+	      goto set_pc;
+	    }
+	  break;
+	default:
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* j */
+    case 0x02:
+      mips_target_addr =
+	(pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2);
+      goto set_delay_slot_pc;
+      break;
+
+      /* beq */
+    case 0x04:
+      {
+	uint32_t tmp;
+	regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	  (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, (insn >> 16) & 0x1f),
+	  (gdb_byte *) & tmp);
+	if (tmpu32 == tmp)
+	  {
+	    goto set_imm_delay_slot_pc;
+	  }
+      }
+      break;
+
+      /* bne */
+    case 0x05:
+      {
+	uint32_t tmp;
+	regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	  (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, (insn >> 16) & 0x1f),
+	  (gdb_byte *) & tmp);
+	if (tmpu32 != tmp)
+	  {
+	    goto set_imm_delay_slot_pc;
+	  }
+      }
+      break;
+
+      /* blez */
+    case 0x06:
+      regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	(gdb_byte *) & tmpu32);
+      if (tmpu32 <= 0)
+	{
+	  goto set_imm_delay_slot_pc;
+	}
+      break;
+
+      /* bgtz */
+    case 0x07:
+      regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	(gdb_byte *) & tmpu32);
+      if (tmpu32 > 0)
+	{
+	  goto set_imm_delay_slot_pc;
+	}
+      break;
+
+      /* beql */
+    case 0x14:
+      {
+	uint32_t tmp;
+	regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	  (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, (insn >> 16) & 0x1f),
+	  (gdb_byte *) & tmp);
+	if (tmpu32 == tmp)
+	  {
+	    goto set_imm_delay_slot_pc;
+	  }
+	else
+	  {
+	    goto set_pc;
+	  }
+      }
+      break;
+
+      /* bnel */
+    case 0x15:
+      {
+	uint32_t tmp;
+	regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	  (gdb_byte *) & tmpu32);
+	regcache_raw_read (record_regcache, (insn >> 16) & 0x1f),
+	  (gdb_byte *) & tmp);
+	if (tmpu32 == tmp)
+	  {
+	    goto set_imm_delay_slot_pc;
+	  }
+	else
+	  {
+	    goto set_pc;
+	  }
+      }
+      break;
+
+      /* blezl */
+    case 0x16:
+      regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	(gdb_byte *) & tmpu32);
+      if (tmpu32 <= 0)
+	{
+	  goto set_imm_delay_slot_pc;
+	}
+      else
+	{
+	  goto set_pc;
+	}
+      break;
+
+      /* bgtzl */
+    case 0x17:
+      regcache_raw_read (record_regcache, (insn >> 21) & 0x1f),
+	(gdb_byte *) & tmpu32);
+      if (tmpu32 > 0)
+	{
+	  goto set_imm_delay_slot_pc;
+	}
+      else
+	{
+	  goto set_pc;
+	}
+      break;
+
+      /* jal */
+    case 0x03:
+      if (record_arch_list_add_reg (31))
+	{
+	  return (-1);
+	}
+      mips_target_addr =
+	(pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2);
+      goto set_delay_slot_pc;
+      break;
+
+      /* jalx */
+    case 0x1d:
+      goto no_support;
+      break;
+
+      /* addi */
+    case 0x08:
+      /* addiu */
+    case 0x09:
+      /* slti */
+    case 0x0a:
+      /* sltiu */
+    case 0x0b:
+      /* andi */
+    case 0x0c:
+      /* ori */
+    case 0x0d:
+      /* xori */
+    case 0x0e:
+      /* lui */
+    case 0x0f:
+      goto set_rt;
+      break;
+
+      /* COP0 */
+    case 0x10:
+      if ((insn >> 25) & 0x1)
+	{
+	  switch ((insn >> 0) & 0x3f)
+	    {
+	      /* eret */
+	    case 0x18:
+	      goto set_pc;
+	      break;
+	    default:
+	      goto no_support;
+	      break;
+	    }
+	}
+      else
+	{
+	  switch ((insn >> 21) & 0x1f)
+	    {
+	      /* mfc0 */
+	    case 0x00:
+	      goto set_rt;
+	      break;
+	      /* mtc0 */
+	    case 0x04:
+	      {
+		switch ((insn >> 11) & 0x1f)
+		  {
+		  case 13:
+		    /* Cause */
+		    if (record_arch_list_add_reg (regnum->cause))
+		      {
+			return (-1);
+		      }
+		  case 8:
+		    /* badvaddr */
+		    if (record_arch_list_add_reg (regnum->badvaddr))
+		      {
+			return (-1);
+		      }
+		  }
+	      }
+	      break;
+	    default:
+	      goto no_support;
+	      break;
+	    }
+	}
+      break;
+
+    case 0x1c:
+      switch ((insn >> 0) & 0x3f)
+	{
+	  /* madd */
+	case 0x00:
+	  /* maddu */
+	case 0x01:
+	  /* msub */
+	case 0x04:
+	  /* msubu */
+	case 0x05:
+	  goto set_hi_lo;
+	  break;
+	  /* mul */
+	case 0x02:
+	  {
+	    uint32_t rd = (insn >> 11) & 0x1f;
+	    if (rd != 0)
+	      {
+		if (record_arch_list_add_reg (rd))
+		  {
+		    return (-1);
+		  }
+	      }
+	    goto set_hi_lo;
+	  }
+	  break;
+	  /* clo */
+	case 0x21:
+	  /* clz */
+	case 0x20:
+	  goto set_rd;
+	  break;
+	default:
+	  goto no_support;
+	  break;
+	}
+      break;
+
+      /* lb */
+    case 0x20:
+      /* lh */
+    case 0x21:
+      /* lwl */
+    case 0x22:
+      /* lw */
+    case 0x23:
+      /* lbu */
+    case 0x24:
+      /* lhu */
+    case 0x25:
+      /* lwr */
+    case 0x26:
+      /* ll */
+    case 0x30:
+      goto set_rt;
+      break;
+
+      /* sb */
+    case 0x28:
+      /* sh */
+    case 0x29:
+      /* swl */
+    case 0x2a:
+      /* sw */
+    case 0x2b:
+      /* swr */
+    case 0x2e:
+      /* sc */
+    case 0x38:
+      {
+	uint32_t addr;
+
+	/* addr */
+	/* base */
+	regcache_raw_read (record_regcache, (insn >> 21) & 0x1f,
+			   (gdb_byte *) & addr);
+	/* offset */
+	addr += (insn >> 0) & 0xffff;
+
+	switch (opcode)
+	  {
+	    /* sb */
+	  case 0x28:
+	    if (record_arch_list_add_mem (addr, 1))
+	      {
+		return (-1);
+	      }
+	    break;
+	    /* sh */
+	  case 0x29:
+	    if (record_arch_list_add_mem (addr, 2))
+	      {
+		return (-1);
+	      }
+	    break;
+	    /* swl */
+	  case 0x2a:
+	    /* swr */
+	  case 0x2e:
+	    if (record_arch_list_add_mem (addr & 0xffffff00, 2))
+	      {
+		return (-1);
+	      }
+	    break;
+	    /* sw */
+	  case 0x2b:
+	    if (record_arch_list_add_mem (addr, 4))
+	      {
+		return (-1);
+	      }
+	    break;
+	    /* sc */
+	  case 0x38:
+	    if (record_arch_list_add_mem (addr, 4))
+	      {
+		return (-1);
+	      }
+	    goto set_rt;
+	    break;
+	  }
+      }
+      break;
+      /* pref */
+    case 0x33:
+      break;
+
+    default:
+      goto no_support;
+      break;
+    }
+
+out:
+  if (record_delay_slot)
+    {
+      if (add_pc)
+	{
+	  if (record_arch_list_add_reg (regnum->pc))
+	    {
+	      return (-1);
+	    }
+	  add_pc = 0;
+	}
+    }
+  if (record_arch_list_add_end (add_pc))
+    {
+      return (-1);
+    }
+  return (0);
+
+no_support:
+  printf_unfiltered (_
+		     ("record: record and reverse function don't support 32 bits instruction 0x%08x.\n"),
+		     (unsigned int) insn);
+  return (-1);
+
+set_rd:
+  {
+    uint32_t rd = (insn >> 11) & 0x1f;
+    if (rd != 0)
+      {
+	if (record_arch_list_add_reg (rd))
+	  {
+	    return (-1);
+	  }
+      }
+  }
+  goto out;
+
+set_rt:
+  {
+    uint32_t rt = (insn >> 16) & 0x1f;
+    if (rt != 0)
+      {
+	if (record_arch_list_add_reg (rt))
+	  {
+	    return (-1);
+	  }
+      }
+  }
+  goto out;
+
+set_imm_delay_slot_pc:
+  {
+    uint32_t imm = (insn >> 0) & 0xffff;
+    if (imm >> 15)
+      {
+	imm |= 0xffff0000;
+      }
+    imm <<= 2;
+    mips_target_addr = pc + 4 + imm;
+  }
+  goto set_delay_slot_pc;
+
+set_delay_slot_pc:
+  mips_delay_slot_addr = pc + 4;
+  record_delay_slot++;
+  goto set_pc;
+
+set_pc:
+  if (record_arch_list_add_reg (regnum->pc))
+    {
+      return (-1);
+    }
+  add_pc = 0;
+  goto out;
+
+set_hi_lo:
+  if (record_arch_list_add_reg (regnum->hi))
+    {
+      return (-1);
+    }
+  if (record_arch_list_add_reg (regnum->lo))
+    {
+      return (-1);
+    }
+  goto out;
+}
+
+/* Record the value of the memory that willbe changed in current instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int mips_record (struct gdbarch *gdbarch)
+{
+  CORE_ADDR pc = read_pc ();
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: mips_record pc = 0x%s\n",
+			  paddr_nz (pc));
+    }
+
+  if (mips_pc_is_mips16 (pc))
+    {
+      printf_unfiltered (_
+			 ("record: record and reverse function don't support mips16.\n"));
+      return (-1);
+    }
+
+  if (record_delay_slot)
+    {
+      if (mips_record_32 (mips_delay_slot_addr))
+	{
+	  return (-1);
+	}
+      if (mips_record_32 (mips_target_addr))
+	{
+	  return (-1);
+	}
+      record_delay_slot--;
+    }
+  return (mips_record_32 (pc));
+}
+
+static void mips_record_dasm (struct gdbarch *gdbarch)
+{
+  const struct mips_regnum *regnum;
+  ULONGEST pc;
+
+  if (mips_pc_is_mips16 (read_pc ()))
+    {
+      error (_
+	     ("record: record and reverse function don't support mips16.\n"));
+    }
+
+  regnum = mips_regnum (gdbarch);
+  regcache_cooked_read_unsigned (record_regcache, regnum->pc, &pc);
+  if (gdb_is_reverse)
+    {
+      pc -= 4;
+    }
+  else
+    {
+      pc += 4;
+    }
+  regcache_cooked_write_unsigned (record_regcache, regnum->pc, pc);
+}
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -5877,6 +6608,9 @@ mips_gdbarch_init (struct gdbarch_info i
     user_reg_add (gdbarch, mips_register_aliases[i].name,
 		  value_of_mips_user_reg, &mips_register_aliases[i].regnum);
 
+  set_gdbarch_record (gdbarch, mips_record);
+  set_gdbarch_record_dasm (gdbarch, mips_record_dasm);
+
   return gdbarch;
 }
 
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -0,0 +1,606 @@
+/* Record v0.1.2 for GDB, the GNU debugger.
+   Written by Hui Zhu <teawater@gmail.com>
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+/* Before the inferior resume, if the record function is open and inferior will
+   really execute (will not call "record_wait"), the GDB will call
+   function "record_message" to record the values of registrs and memory that
+   will be changed in next instrution to "record_list".
+   When GDB is in reverse debug mode and inferior is not in the begin of 
+   "record_list" or GDB is in normail deubg mode and inferior is not in the
+   end of "record_list", GDB will call this function instead "target_wait". In
+   this status, function "resume" will directly return. Then inferior will
+   instead execute to call "record_wait".
+   "record_wait" will set the running message in "record_list" to inferior.
+   Then the registers and memory of  inferior will change back to before. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "target.h"
+#include "exceptions.h"
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include "regcache.h"
+#include <ctype.h>
+#include <stdint.h>
+#include "mips-tdep.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/file.h>
+#include "frame-unwind.h"
+#include "gdbthread.h"
+#include "exceptions.h"
+#include "infcall.h"
+#include "source.h"
+#include "top.h"
+#include "record.h"
+
+#define RECORD_REC_PROMPT	"(rec) "
+#define RECORD_REV_PROMPT	"(rev) "
+
+extern struct breakpoint *breakpoint_chain;
+
+record_t *record_list = NULL;
+record_t *record_arch_list_head = NULL;
+record_t *record_arch_list_tail = NULL;
+unsigned int gdb_is_recording = 0;
+int gdb_is_reverse = 0;
+int debug_record = 0;
+int record_wait_step = 0;
+int record_delay_slot = 0;
+static sigset_t record_maskall;
+static int record_get_sig = 0;
+struct regcache *record_regcache;
+static char record_gdb_prompt[20];
+
+static void
+show_debug_record (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Record debugging is %s.\n"), value);
+}
+
+static void
+record_list_release (record_t * rec)
+{
+  record_t *tmp;
+
+  while (rec)
+    {
+      tmp = rec;
+      rec = rec->prev;
+      xfree (tmp);
+    }
+}
+
+/* Before inferior step (When GDB record the running message, inferior only can
+   step.), GDB will call this function to record the values to "record_list".
+   This function will call "gdbarch_record" to record the running message of
+   inferior and set them to "record_arch_list". And add it to "record_list". */
+void
+record_message (struct gdbarch *gdbarch)
+{
+  int ret;
+
+  record_arch_list_head = NULL;
+  record_arch_list_tail = NULL;
+  record_regcache = get_current_regcache ();
+
+  ret = gdbarch_record (gdbarch);
+  if (ret > 0)
+    {
+      record_list_release (record_arch_list_tail);
+      error (_("record: record pause the program."));
+    }
+  if (ret < 0)
+    {
+      record_delay_slot = 0;
+      record_list_release (record_arch_list_tail);
+      error (_("record: record message error."));
+    }
+
+  if (record_list)
+    {
+      record_list->next = record_arch_list_head;
+      record_arch_list_head->prev = record_list;
+      record_list = record_arch_list_tail;
+    }
+  else
+    {
+      record_list = record_arch_list_tail;
+    }
+}
+
+/* Add a record_t to "record_arch_list". */
+static void
+record_arch_list_add (record_t * rec)
+{
+  if (record_arch_list_tail)
+    {
+      record_arch_list_tail->next = rec;
+      rec->prev = record_arch_list_tail;
+      record_arch_list_tail = rec;
+    }
+  else
+    {
+      record_arch_list_head = rec;
+      record_arch_list_tail = rec;
+    }
+}
+
+/* Record the value of a register("num") to "record_arch_list". */
+int
+record_arch_list_add_reg (int num)
+{
+  record_t *rec;
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "record: add reg num = %d to arch list.\n", num);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  if (!rec)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+      return (-1);
+    }
+  rec->u.reg.val = (gdb_byte *) xmalloc (MAX_REGISTER_SIZE);
+  if (!rec->u.reg.val)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+      xfree (rec);
+      return (-1);
+    }
+  rec->prev = NULL;
+  rec->next = NULL;
+  rec->type = record_reg;
+  rec->u.reg.num = num;
+
+  regcache_raw_read (record_regcache, num, rec->u.reg.val);
+
+  record_arch_list_add (rec);
+
+  return (0);
+}
+
+/* Record the value of a part of memroy that address is "addr" and length is
+   "len" to "record_arch_list". */
+int
+record_arch_list_add_mem (CORE_ADDR addr, int len)
+{
+  record_t *rec;
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "record: add mem addr = 0x%s len = %d to arch list.\n",
+			  paddr_nz (addr), len);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  if (!rec)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+      return (-1);
+    }
+  rec->u.mem.val = (gdb_byte *) xmalloc (len);
+  if (!rec->u.mem.val)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+      xfree (rec);
+      return (-1);
+    }
+  rec->prev = NULL;
+  rec->next = NULL;
+  rec->type = record_mem;
+  rec->u.mem.addr = addr;
+  rec->u.mem.len = len;
+
+  if (target_read_memory (addr, rec->u.mem.val, len))
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "record: read memory addr = 0x%s len = %d error.\n",
+			  paddr_nz (addr), len);
+      xfree (rec->u.mem.val);
+      xfree (rec);
+      return (-1);
+    }
+
+  record_arch_list_add (rec);
+
+  return (0);
+}
+
+/* Add a "record_end" type record_t to "record_arch_list". */
+int
+record_arch_list_add_end (int need_dasm)
+{
+  record_t *rec;
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "record: add end need_dasm = %d to arch list.\n",
+			  need_dasm);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  if (!rec)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+      return (-1);
+    }
+  rec->prev = NULL;
+  rec->next = NULL;
+  rec->type = record_end;
+
+  rec->u.need_dasm = need_dasm;
+
+  record_arch_list_add (rec);
+
+  return (0);
+}
+
+static void
+record_sig_handler (int signo)
+{
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: get a signal\n");
+    }
+  record_wait_step = 1;
+  record_get_sig = 1;
+}
+
+/* When GDB is in reverse debug mode and inferior is not in the begin of 
+   "record_list" or GDB is in normail deubg mode and inferior is not in the
+   end of "record_list", GDB will call this function instead "target_wait". In
+   this status, function "resume" will directly return. Then inferior will
+   instead execute to call "record_wait".
+   "record_wait" will set the running message in "record_list" to inferior.
+   Then the registers and memory of  inferior will change back to before. */
+ptid_t
+record_wait (struct gdbarch *gdbarch, ptid_t ptid, struct target_waitstatus *status)
+{
+  struct sigaction act, old_act;
+  static int state = 0;		/* 0 normal 1 to the end 2 to the begin */
+  int con = 1;
+  int insn_end = 0;
+  int need_dasm = 0;
+  struct regcache *regcache = get_current_regcache ();
+
+  if (debug_record)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: record_wait step = %d\n",
+			  record_wait_step);
+    }
+
+  record_get_sig = 0;
+  act.sa_handler = record_sig_handler;
+  act.sa_mask = record_maskall;
+  act.sa_flags = SA_RESTART;
+  if (sigaction (SIGINT, &act, &old_act))
+    {
+      perror_with_name (_("sigaction"));
+    }
+
+  do
+    {
+      /* check state */
+      if ((gdb_is_reverse && !record_list->prev && state == 2)
+	  || (!gdb_is_reverse && !record_list->next && state == 1))
+	{
+	  if (state == 1)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: running to the end of record list.\n");
+	    }
+	  else if (state == 2)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: running to the begin of record list.\n");
+	    }
+	  stop_soon = STOP_QUIETLY;
+	  break;
+	}
+      state = 0;
+
+      /* set register and memory according to record_list */
+      if (record_list->type == record_reg)
+	{
+	  /* reg */
+	  gdb_byte reg[MAX_REGISTER_SIZE];
+	  if (debug_record)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: record_list reg num = %d to arch list.\n",
+				  record_list->u.reg.num);
+	    }
+	  regcache_cooked_read (regcache, record_list->u.reg.num, reg);
+	  regcache_cooked_write (regcache, record_list->u.reg.num,
+				 record_list->u.reg.val);
+	  memcpy (record_list->u.reg.val, reg, MAX_REGISTER_SIZE);
+	}
+      else if (record_list->type == record_mem)
+	{
+	  /* mem */
+	  gdb_byte mem[record_list->u.mem.len];
+	  if (debug_record)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: record_list mem addr = 0x%s len = %d to current.\n",
+				  paddr_nz (record_list->u.mem.addr),
+				  record_list->u.mem.len);
+	    }
+	  if (target_read_memory
+	      (record_list->u.mem.addr, mem, record_list->u.mem.len))
+	    {
+	      error (_("record: read memory addr = 0x%s len = %d error."),
+		     paddr_nz (record_list->u.mem.addr),
+		     record_list->u.mem.len);
+	    }
+	  if (target_write_memory
+	      (record_list->u.mem.addr, record_list->u.mem.val,
+	       record_list->u.mem.len))
+	    {
+	      error (_("record: write memory addr = 0x%s len = %d error."),
+		     paddr_nz (record_list->u.mem.addr),
+		     record_list->u.mem.len);
+	    }
+	  memcpy (record_list->u.mem.val, mem, record_list->u.mem.len);
+	}
+      else
+	{
+	  if (debug_record)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: record_list end need_dasm = %d to current.\n",
+				  record_list->u.need_dasm);
+	    }
+
+	  need_dasm = record_list->u.need_dasm;
+	  if (!gdb_is_reverse)
+	    {
+	      insn_end = 1;
+	    }
+	}
+
+      if (gdb_is_reverse)
+	{
+	  if (record_list->prev)
+	    {
+	      record_list = record_list->prev;
+	      if (!record_list->type)
+		{
+		  insn_end = 1;
+		}
+	    }
+	  else
+	    {
+	      state = 2;
+	      insn_end = 1;
+	    }
+	}
+      else
+	{
+	  if (record_list->next)
+	    {
+	      record_list = record_list->next;
+	    }
+	  else
+	    {
+	      state = 1;
+	    }
+	}
+
+      if (insn_end)
+	{
+	  struct breakpoint *b;
+	  CORE_ADDR tmp_pc;
+
+	  if (debug_record)
+	    {
+	      fprintf_unfiltered (gdb_stdlog,
+				  "record: insn end need_dasm = %d to current.\n",
+				  need_dasm);
+	    }
+
+	  if (need_dasm)
+	    {
+	      gdbarch_record_dasm (gdbarch);
+	    }
+
+	  //registers_changed ();
+	  tmp_pc = read_pc ();
+
+	  /* end */
+	  if (record_wait_step)
+	    {
+	      if (debug_record)
+		{
+		  fprintf_unfiltered (gdb_stdlog, "record: step.\n");
+		}
+	      con = 0;
+	    }
+
+	  /* check breakpoint */
+	  for (b = breakpoint_chain; b; b = b->next)
+	    {
+	      if (b->loc->inserted)
+		{
+		  if (b->loc->target_info.placed_address == tmp_pc)
+		    {
+		      if (debug_record)
+			{
+			  fprintf_unfiltered (gdb_stdlog,
+					      "record: break at 0x%s.\n",
+					      paddr_nz (tmp_pc));
+			}
+		      con = 0;
+		      break;
+		    }
+		}
+	    }
+
+	  insn_end = 0;
+	}
+    }
+  while (con);
+
+  if (sigaction (SIGALRM, &old_act, NULL))
+    {
+      perror_with_name (_("sigaction"));
+    }
+
+  status->kind = TARGET_WAITKIND_STOPPED;
+  if (record_get_sig)
+    {
+      status->value.sig = TARGET_SIGNAL_INT;
+    }
+  else
+    {
+      status->value.sig = TARGET_SIGNAL_TRAP;
+    }
+
+  return (inferior_ptid);
+}
+
+void
+record_close (void)
+{
+  gdb_is_recording = 0;
+  gdb_is_reverse = 0;
+  record_list_release (record_list);
+  record_list = NULL;
+  record_delay_slot = 0;
+  printf_unfiltered (_("record: record and reverse function is stopped.\n"));
+}
+
+static void
+cmd_record_start (char *args, int from_tty)
+{
+  /* check exec */
+  if (!target_has_execution)
+    {
+      error (_("record: the program is not being run."));
+    }
+
+  if (!gdbarch_record_p (current_gdbarch))
+    {
+      error (_("record: the current gdbarch don't support record function."));
+    }
+
+  if (gdb_is_recording)
+    {
+      printf_unfiltered (_
+			 ("record: record and reverse function has already been started.\n"));
+    }
+  else
+    {
+      char *tmp;
+
+      gdb_is_recording = 1;
+      printf_unfiltered (_
+			 ("record: record and reverse function is started.\n"));
+
+      tmp = get_prompt ();
+      snprintf (record_gdb_prompt, 20, "%s", tmp);
+      set_prompt (RECORD_REC_PROMPT);
+    }
+}
+
+static void
+cmd_record_stop (char *args, int from_tty)
+{
+  /* check exec */
+  if (!target_has_execution)
+    {
+      error (_("record: the program is not being run."));
+    }
+
+  if (!gdbarch_record_p (current_gdbarch))
+    {
+      error (_("record: the current gdbarch don't support record function."));
+    }
+
+  if (gdb_is_recording)
+    {
+      record_close ();
+      set_prompt (record_gdb_prompt);
+    }
+  else
+    {
+      printf_unfiltered (_
+			 ("record: record and reverse function is not started.\n"));
+    }
+}
+
+static void
+cmd_reverse (char *args, int from_tty)
+{
+  if (gdb_is_reverse)
+    {
+      gdb_is_reverse = 0;
+      printf_unfiltered (_("record: GDB is set to normal debug mode.\n"));
+      set_prompt (RECORD_REC_PROMPT);
+    }
+  else
+    {
+      if (!record_list)
+	{
+	  error (_("record: record and reverse function is not started."));
+	}
+      gdb_is_reverse = 1;
+      printf_unfiltered (_("record: GDB is set to reverse debug mode.\n"));
+      set_prompt (RECORD_REV_PROMPT);
+    }
+}
+
+void
+_initialize_record (void)
+{
+  /*  init record_maskall */
+  if (sigfillset (&record_maskall) == -1)
+    {
+      perror_with_name (_("sigfillset"));
+    }
+
+  add_setshow_zinteger_cmd ("record", class_maintenance, &debug_record,
+			    _("Set record debugging."),
+			    _("Show record debugging."),
+			    _
+			    ("When non-zero, record specific debugging is enabled."),
+			    NULL, show_debug_record, &setdebuglist,
+			    &showdebuglist);
+  add_com ("record", class_obscure, cmd_record_start,
+	   _("Start the record and reverse function."));
+  add_com_alias ("rec", "record", class_obscure, 1);
+  add_com ("stoprecord", class_obscure, cmd_record_stop,
+	   _("Stop the record and reverse function."));
+  add_com_alias ("srec", "stoprecord", class_obscure, 1);
+  add_com ("reverse", class_obscure, cmd_reverse,
+	   _("Set GDB to the reverse debug mode or the normal debug mode."));
+  add_com_alias ("rev", "reverse", class_obscure, 1);
+}
--- a/gdb/record.h
+++ b/gdb/record.h
@@ -0,0 +1,81 @@
+/* Record v0.1.2 for GDB, the GNU debugger.
+   Written by Hui Zhu <teawater@gmail.com>
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _RECORD_H_
+#define _RECORD_H_
+
+typedef struct record_reg_s
+{
+  int num;
+  gdb_byte *val;
+} record_reg_t;
+
+typedef struct record_mem_s
+{
+  CORE_ADDR addr;
+  int len;
+  gdb_byte *val;
+} record_mem_t;
+
+enum record_type {
+  record_end = 0,
+  record_reg,
+  record_mem
+};
+
+/* This is the core struct of record function.
+   An entity of record_t is a record of the value change of a register
+   ("record_reg") or a part of memory ("record_mem"). And Each instruction must
+   has a record_t ("record_end") that point out this is the last record_t of
+   this instruction.
+   Each record_t is linked to "record_list" by "prev" and "next". 
+ */
+typedef struct record_s
+{
+  struct record_s *prev;
+  struct record_s *next;
+  enum record_type type;
+  union
+  {
+    /* reg */
+    record_reg_t reg;
+    /* mem */
+    record_mem_t mem;
+    /* end */
+    int need_dasm;
+  } u;
+} record_t;
+
+extern record_t *record_list;
+extern record_t *record_arch_list_head;
+extern record_t *record_arch_list_tail;
+extern int record_arch_need_dasm;
+extern unsigned int gdb_is_recording;
+extern int gdb_is_reverse;
+extern int debug_record;
+extern int record_wait_step;
+extern int record_delay_slot;
+extern struct regcache *record_regcache;
+
+extern void record_message (struct gdbarch *gdbarch);
+extern int record_arch_list_add_reg (int num);
+extern int record_arch_list_add_mem (CORE_ADDR addr, int len);
+extern int record_arch_list_add_end (int need_dasm);
+extern ptid_t record_wait (struct gdbarch *gdbarch, ptid_t ptid, struct target_waitstatus *status);
+extern void record_close (void);
+#endif //_RECORD_H_
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -39,6 +39,7 @@
 #include "gdbcore.h"
 #include "exceptions.h"
 #include "target-descriptions.h"
+#include "record.h"
 
 static void target_info (char *, int);
 
@@ -1702,6 +1703,16 @@ target_follow_fork (int follow_child)
 		  "could not find a target to follow fork");
 }
 
+void
+target_mourn_inferior (void)
+{
+  if (gdb_is_recording)
+    {
+      record_close ();
+    }
+  (*current_target.to_mourn_inferior) ();
+}
+
 /* Look for a target which can describe architectural features, starting
    from TARGET.  If we find one, return its description.  */
 
@@ -2065,6 +2076,10 @@ debug_to_close (int quitting)
 void
 target_close (struct target_ops *targ, int quitting)
 {
+  if (gdb_is_recording)
+    {
+      record_close ();
+    }
   if (targ->to_xclose != NULL)
     targ->to_xclose (targ, quitting);
   else if (targ->to_close != NULL)
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -861,8 +861,7 @@ int target_follow_fork (int follow_child
 
 /* The inferior process has died.  Do what is right.  */
 
-#define	target_mourn_inferior()	\
-     (*current_target.to_mourn_inferior) ()
+extern void target_mourn_inferior (void);
 
 /* Does target have enough data to do a run or attach command? */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]