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]

Record patch 0.1.6 for GDB branch msnyder-reverse-20080609-branch release again


Hi guys,

I am so sorry that the old patch have a lot of format problem because
I use indent with file infrun.c and linux-nat.c.
Now, I fixed them and send the patch again. Thanks for Pedro told me
my format problem. :)

GDB record patch make GDB support Reversible Debugging.
It make GDB disassemble the instruction that will be executed to get
which memory and register will be changed and record them to record
all program running message. Through these on the use of this
information to achieve the implementation of the GDB Reversible
Debugging function.
To get more message, you can go to http://sourceforge.net/projects/record/ .

The main change of this version is change record function to be a
target of GDB. Then it can work with the interface of branch
msnyder-reverse-20080609-branch. The command in this branch is so cool
such as "rn"(reverse-next), "rs"(reverse-step) and
"rc"(reverse-continue). I like it. :)
You can start record target with command "rec"(record) or "target record".
I try to use some simple commands such as "disconnect" and "detach" to
instead command "delrecord"(dr) and "stoprecord"(sr). But these
commands all have other affect to GDB such as call function
"no_shared_libraries". So I keep the command "delrecord"(dr) and
"stoprecord"(sr).

Please give me your advice about GDB record. Thanks a lot. :)

teawater
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 891b31a..f6a36b8 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -641,7 +641,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c  \
 	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
 
@@ -920,6 +921,7 @@ xcoffsolib_h = xcoffsolib.h
 xml_support_h = xml-support.h $(gdb_obstack_h) $(vec_h)
 xml_tdesc_h = xml-tdesc.h
 xtensa_tdep_h = xtensa-tdep.h 
+record_h = record.h
 
 #
 # gdb/cli/ headers
@@ -1091,7 +1093,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	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
 
@@ -2269,7 +2272,7 @@ i386-linux-tdep.o: i386-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \
 	$(value_h) $(regcache_h) $(inferior_h) $(osabi_h) $(reggroups_h) \
 	$(dwarf2_frame_h) $(gdb_string_h) $(i386_tdep_h) \
 	$(i386_linux_tdep_h) $(glibc_tdep_h) $(solib_svr4_h) $(symtab_h) \
-	$(arch_utils_h) $(regset_h)
+	$(arch_utils_h) $(regset_h) $(record_h)
 i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h) \
 	$(target_h)
 i386nbsd-nat.o: i386nbsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
@@ -2301,7 +2304,7 @@ i386-tdep.o: i386-tdep.c $(defs_h) $(arch_utils_h) $(command_h) \
 	$(gdbcmd_h) $(gdbcore_h) $(objfiles_h) $(osabi_h) $(regcache_h) \
 	$(reggroups_h) $(regset_h) $(symfile_h) $(symtab_h) $(target_h) \
 	$(value_h) $(dis_asm_h) $(gdb_assert_h) $(gdb_string_h) \
-	$(i386_tdep_h) $(i387_tdep_h)
+	$(i386_tdep_h) $(i387_tdep_h) $(record_h)
 i386v4-nat.o: i386v4-nat.c $(defs_h) $(value_h) $(inferior_h) $(regcache_h) \
 	$(i386_tdep_h) $(i387_tdep_h) $(gregset_h)
 i387-tdep.o: i387-tdep.c $(defs_h) $(doublest_h) $(floatformat_h) $(frame_h) \
@@ -2332,13 +2335,14 @@ infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(objfiles_h) $(completer_h) $(ui_out_h) $(event_top_h) \
 	$(parser_defs_h) $(regcache_h) $(reggroups_h) $(block_h) \
 	$(solib_h) $(gdb_assert_h) $(observer_h) $(target_descriptions_h) \
-	$(user_regs_h) $(exceptions_h) $(cli_decode_h) $(gdbthread_h)
+	$(user_regs_h) $(exceptions_h) $(cli_decode_h) $(gdbthread_h) \
+	$(record_h)
 inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
 	$(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h) \
 	$(language_h)
 inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \
 	$(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) \
-	$(inflow_h) $(gdb_select_h)
+	$(inflow_h) $(gdb_select_h) $(record_h)
 inf-ptrace.o: inf-ptrace.c $(defs_h) $(command_h) $(inferior_h) $(inflow_h) \
 	$(gdbcore_h) $(regcache_h) $(gdb_stdint_h) $(gdb_assert_h) \
 	$(gdb_string_h) $(gdb_ptrace_h) $(gdb_wait_h) $(inf_child_h)
@@ -2347,7 +2351,7 @@ infrun.o: infrun.c $(defs_h) $(gdb_string_h) $(symtab_h) $(frame_h) \
 	$(gdbcore_h) $(gdbcmd_h) $(cli_script_h) $(target_h) $(gdbthread_h) \
 	$(annotate_h) $(symfile_h) $(top_h) $(inf_loop_h) $(regcache_h) \
 	$(value_h) $(observer_h) $(language_h) $(solib_h) $(gdb_assert_h) \
-	$(mi_common_h) $(main_h)
+	$(mi_common_h) $(main_h) $(record_h)
 inf-ttrace.o: inf-ttrace.c $(defs_h) $(command_h) $(gdbcore_h) \
 	$(gdbthread_h) $(inferior_h) $(target_h) \
 	$(gdb_assert_h) $(gdb_string_h) $(inf_child_h) $(inf_ttrace_h)
@@ -2393,7 +2397,8 @@ linux-nat.o: linux-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdb_string_h) \
 	$(gdb_wait_h) $(gdb_assert_h) $(linux_nat_h) $(gdbthread_h) \
 	$(gdbcmd_h) $(regcache_h) $(regset_h) $(inf_ptrace_h) $(auxv_h) \
 	$(elf_bfd_h) $(gregset_h) $(gdbcore_h) $(gdbthread_h) $(gdb_stat_h) \
-	$(linux_fork_h) $(inf_loop_h) $(event_loop_h) $(event_top_h)
+	$(linux_fork_h) $(inf_loop_h) $(event_loop_h) $(event_top_h) \
+	$(record_h)
 linux-thread-db.o: linux-thread-db.c $(defs_h) $(gdb_assert_h) \
 	$(gdb_proc_service_h) $(gdb_thread_db_h) $(bfd_h) $(exceptions_h) \
 	$(gdbthread_h) $(inferior_h) $(symfile_h) $(objfiles_h) $(target_h) \
@@ -2661,7 +2666,7 @@ p-valprint.o: p-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
 	$(cp_support_h)
 regcache.o: regcache.c $(defs_h) $(inferior_h) $(target_h) $(gdbarch_h) \
 	$(gdbcmd_h) $(regcache_h) $(reggroups_h) $(gdb_assert_h) \
-	$(gdb_string_h) $(gdbcmd_h) $(observer_h)
+	$(gdb_string_h) $(gdbcmd_h) $(observer_h) $(record_h)
 reggroups.o: reggroups.c $(defs_h) $(reggroups_h) $(gdbtypes_h) \
 	$(gdb_assert_h) $(regcache_h) $(command_h) $(gdbcmd_h)
 regset.o: regset.c $(defs_h) $(regset_h) $(gdb_assert_h)
@@ -3047,6 +3052,8 @@ xtensa-tdep.o: xtensa-tdep.c $(defs_h) $(doublest_h) $(frame_h) \
 	$(reggroups_h) $(arch_utils_h) $(osabi_h) $(block_h) $(gdb_assert_h) \
 	$(elf_bfd_h) $(xtensa_tdep_h) $(dwarf2_frame_h) $(solib_svr4_h)
 xtensa-config.o: $(defs_h) $(xtensa_tdep_h)
+record.o: record.c $(defs_h) $(target_h) $(gdbcmd_h) $(regcache_h) \
+	$(inferior_h) $(record_h)
 
 #
 # gdb/cli/ dependencies
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 6594b35..deeb04f 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -238,6 +238,8 @@ struct gdbarch
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
+  gdbarch_record_ftype *record;
+  gdbarch_record_dasm_ftype *record_dasm;
 };
 
 
@@ -368,6 +370,8 @@ struct gdbarch startup_gdbarch =
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
   0,  /* record_special_symbol */
+  NULL,  /* record_ftype */
+  NULL,  /* record_dasm_ftype */
   /* startup_gdbarch() */
 };
 
@@ -3621,6 +3625,46 @@ deprecated_current_gdbarch_select_hack (struct gdbarch *new_gdbarch)
   reinit_frame_cache ();
 }
 
+int
+gdbarch_record_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return (gdbarch->record != NULL);
+}
+
+int
+gdbarch_record (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  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, addr));
+}
+
+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
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 44d1f2d..fa08227 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -975,6 +975,20 @@ extern struct gdbarch *gdbarch_find_by_info (struct gdbarch_info info);
 extern void deprecated_current_gdbarch_select_hack (struct gdbarch *gdbarch);
 
 
+/* For the record target */
+
+extern int gdbarch_record_p (struct gdbarch *gdbarch);
+typedef int (gdbarch_record_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern int gdbarch_record (struct gdbarch *gdbarch, CORE_ADDR addr);
+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);
+
+
 /* Register per-architecture data-pointer.
 
    Reserve space for a per-architecture data-pointer.  An identifier
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 5284f4a..0d3d205 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -37,6 +37,9 @@
 #include "arch-utils.h"
 #include "regset.h"
 
+#include "record.h"
+#include <stdint.h>
+
 /* Supported register note sections.  */
 static struct core_regset_section i386_linux_regset_sections[] =
 {
@@ -347,6 +350,2530 @@ i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
   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
    the register sets in `struct user' that are used for a.out
@@ -440,6 +2967,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   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);
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index be4f4f3..fa1f282 100644
--- 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[] =
@@ -2450,6 +2453,2529 @@ i386_fetch_pointer_argument (struct frame_info *frame, int argi,
   return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4);
 }
 
+#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,
+};
+
+/* i386 arith/logic operations */
+enum
+{
+  OP_ADDL,
+  OP_ORL,
+  OP_ADCL,
+  OP_SBBL,
+  OP_ANDL,
+  OP_SUBL,
+  OP_XORL,
+  OP_CMPL,
+};
+
+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;
+
+/* 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;
+
+  return (0);
+}
+
+/* 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;
+
+      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);
+	}
+
+      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;
+	}
+
+      if (base != 0xff)
+	{
+	  regcache_raw_read (record_regcache, base, (gdb_byte *) & tmpu32);
+	  *addr += tmpu32;
+	}
+
+      /* 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;
+	}
+
+      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;
+    }
+
+no_rm:
+  return (0);
+}
+
+/* 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;
+
+  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);
+    }
+
+  if (i386_record_lea_modrm_addr (&addr))
+    {
+      return (-1);
+    }
+
+  if (record_arch_list_add_mem (addr, 1 << ot))
+    {
+      return (-1);
+    }
+
+  return (0);
+}
+
+/* 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, CORE_ADDR addr)
+{
+  int prefixes = 0;
+  uint8_t tmpu8;
+  uint16_t tmpu16;
+  uint32_t tmpu32;
+  uint32_t opcode;
+
+  i386_record_pc = addr;
+  aflag = 1;
+  dflag = 1;
+  override = 0;
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: i386_record pc = 0x%s\n",
+			  paddr_nz (i386_record_pc));
+    }
+
+  /* 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;
+    }
+
+  /* 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;
+
+      /* 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;
+	    }
+
+	  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;
+
+      /* GRP1 */
+    case 0x80 ... 0x83:
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      if (reg != OP_CMPL)
+	{
+	  if ((opcode & 1) == 0)
+	    {
+	      ot = OT_BYTE;
+	    }
+	  else
+	    {
+	      ot = dflag + OT_WORD;
+	    }
+
+	  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;
+
+      /* 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;
+
+      /* GRP3 */
+    case 0xf6:
+    case 0xf7:
+      if ((opcode & 1) == 0)
+	{
+	  ot = OT_BYTE;
+	}
+      else
+	{
+	  ot = dflag + OT_WORD;
+	}
+      if (i386_record_modrm ())
+	{
+	  return (-1);
+	}
+
+      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;
+    }
+
+/* In the future, Maybe still need to deal with need_dasm */
+  if (record_arch_list_add_reg (I386_EIP_REGNUM))
+    {
+      return (-1);
+    }
+  if (record_arch_list_add_end (0))
+    {
+      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)
@@ -2638,6 +5164,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (tdep->mm0_regnum == 0)
     tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
 
+  set_gdbarch_record (gdbarch, i386_record);
+
   return gdbarch;
 }
 
diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h
index 227ac66..774dd37 100644
--- 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.  */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index e223829..caf16f2 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -51,6 +51,7 @@
 #include "exceptions.h"
 #include "cli/cli-decode.h"
 #include "gdbthread.h"
+#include "record.h"
 
 /* Functions exported for general use, in inferior.h: */
 
@@ -194,6 +195,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
@@ -458,10 +465,20 @@ kill_if_already_running (int from_tty)
 	 restart it.  */
       target_require_runnable ();
 
-      if (from_tty
-	  && !query ("The program being debugged has been started already.\n\
+      if (RECORD_IS_USED)
+        {
+          if (from_tty
+	      && !query ("The program being debugged and target record have been started already.\n\
+Stop target record and start the program being debugged from the beginning? "))
+	    error (_("Program not restarted."));
+        }
+      else
+        {
+          if (from_tty
+	      && !query ("The program being debugged has been started already.\n\
 Start it from the beginning? "))
-	error (_("Program not restarted."));
+	    error (_("Program not restarted."));
+        }
       target_kill ();
       no_shared_libraries (NULL, from_tty);
       init_wait_for_inferior ();
@@ -750,6 +767,19 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
 	    error (_("No current frame"));
 	  step_frame_id = get_frame_id (frame);
 
+	  if (target_get_execution_direction () == EXEC_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);
@@ -859,6 +889,19 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
 	error (_("No current frame"));
       step_frame_id = get_frame_id (frame);
 
+      if (target_get_execution_direction () == EXEC_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);
@@ -1133,6 +1176,19 @@ until_next_command (int from_tty)
   step_over_calls = STEP_OVER_ALL;
   step_frame_id = get_frame_id (frame);
 
+  if (target_get_execution_direction () == EXEC_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);
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 1dd152a..a57e678 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -314,6 +314,12 @@ extern CORE_ADDR step_range_end;	/* Exclusive */
 
 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.  */
 
diff --git a/gdb/inflow.c b/gdb/inflow.c
index 6a77531..c0996a9 100644
--- a/gdb/inflow.c
+++ b/gdb/inflow.c
@@ -34,6 +34,8 @@
 
 #include "inflow.h"
 
+#include "record.h"
+
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
@@ -594,8 +596,16 @@ kill_command (char *arg, int from_tty)
 
   if (ptid_equal (inferior_ptid, null_ptid))
     error (_("The program is not being run."));
-  if (!query ("Kill the program being debugged? "))
-    error (_("Not confirmed."));
+  if (RECORD_IS_USED)
+    {
+      if (!query ("Stop the record target and kill the program being debugged? "))
+        error (_("Not confirmed."));
+    }
+  else
+    {
+      if (!query ("Kill the program being debugged? "))
+        error (_("Not confirmed."));
+    }
   target_kill ();
 
   init_thread_list ();		/* Destroy thread info */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index e7d1dec..b0ba6a4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -49,6 +49,14 @@
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 
+#include "record.h"
+
+/* When the record function want inferior step before call function
+   "keep_going", "reverse_resume_need_step" will be set to 1. It will be set
+   back to 0 in the begin of function "handle_inferior_event" because it just
+   be accessed by the sub-functions of "handle_inferior_event". */
+static int reverse_resume_need_step = 0;
+
 /* Prototypes for local functions */
 
 static void signals_info (char *, int);
@@ -559,7 +567,7 @@ static ptid_t deferred_step_ptid;
 /* If this is not null_ptid, this is the thread carrying out a
    displaced single-step.  This thread's state will require fixing up
    once it has completed its step.  */
-static ptid_t displaced_step_ptid;
+ptid_t displaced_step_ptid;
 
 struct displaced_step_request
 {
@@ -578,7 +586,7 @@ static struct gdbarch *displaced_step_gdbarch;
 static struct displaced_step_closure *displaced_step_closure;
 
 /* The address of the original instruction, and the copy we made.  */
-static CORE_ADDR displaced_step_original, displaced_step_copy;
+CORE_ADDR displaced_step_original, displaced_step_copy;
 
 /* Saved contents of copy area.  */
 static gdb_byte *displaced_step_saved_copy;
@@ -603,7 +611,8 @@ static int
 use_displaced_stepping (struct gdbarch *gdbarch)
 {
   return (can_use_displaced_stepping
-	  && gdbarch_displaced_step_copy_insn_p (gdbarch));
+	  && gdbarch_displaced_step_copy_insn_p (gdbarch)
+	  && !RECORD_IS_REPLAY);
 }
 
 /* Clean out any stray displaced stepping state.  */
@@ -1167,6 +1176,9 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
   if (step < 0)
     stop_after_trap = 1;
 
+  if (RECORD_IS_USED)
+    record_not_record_set ();
+
   if (addr == (CORE_ADDR) -1)
     {
       if (pc == stop_pc && breakpoint_here_p (pc))
@@ -1708,6 +1720,9 @@ handle_inferior_event (struct execution_control_state *ecs)
   int stopped_by_watchpoint;
   int stepped_after_stopped_by_watchpoint = 0;
 
+  /* Reset reverse_resume_need_step to 0. */
+  reverse_resume_need_step = 0;
+
   /* Cache the last pid/waitstatus. */
   target_last_wait_ptid = ecs->ptid;
   target_last_waitstatus = *ecs->wp;
@@ -2457,7 +2472,9 @@ handle_inferior_event (struct execution_control_state *ecs)
 	ecs->random_signal
 	  = !(bpstat_explains_signal (stop_bpstat)
 	      || stepping_over_breakpoint
-	      || (step_range_end && step_resume_breakpoint == NULL));
+	      || (step_range_end && step_resume_breakpoint == NULL)
+	      || (target_get_execution_direction () == EXEC_REVERSE)
+	      || RECORD_IS_USED);
       else
 	{
 	  ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
@@ -2987,15 +3004,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 	     get there, we'll need to single-step back to the
 	     caller.  */
 
-	  if (target_get_execution_direction () == EXEC_REVERSE)
+	  if (target_get_execution_direction () == EXEC_REVERSE
+	      || RECORD_IS_USED)
 	    {
-	      /* FIXME: I'm not sure if we've handled the frame for
-		 recursion.  */
-
-	      struct symtab_and_line sr_sal;
-	      init_sal (&sr_sal);
-	      sr_sal.pc = ecs->stop_func_start;
-	      insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
+	      reverse_resume_need_step = 1;
 	    }
 	  else
 	    insert_step_resume_breakpoint_at_caller (get_current_frame ());
@@ -3071,6 +3083,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 	  sr_sal.pc = ecs->stop_func_start;
 	  insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
 	}
+      else if (RECORD_IS_USED)
+	{
+	  reverse_resume_need_step = 1;
+	}
       else
 	{
 	  /* Set a breakpoint at callee's return address (the address
@@ -3128,6 +3144,13 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
 
+      if (target_get_execution_direction () == EXEC_REVERSE || RECORD_IS_USED)
+	{
+	  reverse_resume_need_step = 1;
+	  keep_going (ecs);
+	  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
@@ -3177,13 +3200,58 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
          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
+	   && target_get_execution_direction () == EXEC_REVERSE)
+	  || RECORD_IS_USED)
+	{
+	  reverse_resume_need_step = 1;
+	  keep_going (ecs);
+	  return;
+	}
+
       stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
     }
 
-  if ((stop_pc == ecs->sal.pc)
+  if (target_get_execution_direction () == EXEC_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)
+      && (target_get_execution_direction () == EXEC_REVERSE
+	  || RECORD_IS_USED))
+    {
+      if ((stop_pc != ecs->sal.pc
+	   && target_get_execution_direction () == EXEC_REVERSE)
+	  || (step_over_calls == STEP_OVER_ALL && RECORD_IS_USED))
+	{
+	  if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog,
+				"infrun: maybe stepped into subroutine\n");
+	  reverse_resume_need_step = 1;
+	  keep_going (ecs);
+	  return;
+	}
+    }
+
+  if (((stop_pc == ecs->sal.pc
+	&& target_get_execution_direction () != EXEC_REVERSE)
+       || (stop_pc >= ecs->sal.pc && stop_pc < ecs->sal.end
+	   && target_get_execution_direction () == EXEC_REVERSE))
       && (ecs->current_line != ecs->sal.line
 	  || ecs->current_symtab != ecs->sal.symtab))
     {
@@ -3252,7 +3320,8 @@ currently_stepping (struct execution_control_state *ecs)
   return (((step_range_end && step_resume_breakpoint == NULL)
 	   || stepping_over_breakpoint)
 	  || ecs->stepping_through_solib_after_catch
-	  || bpstat_should_step ());
+	  || bpstat_should_step ()
+	  || reverse_resume_need_step);
 }
 
 /* Subroutine call with source code we should not step over.  Do step
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 47dac59..ee0d65c 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -50,6 +50,8 @@
 #include "event-loop.h"
 #include "event-top.h"
 
+#include "record.h"
+
 /* Note on this file's use of signals:
 
    We stop threads by sending a SIGSTOP.  The use of SIGSTOP instead
@@ -396,6 +398,106 @@ my_waitpid (int pid, int *status, int flags)
   return ret;
 }
 
+extern struct bp_location *bp_location_chain;
+static int
+my_waitpid_record (int pid, int *status, int flags)
+{
+  int ret;
+  struct bp_location *bl;
+  struct breakpoint *b;
+  CORE_ADDR pc;
+
+wait_begin:
+  ret = waitpid (pid, status, flags);
+  if (ret == -1)
+    {
+      if (errno == EINTR)
+	{
+	  goto wait_begin;
+	}
+      return ret;
+    }
+
+  if (ret == 0)
+    {
+      goto wait_begin;
+    }
+
+  if (WIFSTOPPED (*status) && WSTOPSIG (*status) == SIGTRAP)
+    {
+      /* Check if there is a breakpoint */
+      pc = 0;
+      registers_changed ();
+      for (bl = bp_location_chain; bl; bl = bl->global_next)
+	{
+	  b = bl->owner;
+	  gdb_assert (b);
+	  if (b->enable_state != bp_enabled
+	      && b->enable_state != bp_permanent)
+	    continue;
+	  if (!pc)
+	    {
+	      pc = regcache_read_pc (get_thread_regcache (pid_to_ptid (ret)));
+	    }
+	  switch (b->type)
+	    {
+	    default:
+	      if (bl->address == pc)
+		{
+		  goto out;
+		}
+	      break;
+
+	    case bp_watchpoint:
+	      /*XXX teawater: I still not very clear how to deal with it. */
+	      goto out;
+	      break;
+
+	    case bp_catch_fork:
+	      if (inferior_has_forked (ret, &b->forked_inferior_pid))
+		{
+		  goto out;
+		}
+	      break;
+
+	    case bp_catch_vfork:
+	      if (inferior_has_vforked (ret, &b->forked_inferior_pid))
+		{
+		  goto out;
+		}
+	      break;
+
+	    case bp_catch_exec:
+	      if (inferior_has_execd (ret, &b->exec_pathname))
+		{
+		  goto out;
+		}
+	      break;
+
+	    case bp_hardware_watchpoint:
+	    case bp_read_watchpoint:
+	    case bp_access_watchpoint:
+	      if (STOPPED_BY_WATCHPOINT (0))
+		{
+		  goto out;
+		}
+	      break;
+
+	    }
+	}
+
+      /* record message */
+      record_message (current_gdbarch);
+
+      /* resume program */
+      linux_ops->to_resume (pid_to_ptid (ret), 1, TARGET_SIGNAL_0);
+      goto wait_begin;
+    }
+
+out:
+  return ret;
+}
+
 /* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.
 
    First, we try to enable fork tracing on ORIGINAL_PID.  If this fails,
@@ -2630,7 +2732,16 @@ retry:
 	   queued events.  */
 	lwpid = queued_waitpid (pid, &status, options);
       else
-	lwpid = my_waitpid (pid, &status, options);
+	{
+	  if (RECORD_IS_USED && !record_resume_step)
+	    {
+	      lwpid = my_waitpid_record (pid, &status, options);
+	    }
+	  else
+	    {
+	      lwpid = my_waitpid (pid, &status, options);
+	    }
+	}
 
       if (lwpid > 0)
 	{
diff --git a/gdb/record.c b/gdb/record.c
new file mode 100644
index 0000000..4cab7a0
--- /dev/null
+++ b/gdb/record.c
@@ -0,0 +1,867 @@
+/* Record v0.1.6 for GDB, the GNU debugger.
+   Written by Hui Zhu <teawater@gmail.com>
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "regcache.h"
+#include "inferior.h"
+#include "record.h"
+
+#include <signal.h>
+
+int record_debug = 0;
+record_t record_first;
+record_t *record_list = &record_first;
+int record_list_status = 1;	/* 0 normal 1 to the begin 2 to the end */
+record_t *record_arch_list_head = NULL;
+record_t *record_arch_list_tail = NULL;
+struct regcache *record_regcache = NULL;
+
+struct target_ops record_ops;
+int record_resume_step = 0;
+enum exec_direction_kind record_execdir = EXEC_FORWARD;
+static int record_get_sig = 0;
+static sigset_t record_maskall;
+static int record_not_record = 0;
+int record_regcache_raw_write_regnum = 0;
+int record_will_store_registers = 0;
+
+extern struct breakpoint *breakpoint_chain;
+extern ptid_t displaced_step_ptid;
+extern CORE_ADDR displaced_step_original, displaced_step_copy;
+
+static void
+record_list_release (record_t * rec)
+{
+  record_t *tmp;
+
+  if (!rec)
+    return;
+
+  while (rec->next)
+    {
+      rec = rec->next;
+    }
+
+  while (rec->prev)
+    {
+      tmp = rec;
+      rec = rec->prev;
+      if (tmp->type == record_reg)
+	{
+	  xfree (tmp->u.reg.val);
+	}
+      else if (tmp->type == record_mem)
+	{
+	  xfree (tmp->u.mem.val);
+	}
+      xfree (tmp);
+    }
+
+  if (rec != &record_first)
+    {
+      xfree (rec);
+    }
+}
+
+static void
+record_list_release_next (record_t * rec)
+{
+  record_t *tmp = rec->next;
+  rec->next = NULL;
+  while (tmp)
+    {
+      rec = tmp->next;
+      if (tmp->type == record_reg)
+	{
+	  xfree (tmp->u.reg.val);
+	}
+      else if (tmp->type == record_mem)
+	{
+	  xfree (tmp->u.mem.val);
+	}
+      xfree (tmp);
+      tmp = rec;
+    }
+}
+
+/* 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 (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "Record: add reg num = %d to record list.\n", num);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  rec->u.reg.val = (gdb_byte *) xmalloc (MAX_REGISTER_SIZE);
+  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 (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "Record: add mem addr = 0x%s len = %d to record list.\n",
+			  paddr_nz (addr), len);
+    }
+
+  if (!addr)
+    {
+      return (0);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  rec->u.mem.val = (gdb_byte *) xmalloc (len);
+  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 (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "Record: add end need_dasm = %d to arch list.\n",
+			  need_dasm);
+    }
+
+  rec = (record_t *) xmalloc (sizeof (record_t));
+  rec->prev = NULL;
+  rec->next = NULL;
+  rec->type = record_end;
+
+  rec->u.need_dasm = need_dasm;
+
+  record_arch_list_add (rec);
+
+  return (0);
+}
+
+/* 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 ();
+
+  /* Deal with displaced stepping */
+  if (!ptid_equal (displaced_step_ptid, null_ptid))
+    {
+      if (record_debug)
+	{
+	  fprintf_unfiltered (gdb_stdlog,
+			      "Record: this stepping is displaced stepping. Change PC register to original address 0x%s before call gdbarch_record. After that, change it back to 0x%s.\n",
+			      paddr_nz (displaced_step_original),
+			      paddr_nz (displaced_step_copy));
+	}
+      regcache_write_pc (record_regcache, displaced_step_original);
+      ret = gdbarch_record (gdbarch, displaced_step_copy);
+      regcache_write_pc (record_regcache, displaced_step_copy);
+    }
+  else
+    {
+      ret = gdbarch_record (gdbarch, regcache_read_pc (record_regcache));
+    }
+
+  if (ret > 0)
+    {
+      record_list_release (record_arch_list_tail);
+      error (_("Record: record pause the program."));
+    }
+  if (ret < 0)
+    {
+      record_list_release (record_arch_list_tail);
+      error (_("Record: record message error."));
+    }
+
+  record_list->next = record_arch_list_head;
+  record_arch_list_head->prev = record_list;
+  record_list = record_arch_list_tail;
+}
+
+/* Things to clean up if we QUIT out of function that set record_not_record.  */
+static void
+record_not_record_cleanups (void *ignore)
+{
+  record_not_record = 0;
+}
+
+void
+record_not_record_set (void)
+{
+  struct cleanup *old_cleanups = make_cleanup (record_not_record_cleanups, 0);
+  record_not_record = 1;
+}
+
+static void
+record_open (char *name, int from_tty)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_open\n");
+    }
+
+  /* check exec */
+  if (!target_has_execution)
+    {
+      error (_("Record: the program is not being run."));
+    }
+
+  if (!gdbarch_record_p (current_gdbarch))
+    {
+      error (_
+	     ("Record: the current architecture don't support record function."));
+    }
+
+  /* Check if record target is already running */
+  if (RECORD_IS_USED)
+    {
+      if (!nquery
+	  (_
+	   ("Record target already running, do you want delete the old running message?")))
+	{
+	  return;
+	}
+    }
+
+  push_target (&record_ops);
+}
+
+static void
+record_close (int quitting)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_close\n");
+    }
+  record_list_release (record_list);
+  record_list_status = 1;
+  record_execdir = EXEC_FORWARD;
+}
+
+static void
+record_resume (ptid_t ptid, int step, enum target_signal siggnal)
+{
+  record_resume_step = step;
+
+  if (!RECORD_IS_REPLAY)
+    {
+      record_message (current_gdbarch);
+      return record_ops.beneath->to_resume (ptid, 1, siggnal);
+    }
+}
+
+static void
+record_sig_handler (int signo)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: get a signal\n");
+    }
+  record_resume_step = 1;
+  record_get_sig = 1;
+}
+
+static ptid_t
+record_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_resume_step = %d\n",
+			  record_resume_step);
+    }
+
+  if (!RECORD_IS_REPLAY)
+    {
+      return record_ops.beneath->to_wait (ptid, status);
+    }
+  else
+    {
+      struct sigaction act, old_act;
+      int need_dasm = 0;
+      struct regcache *regcache = get_current_regcache ();
+      int con = 1;
+      int first_record_end = 1;
+
+      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 (_("Record: sigaction"));
+	}
+
+      do
+	{
+
+	  /* check state */
+	  if ((record_execdir == EXEC_REVERSE && !record_list->prev
+	       && record_list_status == 1) || (record_execdir != EXEC_REVERSE
+					       && !record_list->next
+					       && record_list_status == 2))
+	    {
+	      if (record_list_status == 2)
+		{
+		  fprintf_unfiltered (gdb_stdlog,
+				      "Record: running to the end of record list.\n");
+		}
+	      else if (record_list_status == 1)
+		{
+		  fprintf_unfiltered (gdb_stdlog,
+				      "Record: running to the begin of record list.\n");
+		}
+	      stop_soon = STOP_QUIETLY;
+	      break;
+	    }
+	  record_list_status = 0;
+
+	  /* set register and memory according to record_list */
+	  if (record_list->type == record_reg)
+	    {
+	      /* reg */
+	      gdb_byte reg[MAX_REGISTER_SIZE];
+	      if (record_debug > 1)
+		{
+		  fprintf_unfiltered (gdb_stdlog,
+				      "Record: record_reg to inferior num = %d.\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 = alloca (record_list->u.mem.len);
+	      if (record_debug > 1)
+		{
+		  fprintf_unfiltered (gdb_stdlog,
+				      "Record: record_mem to inferior addr = 0x%s len = %d.\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
+	    {
+	      CORE_ADDR tmp_pc;
+	      struct breakpoint *b;
+
+	      if (record_debug > 1)
+		{
+		  fprintf_unfiltered (gdb_stdlog,
+				      "Record: record_end to inferior need_dasm = %d.\n",
+				      record_list->u.need_dasm);
+		}
+
+	      if (record_execdir == EXEC_FORWARD)
+		{
+		  need_dasm = record_list->u.need_dasm;
+		}
+	      if (need_dasm)
+		{
+		  gdbarch_record_dasm (current_gdbarch);
+		}
+
+	      if (first_record_end && record_execdir == EXEC_REVERSE)
+		{
+		  /* When reverse excute, the first record_end is the part of current instruction */
+		  first_record_end = 0;
+		}
+	      else
+		{
+		  /* In EXEC_REVERSE mode, this is the record_end of prev
+		     instruction.
+		     In EXEC_FORWARD mode, this is the record_end of current
+		     instruction. */
+		  /* step */
+		  if (record_resume_step)
+		    {
+		      if (record_debug > 1)
+			{
+			  fprintf_unfiltered (gdb_stdlog, "Record: step.\n");
+			}
+		      con = 0;
+		    }
+
+		  /* check breakpoint */
+		  tmp_pc = read_pc ();
+		  for (b = breakpoint_chain; b; b = b->next)
+		    {
+		      if (b->loc->inserted)
+			{
+			  if (b->loc->target_info.placed_address == tmp_pc)
+			    {
+			      if (record_debug > 1)
+				{
+				  fprintf_unfiltered (gdb_stdlog,
+						      "Record: break at 0x%s.\n",
+						      paddr_nz (tmp_pc));
+				}
+			      con = 0;
+			    }
+			}
+		    }
+		}
+	      if (record_execdir == EXEC_REVERSE)
+		{
+		  need_dasm = record_list->u.need_dasm;
+		}
+	    }
+
+	  if (record_execdir == EXEC_REVERSE)
+	    {
+	      if (record_list->prev && con)
+		record_list = record_list->prev;
+	      else
+		record_list_status = 1;
+	    }
+	  else
+	    {
+	      if (record_list->next)
+		record_list = record_list->next;
+	      else
+		record_list_status = 2;
+	    }
+
+	}
+      while (con);
+
+      if (sigaction (SIGALRM, &old_act, NULL))
+	{
+	  perror_with_name (_("Record: 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;
+}
+
+static void
+record_disconnect (struct target_ops *target, char *args, int from_tty)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_disconnect\n");
+    }
+  unpush_target (&record_ops);
+  target_disconnect (args, from_tty);
+}
+
+static void
+record_detach (char *args, int from_tty)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_detach\n");
+    }
+  unpush_target (&record_ops);
+  target_detach (args, from_tty);
+}
+
+/* Close record target before kill the inferior process. */
+static void
+record_kill (void)
+{
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Record: record_kill\n");
+    }
+  unpush_target (&record_ops);
+  target_kill ();
+}
+
+/* Record registers change to list as an instruction */
+static void
+record_registers_change (struct regcache *regcache, int regnum)
+{
+  record_arch_list_head = NULL;
+  record_arch_list_tail = NULL;
+  record_regcache = get_current_regcache ();
+  if (regnum < 0)
+    {
+      int i;
+      for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
+	{
+	  if (record_arch_list_add_reg (i))
+	    {
+	      record_list_release (record_arch_list_tail);
+	      error (_("Record: record message error."));
+	    }
+	}
+    }
+  else
+    {
+      if (record_arch_list_add_reg (regnum))
+	{
+	  record_list_release (record_arch_list_tail);
+	  error (_("Record: record message error."));
+	}
+    }
+  if (record_arch_list_add_end (0))
+    {
+      record_list_release (record_arch_list_tail);
+      error (_("Record: record message error."));
+    }
+  record_list->next = record_arch_list_head;
+  record_arch_list_head->prev = record_list;
+  record_list = record_arch_list_tail;
+}
+
+/* XXX: I don't know how to do if GDB call function target_store_registers
+   without call function target_prepare_to_store. */
+static void
+record_prepare_to_store (struct regcache *regcache)
+{
+  if (!record_not_record)
+    {
+      if (RECORD_IS_REPLAY)
+	{
+	  struct cleanup *old_cleanups;
+	  /* Let user choice if he want to write register or not. */
+	  if (!nquery (_
+		       ("Becuse GDB is in replay mode, this operation will destory the record in the next if set the value of register %s. Do you want GDB do it?"),
+		       gdbarch_register_name (get_regcache_arch
+					      (regcache),
+					      record_regcache_raw_write_regnum)))
+	    {
+	      error (_("Record: record cancel the operation."));
+	    }
+
+	  /* Destory the record in the next */
+	  record_list_release_next (record_list);
+	}
+
+      record_registers_change (regcache, record_regcache_raw_write_regnum);
+    }
+  record_ops.beneath->to_prepare_to_store (regcache);
+}
+
+static LONGEST
+record_xfer_partial (struct target_ops *ops, enum target_object object,
+		     const char *annex, gdb_byte * readbuf,
+		     const gdb_byte * writebuf, ULONGEST offset, LONGEST len)
+{
+  if (!record_not_record
+      && (object == TARGET_OBJECT_MEMORY
+	  || object == TARGET_OBJECT_RAW_MEMORY) && writebuf)
+    {
+      if (RECORD_IS_REPLAY)
+	{
+	  /* Let user choice if he want to write memory or not. */
+	  if (!nquery (_
+		       ("Becuse GDB is in replay mode, this operation will destory the record in the next if write memory that addr is 0x%s and size is %lld. Do you want GDB do it?"),
+		       paddr_nz (offset), len))
+	    {
+	      return -1;
+	    }
+
+	  /* Destory the record in the next */
+	  record_list_release_next (record_list);
+	}
+
+      /* Record registers change to list as an instruction */
+      record_arch_list_head = NULL;
+      record_arch_list_tail = NULL;
+      record_regcache = get_current_regcache ();
+      if (record_arch_list_add_mem (offset, len))
+	{
+	  record_list_release (record_arch_list_tail);
+	  fprintf_unfiltered (gdb_stdlog, _("Record: record message error."));
+	  return -1;
+	}
+      if (record_arch_list_add_end (0))
+	{
+	  record_list_release (record_arch_list_tail);
+	  fprintf_unfiltered (gdb_stdlog, _("Record: record message error."));
+	  return -1;
+	}
+      record_list->next = record_arch_list_head;
+      record_arch_list_head->prev = record_list;
+      record_list = record_arch_list_tail;
+    }
+
+  return record_ops.beneath->to_xfer_partial (ops, object, annex, readbuf,
+					      writebuf, offset, len);
+}
+
+static int
+record_insert_breakpoint (struct bp_target_info *bp_tgt)
+{
+  if (!RECORD_IS_REPLAY)
+    {
+      return record_ops.beneath->to_insert_breakpoint (bp_tgt);
+    }
+
+  return 0;
+}
+
+static int
+record_remove_breakpoint (struct bp_target_info *bp_tgt)
+{
+  if (!RECORD_IS_REPLAY)
+    {
+      return record_ops.beneath->to_remove_breakpoint (bp_tgt);
+    }
+
+  return 0;
+}
+
+static enum exec_direction_kind
+record_get_execdir (void)
+{
+  if (record_debug > 1)
+    printf_filtered ("Record: execdir is %s\n",
+		     record_execdir == EXEC_FORWARD ? "forward" :
+		     record_execdir == EXEC_REVERSE ? "reverse" : "unknown");
+  return record_execdir;
+}
+
+static int
+record_set_execdir (enum exec_direction_kind dir)
+{
+  if (record_debug)
+    printf_filtered ("Record: set execdir: %s\n",
+		     dir == EXEC_FORWARD ? "forward" :
+		     dir == EXEC_REVERSE ? "reverse" : "bad direction");
+
+  /* FIXME: check target for capability.  */
+  if (dir == EXEC_FORWARD || dir == EXEC_REVERSE)
+    return (record_execdir = dir);
+  else
+    return EXEC_ERROR;
+}
+
+static void
+init_record_ops (void)
+{
+  record_ops.to_shortname = "record";
+  record_ops.to_longname = "Record and reverse target";
+  record_ops.to_doc =
+    "Record the program running message and replay this message.";
+  record_ops.to_open = record_open;
+  record_ops.to_close = record_close;
+  record_ops.to_resume = record_resume;
+  record_ops.to_wait = record_wait;
+  record_ops.to_disconnect = record_disconnect;
+  record_ops.to_detach = record_detach;
+  record_ops.to_kill = record_kill;
+  record_ops.to_create_inferior = find_default_create_inferior;	/* Make record suppport command "run". */
+  record_ops.to_prepare_to_store = record_prepare_to_store;
+  record_ops.to_xfer_partial = record_xfer_partial;
+  record_ops.to_insert_breakpoint = record_insert_breakpoint;
+  record_ops.to_remove_breakpoint = record_remove_breakpoint;
+  record_ops.to_get_execdir = record_get_execdir;
+  record_ops.to_set_execdir = record_set_execdir;
+  record_ops.to_stratum = record_stratum;
+  record_ops.to_magic = OPS_MAGIC;
+}
+
+static void
+show_record_debug (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Debugging of record target is %s.\n"), value);
+}
+
+static void
+cmd_record_start (char *args, int from_tty)
+{
+  execute_command ("target record", from_tty);
+}
+
+static void
+cmd_record_delete (char *args, int from_tty)
+{
+  if (RECORD_IS_USED)
+    {
+      if (RECORD_IS_REPLAY)
+	{
+	  if (!from_tty || query (_
+				  ("Record: delete the next running messages and begin to record the running message at current address?")))
+	    {
+	      record_list_release_next (record_list);
+	    }
+	}
+      else
+	{
+	  printf_unfiltered (_
+			     ("Record: GDB already at the end of record list.\n"));
+	}
+
+    }
+  else
+    {
+      printf_unfiltered (_("Record: record target is not started.\n"));
+    }
+}
+
+static void
+cmd_record_stop (char *args, int from_tty)
+{
+  if (RECORD_IS_USED)
+    {
+      if (!record_list || !from_tty || query (_
+					      ("Record: delete all the record messages and stop record target?")))
+	{
+	  unpush_target (&record_ops);
+	}
+    }
+  else
+    {
+      printf_unfiltered (_("Record: record target is not started.\n"));
+    }
+}
+
+void
+_initialize_record (void)
+{
+  /* init record_maskall */
+  if (sigfillset (&record_maskall) == -1)
+    {
+      perror_with_name (_("Record: sigfillset"));
+    }
+
+  /* init record_first */
+  record_first.prev = NULL;
+  record_first.next = NULL;
+  record_first.type = record_end;
+  record_first.u.need_dasm = 0;
+
+  init_record_ops ();
+  add_target (&record_ops);
+
+  add_setshow_zinteger_cmd ("record", no_class, &record_debug,
+			    _("Set record debugging."),
+			    _("Show record debugging."),
+			    _
+			    ("When non-zero, record specific debugging is enabled."),
+			    NULL, show_record_debug, &setdebuglist,
+			    &showdebuglist);
+
+  add_com ("record", class_obscure, cmd_record_start,
+	   _("Same with command \"target record\"."));
+  add_com_alias ("rec", "record", class_obscure, 1);
+
+  /* XXX: I try to use some simple commands such as "disconnect" and "detach"
+     to support this functions. But these commands all have other affect to
+     GDB such as call function "no_shared_libraries". So I add special commands
+     to GDB. */
+  add_com ("delrecord", class_obscure, cmd_record_delete,
+	   _
+	   ("When record target running in replay mode, delete the next running messages and begin to record the running message at current address."));
+  add_com_alias ("dr", "delrecord", class_obscure, 1);
+  add_com ("stoprecord", class_obscure, cmd_record_stop,
+	   _("Stop the record target."));
+  add_com_alias ("sr", "stoprecord", class_obscure, 1);
+}
diff --git a/gdb/record.h b/gdb/record.h
new file mode 100644
index 0000000..2547dab
--- /dev/null
+++ b/gdb/record.h
@@ -0,0 +1,86 @@
+/* Record v0.1.5 for GDB, the GNU debugger.
+   Written by Hui Zhu <teawater@gmail.com>
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _RECORD_H_
+#define _RECORD_H_
+
+#define RECORD_IS_USED		(current_target.beneath == &record_ops)
+#define RECORD_IS_REPLAY	(record_list->next || record_execdir == EXEC_REVERSE)
+
+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 int record_debug;
+extern record_t *record_list;
+extern record_t *record_arch_list_head;
+extern record_t *record_arch_list_tail;
+extern struct regcache *record_regcache;
+
+extern struct target_ops record_ops;
+extern int record_resume_step;
+extern int record_regcache_raw_write_regnum;
+extern enum exec_direction_kind record_execdir;
+
+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 void record_message (struct gdbarch *gdbarch);
+extern void record_not_record_set (void);
+#endif /* _RECORD_H_ */
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 199b626..bf54bb7 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -29,6 +29,7 @@
 #include "gdb_string.h"
 #include "gdbcmd.h"		/* For maintenanceprintlist.  */
 #include "observer.h"
+#include "record.h"
 
 /*
  * DATA STRUCTURE
@@ -658,6 +659,7 @@ regcache_raw_write (struct regcache *regcache, int regnum,
   old_chain = save_inferior_ptid ();
   inferior_ptid = regcache->ptid;
 
+  record_regcache_raw_write_regnum = regnum;
   target_prepare_to_store (regcache);
   memcpy (register_buffer (regcache, regnum), buf,
 	  regcache->descr->sizeof_register[regnum]);
diff --git a/gdb/target.h b/gdb/target.h
index 296781b..47b45f2 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -62,7 +62,8 @@ enum strata
     file_stratum,		/* Executable files, etc */
     core_stratum,		/* Core dump files */
     process_stratum,		/* Executing processes */
-    thread_stratum		/* Executing threads */
+    thread_stratum,		/* Executing threads */
+    record_stratum		/* Support record debugging */
   };
 
 enum thread_control_capabilities

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