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


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

GDB record patch 0.1.3 for GDB-6.8 release (It make I386-Linux GDB support Reversible Debugging)


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.

Record 0.1.3 support sysenter syscall. Then it can be use with Linux kernel 2.6 system call.(In the before, I just tested record on Linux kernel 2.4. So I forgot that the syscall in Linux kernel 2.6 is different with Linux kernel 2.4. Sorry about it.)
The other change of record 0.1.3 is that the GDB prompt will auto change to "(rec)" when the record function is started. And it will change to "(rev)" when the reverse function is started. When the record function is stooped, the GDB prompt will be change back to "(gdb)"  It make GDB mode is more clear than before. (I always forgot the mode of GDB when I use the record function. So I add this function. )

More information can be obtained want to http://sourceforge.net/projects/record/. You can get the patch and the GDB that patched in there.

Record patch add 3 commands to GDB:
record(rec)		Use to start the record and reverse function.
stoprecord(srec)	Use to stop the record and reverse function.
reverse(rev)		When the record and reverse function is started, It use to set GDB to the reverse debug mode or the normal debug mode. When GDB is set to the reverse debug mode, you can use GDB commands (Such as continue, step, print) to control and debug the program.

To make and install the GDB record patch 0.1.3 with GDB-6.8:
tar vxjf gdb-6.8.tar.bz2
cp gdb-6.8-record-0.1.3.patch gdb-6.8/
cd gdb-6.8
patch -p1 < gdb-6.8-record-0.1.3.patch
cd ..
mkdir bgdb68
cd bgdb68
../gdb-6.8/configure
make
make install
gdbrecord

The following is how to use the record:
cat 1.c
int     a = 0;
void
cool2 ()
{
	printf ("a = %d\n", a);
}
int
cool ()
{
       a += 3;

cool2();

       return (a);
}
int
main()
{
       int     b = 0;
       int     c = 1;

	printf ("a = %d b = %d c = %d\n", a, b, c);
       b = cool ();
	printf ("a = %d b = %d c = %d\n", a, b, c);

       c += 1;
	printf ("a = %d b = %d c = %d\n", a, b, c);
       a -= 2;
	printf ("a = %d b = %d c = %d\n", a, b, c);

return (0);
}
gcc -g 1.c
gdbrecord a.out
GNU gdb 6.8
Record 0.1.3
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Setting up the environment for debugging gdb.
Function "internal_error" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Function "info_command" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
/media/disk/bgdb68/gdb/.gdbinit:8: Error in sourced command file:
No breakpoint number 0.
(gdb) b main
Breakpoint 1 at 0x80483c1: file 1.c, line 19.
(gdb) r a.out Starting program: /media/disk/bgdb68/gdb/a.out a.out


Breakpoint 1, main () at 1.c:19
19 int b = 0;
(gdb) rec
record: record and reverse function is started.
(rec) n
During symbol reading, incomplete CFI data; unspecified registers (e.g., eax) at 0x80483be.
20 int c = 1;
(rec) 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) During symbol reading, incomplete CFI data; DW_CFA_restore unspecified
register ebp (#5) at 0xffffe411.
a = 0 b = 0 c = 1
23 b = cool ();
(rec) b
Breakpoint 2 at 0x80483f3: file 1.c, line 23.
(rec) rev
record: GDB is set to reverse debug mode.
(rev) n
0x080483ee 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rev) 20 int c = 1;
(rev) rev
record: GDB is set to normal debug mode.
(rec) c
Continuing.


Breakpoint 2, main () at 1.c:23
23 b = cool ();
(rec) n
a = 3
24 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) c
Continuing.
a = 3 b = 3 c = 1
a = 3 b = 3 c = 2
a = 1 b = 3 c = 2
The next instruction is syscall exit_group. It will make the program exit. Do you want to pause the program.([y] or n) 0xffffe405 in __kernel_vsyscall ()
record: record pause the program.
(rec) rev
record: GDB is set to reverse debug mode.
(rev) c
Continuing.


Breakpoint 2, main () at 1.c:23
23              b = cool ();
(rev) c
Continuing.

Breakpoint 1, main () at 1.c:19
19 int b = 0;
(rev) c
Continuing.
record: running to the begin of record list.
main () at 1.c:19
19 int b = 0;
(rev) rev
record: GDB is set to normal debug mode.
(rec) n
20 int c = 1;
(rec) 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) rec
record: record and reverse function has already been started.
(rec) srec
record: record and reverse function is stopped.
(gdb) c
Continuing.
a = 0 b = 0 c = 1


Breakpoint 2, main () at 1.c:23
23              b = cool ();
(gdb) c
Continuing.
a = 3
a = 3 b = 3 c = 1
a = 3 b = 3 c = 2
a = 1 b = 3 c = 2

Program exited normally.
(gdb) quit
Breakpoint 1 at 0x80483c1: file 1.c, line 19.
(gdb) r a.out Starting program: /media/disk/bgdb68/gdb/a.out a.out


Breakpoint 1, main () at 1.c:19
19 int b = 0;
(gdb) rec
record: record and reverse function is started.
(rec) n
During symbol reading, incomplete CFI data; unspecified registers (e.g., eax) at 0x80483be.
20 int c = 1;
(rec) 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) During symbol reading, incomplete CFI data; DW_CFA_restore unspecified
register ebp (#5) at 0xffffe411.
a = 0 b = 0 c = 1
23 b = cool ();
(rec) b
Breakpoint 2 at 0x80483f3: file 1.c, line 23.
(rec) rev
record: GDB is set to reverse debug mode.
(rev) n
0x080483ee 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rev) 20 int c = 1;
(rev) rev
record: GDB is set to normal debug mode.
(rec) c
Continuing.


Breakpoint 2, main () at 1.c:23
23 b = cool ();
(rec) n
a = 3
24 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) c
Continuing.
a = 3 b = 3 c = 1
a = 3 b = 3 c = 2
a = 1 b = 3 c = 2
The next instruction is syscall exit_group. It will make the program exit. Do you want to pause the program.([y] or n) 0xffffe405 in __kernel_vsyscall ()
record: record pause the program.
(rec) rev
record: GDB is set to reverse debug mode.
(rev) c
Continuing.


Breakpoint 2, main () at 1.c:23
23              b = cool ();
(rev) c
Continuing.

Breakpoint 1, main () at 1.c:19
19 int b = 0;
(rev) c
Continuing.
record: running to the begin of record list.
main () at 1.c:19
19 int b = 0;
(rev) rev
record: GDB is set to normal debug mode.
(rec) n
20 int c = 1;
(rec) 22 printf ("a = %d b = %d c = %d\n", a, b, c);
(rec) rec
record: record and reverse function has already been started.
(rec) srec
record: record and reverse function is stopped.
(gdb) c
Continuing.
a = 0 b = 0 c = 1


Breakpoint 2, main () at 1.c:23
23              b = cool ();
(gdb) c
Continuing.
a = 3
a = 3 b = 3 c = 1
a = 3 b = 3 c = 2
a = 1 b = 3 c = 2

Program exited normally.
(gdb) quit


Patch to make make I386-Linux GDB support Reversible Debugging
http://sourceforge.net/projects/record/

Signed-off-by: Hui Zhu <hui.zhu@windriver.com>
---
 Makefile.in       |   14 
 gdbarch.c         |   49 +
 gdbarch.h         |   10 
 i386-linux-tdep.c | 2044 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 i386-tdep.c       | 2097 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 i386-tdep.h       |    5 
 infcmd.c          |   40 +
 inferior.h        |    3 
 infrun.c          |  126 +++
 mips-tdep.c       |  623 ++++++++++++++++
 record.c          |  471 ++++++++++++
 record.h          |   64 +
 target.c          |   19 
 target.h          |    5 
 top.c             |    4 
 15 files changed, 5564 insertions(+), 10 deletions(-)

--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -230,6 +230,10 @@ struct gdbarch
   gdbarch_core_read_description_ftype *core_read_description;
   gdbarch_static_transform_name_ftype *static_transform_name;
   int sofun_address_maybe_missing;
+/*teawater rec begin----------------------------------------------------------*/
+	gdbarch_record_ftype		*record;
+	gdbarch_record_dasm_ftype	*record_dasm;
+/*teawater rec end------------------------------------------------------------*/
 };
 
 
@@ -352,6 +356,10 @@ struct gdbarch startup_gdbarch =
   0,  /* core_read_description */
   0,  /* static_transform_name */
   0,  /* sofun_address_maybe_missing */
+/*teawater rec begin----------------------------------------------------------*/
+  NULL,
+  NULL,
+/*teawater rec end------------------------------------------------------------*/
   /* startup_gdbarch() */
 };
 
@@ -3391,6 +3399,47 @@ deprecated_current_gdbarch_select_hack (
   reinit_frame_cache ();
 }
 
+/*teawater rec begin----------------------------------------------------------*/
+int
+gdbarch_record_p (struct gdbarch *gdbarch)
+{
+	gdb_assert (gdbarch != NULL);
+	return (gdbarch->record != NULL);
+}
+
+int
+gdbarch_record (struct gdbarch *gdbarch)
+{
+	gdb_assert (gdbarch != NULL);
+	gdb_assert (gdbarch->record != NULL);
+	if (gdbarch_debug >= 2)
+		fprintf_unfiltered (gdb_stdlog, "gdbarch_record called\n");
+	return (gdbarch->record ());
+}
+
+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 ();
+}
+
+void
+set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm)
+{
+	gdbarch->record_dasm = record_dasm;
+}
+/*teawater rec end------------------------------------------------------------*/
+
 extern void _initialize_gdbarch (void);
 
 void
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -900,4 +900,14 @@ extern int gdbarch_debug;
 
 extern void gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file);
 
+/*teawater rec begin----------------------------------------------------------*/
+extern int	gdbarch_record_p (struct gdbarch *gdbarch);
+typedef int	(gdbarch_record_ftype) (void);
+extern int	gdbarch_record (struct gdbarch *gdbarch);
+extern void	set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype *record);
+typedef void	(gdbarch_record_dasm_ftype) (void);
+extern void	gdbarch_record_dasm (struct gdbarch *gdbarch);
+extern void	set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm);
+/*teawater rec end------------------------------------------------------------*/
+
 #endif
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -35,6 +35,11 @@
 #include "solib-svr4.h"
 #include "symtab.h"
 
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+#include <stdint.h>
+/*teawater rec end------------------------------------------------------------*/
+
 /* Return the name of register REG.  */
 
 static const char *
@@ -335,6 +340,2041 @@ i386_linux_write_pc (struct regcache *re
      restarted.  */
   regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
 }
+
+/*teawater rec begin----------------------------------------------------------*/
+#include <sys/ptrace.h>
+#include <sys/ioctl.h>
+
+#define RECORD_SIZE__old_kernel_stat	32
+#define RECORD_SIZE_tms	16
+#define RECORD_SIZE_loff_t	8
+#define RECORD_SIZE_flock	16
+#define RECORD_SIZE_oldold_utsname	45
+#define RECORD_SIZE_ustat	20
+#define RECORD_SIZE_old_sigaction	140
+#define RECORD_SIZE_old_sigset_t	128
+#define RECORD_SIZE_rlimit	8
+#define RECORD_SIZE_rusage	72
+#define RECORD_SIZE_timeval	8
+#define RECORD_SIZE_timezone	8
+#define RECORD_SIZE_old_gid_t	2
+#define RECORD_SIZE_old_uid_t	2
+#define RECORD_SIZE_fd_set	128
+#define RECORD_SIZE_dirent	268
+#define RECORD_SIZE_dirent64	276
+#define RECORD_SIZE_statfs	64
+#define RECORD_SIZE_statfs64	84
+#define RECORD_SIZE_sockaddr	16
+#define RECORD_SIZE_int		4
+#define RECORD_SIZE_long	4
+#define RECORD_SIZE_ulong	4
+#define RECORD_SIZE_msghdr	28
+#define RECORD_SIZE_itimerval	16
+#define RECORD_SIZE_stat	88
+#define RECORD_SIZE_old_utsname	325
+#define RECORD_SIZE_rusage	72
+#define RECORD_SIZE_sysinfo	64
+#define RECORD_SIZE_msqid_ds	88
+#define RECORD_SIZE_shmid_ds	84
+#define RECORD_SIZE_new_utsname	390
+#define RECORD_SIZE_timex	128
+#define RECORD_SIZE_mem_dqinfo	24
+#define RECORD_SIZE_if_dqblk	68
+#define RECORD_SIZE_fs_quota_stat	68
+#define RECORD_SIZE_timespec	8
+#define RECORD_SIZE_pollfd	8
+#define RECORD_SIZE_NFS_FHSIZE	32
+#define RECORD_SIZE_knfsd_fh	132
+#define RECORD_SIZE_TASK_COMM_LEN	16
+#define RECORD_SIZE_sigaction	140
+#define RECORD_SIZE_sigset_t	8
+#define RECORD_SIZE_siginfo_t	128
+#define RECORD_SIZE_cap_user_data_t	12
+#define RECORD_SIZE_stack_t	12
+#define RECORD_SIZE_off_t	RECORD_SIZE_long
+#define RECORD_SIZE_stat64	96
+#define RECORD_SIZE_gid_t	2
+#define RECORD_SIZE_uid_t	2
+#define RECORD_SIZE_uid_t	2
+#define RECORD_SIZE_PAGE_SIZE	4096
+#define RECORD_SIZE_flock64	24
+#define RECORD_SIZE_user_desc	16
+#define RECORD_SIZE_io_event	32
+#define RECORD_SIZE_iocb	64
+#define RECORD_SIZE_epoll_event	12
+#define RECORD_SIZE_itimerspec	(RECORD_SIZE_timespec * 2)
+#define RECORD_SIZE_mq_attr	32
+#define RECORD_SIZE_siginfo	128
+#define RECORD_SIZE_rusage	72
+
+#define RECORD_SYS_SOCKET	1
+#define RECORD_SYS_BIND		2
+#define RECORD_SYS_CONNECT	3
+#define RECORD_SYS_LISTEN	4
+#define RECORD_SYS_ACCEPT	5
+#define RECORD_SYS_GETSOCKNAME	6
+#define RECORD_SYS_GETPEERNAME	7
+#define RECORD_SYS_SOCKETPAIR	8
+#define RECORD_SYS_SEND		9
+#define RECORD_SYS_RECV		10
+#define RECORD_SYS_SENDTO	11
+#define RECORD_SYS_RECVFROM	12
+#define RECORD_SYS_SHUTDOWN	13
+#define RECORD_SYS_SETSOCKOPT	14
+#define RECORD_SYS_GETSOCKOPT	15
+#define RECORD_SYS_SENDMSG	16
+#define RECORD_SYS_RECVMSG	17
+
+#define RECORD_SEMOP		1
+#define RECORD_SEMGET		2
+#define RECORD_SEMCTL		3
+#define RECORD_SEMTIMEDOP	4
+#define RECORD_MSGSND		11
+#define RECORD_MSGRCV		12
+#define RECORD_MSGGET		13
+#define RECORD_MSGCTL		14
+#define RECORD_SHMAT		21
+#define RECORD_SHMDT		22
+#define RECORD_SHMGET		23
+#define RECORD_SHMCTL		24
+
+#define RECORD_Q_GETFMT		0x800004
+#define RECORD_Q_GETINFO	0x800005
+#define RECORD_Q_GETQUOTA	0x800007
+#define RECORD_Q_XGETQSTAT	(('5'<<8)+(5))
+#define RECORD_Q_XGETQUOTA	(('3'<<8)+(3))
+
+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, 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 == PTRACE_PEEKTEXT || tmpu32 == PTRACE_PEEKDATA || tmpu32 == PTRACE_PEEKUSER) {
+				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, 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 FIOCLEX:
+				case FIONCLEX:
+				case FIONBIO:
+				case FIOASYNC:
+					break;
+				case FIOQSIZE:
+					regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, 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, 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, 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, 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, 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, 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, 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, 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, RECORD_SIZE_timeval)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, 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, 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, RECORD_SIZE_fd_set)) {
+					return (-1);
+				}
+				if (record_arch_list_add_mem (sel.outp, RECORD_SIZE_fd_set)) {
+					return (-1);
+				}
+				if (record_arch_list_add_mem (sel.exp, RECORD_SIZE_fd_set)) {
+					return (-1);
+				}
+				if (record_arch_list_add_mem (sel.tvp, 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, 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, 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 RECORD_SYS_SOCKET:
+				case RECORD_SYS_BIND:
+				case RECORD_SYS_CONNECT:
+				case RECORD_SYS_LISTEN:
+					break;
+				case RECORD_SYS_ACCEPT:
+				case RECORD_SYS_GETSOCKNAME:
+				case 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], RECORD_SIZE_sockaddr)) {
+							return (-1);
+						}
+						if (record_arch_list_add_mem (a[2], RECORD_SIZE_int)) {
+							return (-1);
+						}
+					}
+				}
+					break;
+				
+				case 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], RECORD_SIZE_int)) {
+							return (-1);
+						}
+					}
+				}
+					break;
+				case RECORD_SYS_SEND:
+				case RECORD_SYS_SENDTO:
+					break;
+				case 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 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], RECORD_SIZE_sockaddr)) {
+								return (-1);
+							}
+							if (record_arch_list_add_mem (a[5], RECORD_SIZE_int)) {
+								return (-1);
+							}
+						}
+					}
+				}
+					break;
+				case RECORD_SYS_SHUTDOWN:
+				case RECORD_SYS_SETSOCKOPT:
+					break;
+				case 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], RECORD_SIZE_int)) {
+								return (-1);
+							}
+						}
+					}
+				}
+					break;
+				case RECORD_SYS_SENDMSG:
+					break;
+				case 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], 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, 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, 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, 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, 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, RECORD_SIZE_int)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, RECORD_SIZE_sysinfo)) {
+				return (-1);
+			}
+			break;
+
+		/* sys_ipc */
+		case 117:
+			regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32);
+			switch (tmpu32) {
+				case 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 + RECORD_SIZE_long)) {
+						return (-1);
+					}
+				}
+					break;
+				case RECORD_MSGCTL:
+					regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_msqid_ds)) {
+						return (-1);
+					}
+					break;
+				case RECORD_SHMAT:
+					regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_ulong)) {
+						return (-1);
+					}
+					break;
+				case RECORD_SHMCTL:
+					regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, 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, 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, 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, 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 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 RECORD_Q_GETINFO:
+					regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_mem_dqinfo)) {
+						return (-1);
+					}
+					break;
+				case RECORD_Q_GETQUOTA:
+					regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_if_dqblk)) {
+						return (-1);
+					}
+					break;
+				case RECORD_Q_XGETQSTAT:
+				case RECORD_Q_XGETQUOTA:
+					regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+					if (record_arch_list_add_mem (tmpu32, 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, 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, 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, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, 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, 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, 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, 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, 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, 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 = RECORD_SIZE_NFS_FHSIZE;
+				}
+				else {
+					rsize = 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, RECORD_SIZE_uid_t)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_uid_t)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, RECORD_SIZE_gid_t)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_gid_t)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, 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, 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, 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, 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, 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, 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, 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 * 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 * RECORD_SIZE_int);
+				if (target_read_memory (tmpu32, (gdb_byte *)iocbp, nr * RECORD_SIZE_int)) {
+					fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), nr * RECORD_SIZE_int);
+					return (-1);
+				}
+				for (i = 0; i < nr; i++) {
+					if (record_arch_list_add_mem (iocbp[i], 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, 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 * 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, 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, 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, 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, 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, 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, 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, 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, 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 * 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, 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, 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, RECORD_SIZE_siginfo)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, 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, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, RECORD_SIZE_pollfd * nfds)) {
+					return (-1);
+				}
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, RECORD_SIZE_int)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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, RECORD_SIZE_loff_t)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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 * 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, RECORD_SIZE_int)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) {
+				return (-1);
+			}
+			regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32);
+			if (record_arch_list_add_mem (tmpu32, 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 * 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);
+}
+/*teawater rec end------------------------------------------------------------*/
+
 
 
 /* The register sets used in GNU/Linux ELF core-dumps are identical to
@@ -428,6 +2468,10 @@ i386_linux_init_abi (struct gdbarch_info
   tdep->sigcontext_addr = i386_linux_sigcontext_addr;
   tdep->sc_reg_offset = i386_linux_sc_reg_offset;
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
+/*teawater rec begin----------------------------------------------------------*/
+  tdep->intx80_record = i386_linux_intx80_sysenter_record;
+  tdep->sysenter_record = i386_linux_intx80_sysenter_record;
+/*teawater rec end------------------------------------------------------------*/
 
   /* N_FUN symbols in shared libaries have 0 for their values and need
      to be relocated. */
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -49,6 +49,11 @@
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+#include <stdint.h>
+/*teawater rec end------------------------------------------------------------*/
+
 /* Register names.  */
 
 static char *i386_register_names[] =
@@ -2315,6 +2320,2094 @@ i386_fetch_pointer_argument (struct fram
   return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4);
 }
 
+/*teawater rec begin----------------------------------------------------------*/
+#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;
+
+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);
+}
+
+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;
+		}
+
+#if 0
+		if (override) {
+			/* *addr += ((uint32_t)read_register (override)) << 4; */
+			printf_unfiltered (_("record: cann't get the value of the segment register.\n"));
+			return (-1);
+		}
+#endif
+	}
+	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;
+
+#if 0
+no_rm:
+		if (override) {
+			/* *addr += ((uint32_t)read_register (override)) << 4; */
+			printf_unfiltered (_("record: cann't get the value of the segment register.\n"));
+			return (-1);
+		}
+#endif
+	}
+
+no_rm:
+	return (0);
+}
+
+static int
+i386_record_lea_modrm ()
+{
+	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);
+}
+
+static int
+i386_record (void)
+{
+	int		prefixes = 0;
+	uint8_t		tmpu8;
+	uint16_t	tmpu16;
+	uint32_t	tmpu32;
+	uint32_t	opcode;
+	int		need_dasm = 0;
+
+	i386_record_pc = read_pc ();
+	aflag = 1;
+	dflag = 1;
+	override = 0;
+
+	if (debug_record) {
+		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 (current_gdbarch)->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 (current_gdbarch)->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 (current_gdbarch)->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 (current_gdbarch)->sysenter_record ();
+				if (ret) {
+					return (ret);
+				}
+			}
+			break;
+
+		/* sysexit */
+		case 0x0f35:
+			printf_unfiltered (_("record: record and reverse function don't support instruction sysexit.\n"));
+			i386_record_pc -= 2;
+			goto no_support;
+			break;
+
+		/* cpuid */
+		case 0x0fa2:
+			if (record_arch_list_add_reg (I386_EAX_REGNUM)) {
+				return (-1);
+			}
+			if (record_arch_list_add_reg (I386_ECX_REGNUM)) {
+				return (-1);
+			}
+			if (record_arch_list_add_reg (I386_EDX_REGNUM)) {
+				return (-1);
+			}
+			if (record_arch_list_add_reg (I386_EBX_REGNUM)) {
+				return (-1);
+			}
+			break;
+
+		/* hlt */
+		case 0xf4:
+			printf_unfiltered (_("record: record and reverse function don't support instruction hlt.\n"));
+			i386_record_pc -= 1;
+			goto no_support;
+			break;
+
+		case 0x0f00:
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			switch (reg) {
+				/* sldt */
+				case 0:
+				/* str */
+				case 1:
+					if (mod == 3) {
+						if (record_arch_list_add_reg (rm)) {
+							return (-1);
+						}
+					}
+					else {
+						ot = OT_WORD;
+						if (i386_record_lea_modrm ()) {
+							return (-1);
+						}
+					}
+					break;
+				/* lldt */
+				case 2:
+				/* ltr */
+				case 3:
+					break;
+				/* verr */
+				case 4:
+				/* verw */
+				case 5:
+					if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) {
+						return (-1);
+					}
+					break;
+				default:
+					i386_record_pc -= 3;
+					opcode = opcode << 8 | modrm;
+					goto no_support;
+					break;
+			}
+			break;
+
+		case 0x0f01:
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			switch(reg) {
+				/* sgdt */
+				case 0: {
+						uint32_t	addr;
+
+						if (mod == 3) {
+							i386_record_pc -= 3;
+							opcode = opcode << 8 | modrm;
+							goto no_support;
+						}
+
+						if (override) {
+							printf_unfiltered (_("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"), paddr_nz (read_pc ()));
+						}
+						else {
+							if (i386_record_lea_modrm_addr (&addr)) {
+								return (-1);
+							}
+							if (record_arch_list_add_mem (addr, 2)) {
+								return (-1);
+							}
+							addr += 2;
+							if (record_arch_list_add_mem (addr, 4)) {
+								return (-1);
+							}
+						}
+					}
+					break;
+				case 1:
+					if (mod == 3) {
+						switch (rm) {
+							/* monitor */
+							case 0:
+								break;
+							/* mwait */
+							case 1:
+								if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) {
+									return (-1);
+								}
+								break;
+							default:
+								i386_record_pc -= 3;
+								opcode = opcode << 8 | modrm;
+								goto no_support;
+								break;
+						}
+					}
+					else {
+						/* sidt */
+						if (override) {
+							printf_unfiltered (_("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"), paddr_nz (read_pc ()));
+						}
+						else {
+							uint32_t	addr;
+
+							if (i386_record_lea_modrm_addr (&addr)) {
+								return (-1);
+							}
+							if (record_arch_list_add_mem (addr, 2)) {
+								return (-1);
+							}
+							addr += 2;
+							if (record_arch_list_add_mem (addr, 4)) {
+								return (-1);
+							}
+						}
+					}
+					break;
+				/* lgdt */
+				case 2:
+				/* lidt */
+				case 3:
+				/* invlpg */
+				case 7:
+				default:
+					if (mod == 3) {
+						i386_record_pc -= 3;
+						opcode = opcode << 8 | modrm;
+						goto no_support;
+					}
+					break;
+				/* smsw */
+				case 4:
+					if (mod == 3) {
+						if (record_arch_list_add_reg (rm)) {
+							return (-1);
+						}
+					}
+					else {
+						ot = OT_WORD;
+						if (i386_record_lea_modrm ()) {
+							return (-1);
+						}
+					}
+					break;
+				/* lmsw */
+				case 6:
+					break;
+			}
+			break;
+
+		/* invd */
+		case 0x0f08:
+		/* wbinvd */
+		case 0x0f09:
+			break;
+
+		/* arpl */
+		case 0x63:
+			ot = dflag ? OT_LONG : OT_WORD;
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			if (mod != 3) {
+				if (i386_record_lea_modrm ()) {
+					return (-1);
+				}
+			}
+			else {
+				if (record_arch_list_add_reg (rm)) {
+					return (-1);
+				}
+			}
+			if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) {
+				return (-1);
+			}
+			break;
+
+		/* lar */
+		case 0x0f02:
+		/* lsl */
+		case 0x0f03:
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			if (record_arch_list_add_reg (reg)) {
+				return (-1);
+			}
+			if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) {
+				return (-1);
+			}
+			break;
+
+		case 0x0f18:
+			break;
+
+		/* nop (multi byte) */
+		case 0x0f19 ... 0x0f1f:
+			break;
+
+		/* mov reg, crN */
+		case 0x0f20:
+		/* mov crN, reg */
+		case 0x0f22:
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			if ((modrm & 0xc0) != 0xc0) {
+				i386_record_pc -= 2;
+				opcode = opcode << 8 | modrm;
+				goto no_support;
+			}
+			switch(reg) {
+				case 0:
+				case 2:
+				case 3:
+				case 4:
+				case 8:
+					if (opcode & 2) {
+					}
+					else {
+						if (record_arch_list_add_reg (rm)) {
+							return (-1);
+						}
+					}
+					break;
+				default:
+					i386_record_pc -= 2;
+					opcode = opcode << 8 | modrm;
+					goto no_support;
+					break;
+			}
+			break;
+
+		/* mov reg, drN */
+		case 0x0f21:
+		/* mov drN, reg */
+		case 0x0f23:
+			if (i386_record_modrm ()) {
+				return (-1);
+			}
+			if ((modrm & 0xc0) != 0xc0 || reg == 4 || reg == 5 || reg >= 8) {
+				i386_record_pc -= 2;
+				opcode = opcode << 8 | modrm;
+				goto no_support;
+			}
+			if (opcode & 2) {
+			}
+			else {
+				if (record_arch_list_add_reg (rm)) {
+					return (-1);
+				}
+			}
+			break;
+
+		/* clts */
+		case 0x0f06:
+			break;
+
+		/* MMX/SSE/SSE2/PNI support */
+		/* XXX */
+
+		default:
+			if (opcode > 0xff) {
+				i386_record_pc -= 2;
+			}
+			else {
+				i386_record_pc -= 1;
+			}
+			goto no_support;
+			break;
+	}
+
+	if (!need_dasm) {
+		if (record_arch_list_add_reg (I386_EIP_REGNUM)) {
+			return (-1);
+		}
+	}
+	if (record_arch_list_add_end (need_dasm)) {
+		return (-1);
+	}
+
+	return (0);
+
+no_support:
+	printf_unfiltered (_("record: record and reverse function don't support instruction 0x%02x at address 0x%s.\n"), (unsigned int)(opcode), paddr_nz (i386_record_pc));
+	return (-1);
+}
+/*teawater rec end------------------------------------------------------------*/
+
 
 static struct gdbarch *
 i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
@@ -2503,6 +4596,10 @@ i386_gdbarch_init (struct gdbarch_info i
   if (tdep->mm0_regnum == 0)
     tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
 
+/*teawater rec begin----------------------------------------------------------*/
+  set_gdbarch_record (gdbarch, i386_record);
+/*teawater rec end------------------------------------------------------------*/
+
   return gdbarch;
 }
 
--- a/gdb/i386-tdep.h
+++ b/gdb/i386-tdep.h
@@ -106,6 +106,11 @@ struct gdbarch_tdep
   /* ISA-specific data types.  */
   struct type *i386_mmx_type;
   struct type *i386_sse_type;
+
+/*teawater rec begin----------------------------------------------------------*/
+	int (*intx80_record) (void);
+	int (*sysenter_record) (void);
+/*teawater rec end------------------------------------------------------------*/
 };
 
 /* Floating-point registers.  */
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -49,6 +49,10 @@
 #include "target-descriptions.h"
 #include "user-regs.h"
 
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+/*teawater rec end------------------------------------------------------------*/
+
 /* Functions exported for general use, in inferior.h: */
 
 void all_registers_info (char *, int);
@@ -188,6 +192,9 @@ CORE_ADDR step_range_end;	/* Exclusive *
    and how to set the frame for the breakpoint used to step out.  */
 
 struct frame_id step_frame_id;
+/*teawater rec begin----------------------------------------------------------*/
+struct frame_id step_prev_frame_id;
+/*teawater rec end------------------------------------------------------------*/
 
 enum step_over_calls_kind step_over_calls;
 
@@ -737,6 +744,17 @@ step_1 (int skip_subroutines, int single
 	  if (!frame)		/* Avoid coredump here.  Why tho? */
 	    error (_("No current frame"));
 	  step_frame_id = get_frame_id (frame);
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_reverse) {
+		frame = get_prev_frame (frame);
+		if (frame) {
+			step_prev_frame_id = get_frame_id (frame);
+		}
+		else {
+			step_prev_frame_id = null_frame_id;
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
 
 	  if (!single_inst)
 	    {
@@ -836,6 +854,17 @@ step_once (int skip_subroutines, int sin
       if (!frame)		/* Avoid coredump here.  Why tho? */
 	error (_("No current frame"));
       step_frame_id = get_frame_id (frame);
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_reverse) {
+		frame = get_prev_frame (frame);
+		if (frame) {
+			step_prev_frame_id = get_frame_id (frame);
+		}
+		else {
+			step_prev_frame_id = null_frame_id;
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
 
       if (!single_inst)
 	{
@@ -1088,6 +1117,17 @@ until_next_command (int from_tty)
 
   step_over_calls = STEP_OVER_ALL;
   step_frame_id = get_frame_id (frame);
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_reverse) {
+		frame = get_prev_frame (frame);
+		if (frame) {
+			step_prev_frame_id = get_frame_id (frame);
+		}
+		else {
+			step_prev_frame_id = null_frame_id;
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
 
   step_multi = 0;		/* Only one call to proceed */
 
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -317,6 +317,9 @@ extern CORE_ADDR step_range_end;	/* Excl
    and how to set the frame for the breakpoint used to step out.  */
 
 extern struct frame_id step_frame_id;
+/*teawater rec begin----------------------------------------------------------*/
+extern struct frame_id step_prev_frame_id;
+/*teawater rec end------------------------------------------------------------*/
 
 /* 1 means step over all subroutine calls.
    -1 means step over calls to undebuggable functions.  */
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -49,6 +49,11 @@
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+static int		record_resume_step = 0;
+/*teawater rec end------------------------------------------------------------*/
+
 /* Prototypes for local functions */
 
 static void signals_info (char *, int);
@@ -518,6 +523,20 @@ resume (int step, enum target_signal sig
     fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d)\n",
 			step, sig);
 
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_recording) {
+		if (record_list && (record_list->next || gdb_is_reverse)) {
+			discard_cleanups (old_cleanups);
+			record_wait_step = step;
+			return;
+		}
+		else {
+			step = 1;
+			record_message ();
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
+
   /* FIXME: calling breakpoint_here_p (read_pc ()) three times! */
 
 
@@ -1026,10 +1045,19 @@ wait_for_inferior (int treat_exec_as_sig
 
   while (1)
     {
+/*teawater rec begin----------------------------------------------------------*/
+	if (record_list && (record_list->next || gdb_is_reverse)) {
+		ecs->ptid = record_wait (ecs->waiton_ptid, ecs->wp);
+	}
+	else {
+/*teawater rec end------------------------------------------------------------*/
       if (deprecated_target_wait_hook)
 	ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp);
       else
 	ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp);
+/*teawater rec begin----------------------------------------------------------*/
+	}
+/*teawater rec end------------------------------------------------------------*/
 
       if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
         {
@@ -2003,11 +2031,19 @@ handle_inferior_event (struct execution_
          be necessary for call dummies on a non-executable stack on
          SPARC.  */
 
-      if (stop_signal == TARGET_SIGNAL_TRAP)
-	ecs->random_signal
-	  = !(bpstat_explains_signal (stop_bpstat)
-	      || stepping_over_breakpoint
-	      || (step_range_end && step_resume_breakpoint == NULL));
+/*teawater rec begin----------------------------------------------------------*/
+      if (stop_signal == TARGET_SIGNAL_TRAP) {
+		if (gdb_is_reverse || gdb_is_recording) {
+			ecs->random_signal = 0;
+		}
+		else {
+			ecs->random_signal
+			  = !(bpstat_explains_signal (stop_bpstat)
+			      || stepping_over_breakpoint
+			      || (step_range_end && step_resume_breakpoint == NULL));
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
       else
 	{
 	  ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
@@ -2489,6 +2525,16 @@ process_event_stop_test:
 	  /* We're doing a "next", set a breakpoint at callee's return
 	     address (the address at which the caller will
 	     resume).  */
+
+/*teawater rec begin----------------------------------------------------------*/
+		if (gdb_is_reverse || gdb_is_recording) {
+			record_resume_step = 1;
+			keep_going (ecs);
+			record_resume_step = 0;
+			return;
+		}
+/*teawater rec end------------------------------------------------------------*/
+
 	  insert_step_resume_breakpoint_at_caller (get_current_frame ());
 	  keep_going (ecs);
 	  return;
@@ -2551,6 +2597,15 @@ process_event_stop_test:
 	  return;
 	}
 
+/*teawater rec begin----------------------------------------------------------*/
+	if ((gdb_is_reverse || gdb_is_recording) && step_over_calls == STEP_OVER_UNDEBUGGABLE) {
+		record_resume_step = 1;
+		keep_going (ecs);
+		record_resume_step = 0;
+		return;
+	}
+/*teawater rec end------------------------------------------------------------*/
+
       /* Set a breakpoint at callee's return address (the address at
          which the caller will resume).  */
       insert_step_resume_breakpoint_at_caller (get_current_frame ());
@@ -2605,6 +2660,15 @@ process_event_stop_test:
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
 
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_reverse || gdb_is_recording) {
+		record_resume_step = 1;
+		keep_going (ecs);
+		record_resume_step = 0;
+		return;
+	}
+/*teawater rec end------------------------------------------------------------*/
+
       /* The inferior just stepped into, or returned to, an
          undebuggable function (where there is no debugging information
          and no line number corresponding to the address where the
@@ -2654,15 +2718,51 @@ process_event_stop_test:
          or can this happen as a result of a return or longjmp?).  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
+
+/*teawater rec begin----------------------------------------------------------*/
+	if ((step_over_calls == STEP_OVER_ALL && gdb_is_reverse) || gdb_is_recording) {
+		record_resume_step = 1;
+		keep_going (ecs);
+		record_resume_step = 0;
+		return;
+	}
+/*teawater rec end------------------------------------------------------------*/
+
       stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
       return;
     }
 
-  if ((stop_pc == ecs->sal.pc)
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_reverse && frame_id_eq (get_frame_id (get_current_frame ()), step_prev_frame_id)) {
+		if (debug_infrun) {
+			fprintf_unfiltered (gdb_stdlog, "infrun: return to the prev function\n");
+		}
+		stop_step = 1;
+		print_stop_reason (END_STEPPING_RANGE, 0);
+		stop_stepping (ecs);
+		return;
+	}
+
+	if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id) && (gdb_is_reverse || gdb_is_recording)) {
+		if ((stop_pc != ecs->sal.pc && gdb_is_reverse) || ( step_over_calls == STEP_OVER_ALL && gdb_is_recording)) {
+			if (debug_infrun)
+				fprintf_unfiltered (gdb_stdlog, "infrun: maybe stepped into subroutine\n");
+			record_resume_step = 1;
+			keep_going (ecs);
+			record_resume_step = 0;
+			return;
+		}
+	}
+/*teawater rec end------------------------------------------------------------*/
+
+/*teawater rec begin----------------------------------------------------------*/
+    //if ((stop_pc == ecs->sal.pc)
+    if (((stop_pc == ecs->sal.pc && !gdb_is_reverse) || (stop_pc >= ecs->sal.pc && stop_pc < ecs->sal.end && gdb_is_reverse))
       && (ecs->current_line != ecs->sal.line
 	  || ecs->current_symtab != ecs->sal.symtab))
+/*teawater rec end------------------------------------------------------------*/
     {
       /* We are at the start of a different line.  So stop.  Note that
          we don't stop if we step into the middle of a different line.
@@ -2670,6 +2770,16 @@ process_event_stop_test:
          better.  */
       if (debug_infrun)
 	 fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
+
+/*teawater rec begin----------------------------------------------------------*/
+#if 0
+	if (gdb_is_recording) {
+		keep_going (ecs);
+		return;
+	}
+#endif
+/*teawater rec end------------------------------------------------------------*/
+
       stop_step = 1;
       print_stop_reason (END_STEPPING_RANGE, 0);
       stop_stepping (ecs);
@@ -2726,11 +2836,13 @@ process_event_stop_test:
 static int
 currently_stepping (struct execution_control_state *ecs)
 {
+/*teawater rec begin----------------------------------------------------------*/
   return ((!ecs->handling_longjmp
 	   && ((step_range_end && step_resume_breakpoint == NULL)
 	       || stepping_over_breakpoint))
 	  || ecs->stepping_through_solib_after_catch
-	  || bpstat_should_step ());
+	  || bpstat_should_step () || record_resume_step);
+/*teawater rec end------------------------------------------------------------*/
 }
 
 /* Subroutine call with source code we should not step over.  Do step
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -51,7 +51,9 @@ includedir = @includedir@
 top_builddir = .
 
 SHELL = @SHELL@
-EXEEXT = @EXEEXT@
+#teawater rec begin-------------------------------------------------------------
+EXEEXT = @EXEEXT@record
+#teawater rec end---------------------------------------------------------------
 
 AWK = @AWK@
 LN_S = @LN_S@
@@ -586,6 +588,7 @@ TARGET_FLAGS_TO_PASS = \
 # Links made at configuration time should not be specified here, since
 # SFILES is used in building the distribution archive.
 
+#teawater rec begin-------------------------------------------------------------
 SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c  \
 	addrmap.c \
 	auxv.c ax-general.c ax-gdb.c \
@@ -633,7 +636,9 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	user-regs.c \
 	valarith.c valops.c valprint.c value.c varobj.c vec.c \
 	wrapper.c \
-	xml-tdesc.c xml-support.c
+	xml-tdesc.c xml-support.c \
+	record.c
+#teawater rec end---------------------------------------------------------------
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 
@@ -1022,6 +1027,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_
 	$(CONFIG_SRCS)
 TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
 
+#teawater rec begin-------------------------------------------------------------
 COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	version.o \
 	annotate.o \
@@ -1072,7 +1078,9 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	tramp-frame.o \
 	solib.o solib-null.o \
 	prologue-value.o memory-map.o xml-support.o \
-	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
+	record.o
+#teawater rec end---------------------------------------------------------------
 
 TSOBS = inflow.o
 
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -58,6 +58,11 @@
 #include "dwarf2-frame.h"
 #include "user-regs.h"
 
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+#include <stdint.h>
+/*teawater rec end------------------------------------------------------------*/
+
 static const struct objfile_data *mips_pdr_data;
 
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
@@ -5213,6 +5218,619 @@ value_of_mips_user_reg (struct frame_inf
   return value_of_register (*reg_p, frame);
 }
 
+/*teawater rec begin----------------------------------------------------------*/
+static CORE_ADDR	mips_delay_slot_addr;
+static CORE_ADDR	mips_target_addr;
+
+static int
+mips_record_32 (CORE_ADDR pc)
+{
+	uint32_t			insn = (uint32_t)mips_fetch_instruction (pc);
+	uint32_t			opcode;
+	const struct mips_regnum	*regnum = mips_regnum (current_gdbarch);
+	int				add_pc = 1;
+	uint32_t			tmpu32;
+
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: mips_record_32 insn = 0x%08x\n", (unsigned int)insn);
+	}
+
+	opcode = insn >> 26;
+	switch (opcode) {
+		case 0x00:
+			switch ((insn >> 0) & 0x3f) {
+				/* sll */
+				case 0x00:
+				/* srl */
+				case 0x02:
+				/* sra */
+				case 0x03:
+				/* sllv */
+				case 0x04:
+				/* srlv */
+				case 0x06:
+				/* srav */
+				case 0x07:
+				/* movz */
+				case 0x0a:
+				/* movn */
+				case 0x0b:
+				/* mfhi */
+				case 0x10:
+				/* mflo */
+				case 0x12:
+				/* add */
+				case 0x20:
+				/* addu */
+				case 0x21:
+				/* sub */
+				case 0x22:
+				/* subu */
+				case 0x23:
+				/* and */
+				case 0x24:
+				/* or */
+				case 0x25:
+				/* xor */
+				case 0x26:
+				/* nor */
+				case 0x27:
+				/* slt */
+				case 0x2a:
+				/* sltu */
+				case 0x2b:
+					goto set_rd;
+					break;
+				/* jr */
+				case 0x08:
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&mips_target_addr);
+					goto set_delay_slot_pc;
+					break;
+				/* jalr */
+				case 0x09:
+					{
+						uint32_t	rd = (insn >> 11) & 0x1f;
+						if (rd != 0) {
+							if (record_arch_list_add_reg (rd)) {
+								return (-1);
+							}
+						}
+						regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&mips_target_addr);
+						goto set_delay_slot_pc;
+					}
+					break;
+				/* sync */
+				case 0x0f:
+					break;
+				/* mthi */
+				case 0x11:
+					if (record_arch_list_add_reg (regnum->hi)) {
+						return (-1);
+					}
+					break;
+				/* mtlo */
+				case 0x13:
+					if (record_arch_list_add_reg (regnum->lo)) {
+						return (-1);
+					}
+					break;
+				/* mult */
+				case 0x18:
+				/* multu */
+				case 0x19:
+				/* div */
+				case 0x1a:
+				/* divu */
+				case 0x1b:
+					goto set_hi_lo;
+					break;
+				default:
+					goto no_support;
+					break;
+			}
+			break;
+
+		case 0x01:
+			switch ((insn >> 16) & 0x1f) {
+				/* bltz */
+				case 0x00:
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 < 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					break;
+				/* bgez */
+				case 0x01:
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 >= 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					break;
+				/* bltzl */
+				case 0x02:
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 < 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					else {
+						goto set_pc;
+					}
+					break;
+				/* bgezl */
+				case 0x03:
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 >= 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					else {
+						goto set_pc;
+					}
+					break;
+				/* bltzal */
+				case 0x10:
+					if (record_arch_list_add_reg (31)) {
+						return (-1);
+					}
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 < 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					break;
+				/* bgezal */
+				case 0x11:
+					if (record_arch_list_add_reg (31)) {
+						return (-1);
+					}
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 >= 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					break;
+				/* bltzall */
+				case 0x12:
+					if (record_arch_list_add_reg (31)) {
+						return (-1);
+					}
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 < 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					else {
+						goto set_pc;
+					}
+					break;
+				/* bgezall */
+				case 0x13:
+					if (record_arch_list_add_reg (31)) {
+						return (-1);
+					}
+					regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32);
+					if (tmpu32 >= 0) {
+						goto set_imm_delay_slot_pc;
+					}
+					else {
+						goto set_pc;
+					}
+					break;
+				default:
+					goto no_support;
+					break;
+			}
+			break;
+
+		/* j */
+		case 0x02:
+			mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2);
+			goto set_delay_slot_pc;
+			break;
+
+		/* beq */
+		case 0x04: {
+				uint32_t	tmp;
+				regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+				regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp);
+				if (tmpu32 == tmp) {
+					goto set_imm_delay_slot_pc;
+				}
+			}
+			break;
+
+		/* bne */
+		case 0x05: {
+				uint32_t	tmp;
+				regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+				regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp);
+				if (tmpu32 != tmp) {
+					goto set_imm_delay_slot_pc;
+				}
+			}
+			break;
+
+		/* blez */
+		case 0x06:
+			regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+			if (tmpu32 <= 0) {
+				goto set_imm_delay_slot_pc;
+			}
+			break;
+
+		/* bgtz */
+		case 0x07:
+			regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+			if (tmpu32 > 0) {
+				goto set_imm_delay_slot_pc;
+			}
+			break;
+
+		/* beql */
+		case 0x14: {
+				uint32_t	tmp;
+				regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+				regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp);
+				if (tmpu32 == tmp) {
+					goto set_imm_delay_slot_pc;
+				}
+				else {
+					goto set_pc;
+				}
+			}
+			break;
+
+		/* bnel */
+		case 0x15: {
+				uint32_t	tmp;
+				regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+				regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp);
+				if (tmpu32 == tmp) {
+					goto set_imm_delay_slot_pc;
+				}
+				else {
+					goto set_pc;
+				}
+			}
+			break;
+
+		/* blezl */
+		case 0x16:
+			regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+			if (tmpu32 <= 0) {
+				goto set_imm_delay_slot_pc;
+			}
+			else {
+				goto set_pc;
+			}
+			break;
+
+		/* bgtzl */
+		case 0x17:
+			regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32);
+			if (tmpu32 > 0) {
+				goto set_imm_delay_slot_pc;
+			}
+			else {
+				goto set_pc;
+			}
+			break;
+
+		/* jal */
+		case 0x03:
+			if (record_arch_list_add_reg (31)) {
+				return (-1);
+			}
+			mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2);
+			goto set_delay_slot_pc;
+			break;
+
+		/* jalx */
+		case 0x1d:
+			goto no_support;
+			break;
+
+		/* addi */
+		case 0x08:
+		/* addiu */
+		case 0x09:
+		/* slti */
+		case 0x0a:
+		/* sltiu */
+		case 0x0b:
+		/* andi */
+		case 0x0c:
+		/* ori */
+		case 0x0d:
+		/* xori */
+		case 0x0e:
+		/* lui */
+		case 0x0f:
+			goto set_rt;
+			break;
+
+		/* COP0 */
+		case 0x10:
+			if ((insn >> 25) & 0x1) {
+				switch ((insn >> 0) & 0x3f) {
+					/* eret */
+					case 0x18:
+						goto set_pc;
+						break;
+					default:
+						goto no_support;
+						break;
+				}
+			}
+			else {
+				switch ((insn >> 21) & 0x1f) {
+					/* mfc0 */
+					case 0x00:
+						goto set_rt;
+						break;
+					/* mtc0 */
+					case 0x04:
+						{
+							switch ((insn >> 11) & 0x1f) {
+								case 13:
+									/* Cause */
+									if (record_arch_list_add_reg (regnum->cause)) {
+										return (-1);
+									}
+								case 8:
+									/* badvaddr */
+									if (record_arch_list_add_reg (regnum->badvaddr)) {
+										return (-1);
+									}
+							}
+						}
+						break;
+					default:
+						goto no_support;
+						break;
+				}
+			}
+			break;
+
+		case 0x1c:
+			switch ((insn >> 0) & 0x3f) {
+				/* madd */
+				case 0x00:
+				/* maddu */
+				case 0x01:
+				/* msub */
+				case 0x04:
+				/* msubu */
+				case 0x05:
+					goto set_hi_lo;
+					break;
+				/* mul */
+				case 0x02:
+					{
+						uint32_t	rd = (insn >> 11) & 0x1f;
+						if (rd != 0) {
+							if (record_arch_list_add_reg (rd)) {
+								return (-1);
+							}
+						}
+						goto set_hi_lo;
+					}
+					break;
+				/* clo */
+				case 0x21:
+				/* clz */
+				case 0x20:
+					goto set_rd;
+					break;
+				default:
+					goto no_support;
+					break;
+			}
+			break;
+
+		/* lb */
+		case 0x20:
+		/* lh */
+		case 0x21:
+		/* lwl */
+		case 0x22:
+		/* lw */
+		case 0x23:
+		/* lbu */
+		case 0x24:
+		/* lhu */
+		case 0x25:
+		/* lwr */
+		case 0x26:
+		/* ll */
+		case 0x30:
+			goto set_rt;
+			break;
+
+		/* sb */
+		case 0x28:
+		/* sh */
+		case 0x29:
+		/* swl */
+		case 0x2a:
+		/* sw */
+		case 0x2b:
+		/* swr */
+		case 0x2e:
+		/* sc */
+		case 0x38:
+			{
+				uint32_t	addr;
+
+				/* addr */
+				/* base */
+				regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&addr);
+				/* offset */
+				addr += (insn >> 0) & 0xffff;
+
+				switch (opcode) {
+					/* sb */
+					case 0x28:
+						if (record_arch_list_add_mem (addr, 1)) {
+							return (-1);
+						}
+						break;
+					/* sh */
+					case 0x29:
+						if (record_arch_list_add_mem (addr, 2)) {
+							return (-1);
+						}
+						break;
+					/* swl */
+					case 0x2a:
+					/* swr */
+					case 0x2e:
+						if (record_arch_list_add_mem (addr & 0xffffff00, 2)) {
+							return (-1);
+						}
+						break;
+					/* sw */
+					case 0x2b:
+						if (record_arch_list_add_mem (addr, 4)) {
+							return (-1);
+						}
+						break;
+					/* sc */
+					case 0x38:
+						if (record_arch_list_add_mem (addr, 4)) {
+							return (-1);
+						}
+						goto set_rt;
+						break;
+				}
+			}
+			break;
+		/* pref */
+		case 0x33:
+			break;
+
+		default:
+			goto no_support;
+			break;
+	}
+
+out:
+	if (record_delay_slot) {
+		if (add_pc) {
+			if (record_arch_list_add_reg (regnum->pc)) {
+				return (-1);
+			}
+			add_pc = 0;
+		}
+	}
+	if (record_arch_list_add_end (add_pc)) {
+		return (-1);
+	}
+	return (0);
+
+no_support:
+	printf_unfiltered (_("record: record and reverse function don't support 32 bits instruction 0x%08x.\n"), (unsigned int)insn);
+	return (-1);
+
+set_rd:
+	{
+		uint32_t	rd = (insn >> 11) & 0x1f;
+		if (rd != 0) {
+			if (record_arch_list_add_reg (rd)) {
+				return (-1);
+			}
+		}
+	}
+	goto out;
+
+set_rt:
+	{
+		uint32_t	rt = (insn >> 16) & 0x1f;
+		if (rt != 0) {
+			if (record_arch_list_add_reg (rt)) {
+				return (-1);
+			}
+		}
+	}
+	goto out;
+
+set_imm_delay_slot_pc:
+	{
+		uint32_t	imm = (insn >> 0) & 0xffff;
+		if (imm >> 15) {
+			imm |= 0xffff0000;
+		}
+		imm <<= 2;
+		mips_target_addr = pc + 4 + imm;
+	}
+	goto set_delay_slot_pc;
+
+set_delay_slot_pc:
+	mips_delay_slot_addr = pc + 4;
+	record_delay_slot ++;
+	goto set_pc;
+
+set_pc:
+	if (record_arch_list_add_reg (regnum->pc)) {
+		return (-1);
+	}
+	add_pc = 0;
+	goto out;
+
+set_hi_lo:
+	if (record_arch_list_add_reg (regnum->hi)) {
+		return (-1);
+	}
+	if (record_arch_list_add_reg (regnum->lo)) {
+		return (-1);
+	}
+	goto out;
+}
+
+static int
+mips_record (void)
+{
+	CORE_ADDR	pc = read_pc ();
+
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: mips_record pc = 0x%s\n", paddr_nz (pc));
+	}
+
+	if (mips_pc_is_mips16 (pc)) {
+		printf_unfiltered (_("record: record and reverse function don't support mips16.\n"));
+		return (-1);
+	}
+
+	if (record_delay_slot) {
+		if (mips_record_32 (mips_delay_slot_addr)) {
+			return (-1);
+		}
+		if (mips_record_32 (mips_target_addr)) {
+			return (-1);
+		}
+		record_delay_slot --;
+	}
+	return (mips_record_32 (pc));
+}
+
+static void
+mips_record_dasm (void)
+{
+	const struct mips_regnum	*regnum;
+	ULONGEST			pc;
+
+	if (mips_pc_is_mips16 (read_pc ())) {
+		error (_("record: record and reverse function don't support mips16.\n"));
+	}
+
+	regnum = mips_regnum (current_gdbarch);
+	regcache_cooked_read_unsigned (record_regcache, regnum->pc, &pc);
+	if (gdb_is_reverse) {
+		pc -= 4;
+	}
+	else {
+		pc += 4;
+	}
+	regcache_cooked_write_unsigned (record_regcache, regnum->pc, pc);
+}
+/*teawater rec end------------------------------------------------------------*/
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -5877,6 +6495,11 @@ mips_gdbarch_init (struct gdbarch_info i
     user_reg_add (gdbarch, mips_register_aliases[i].name,
 		  value_of_mips_user_reg, &mips_register_aliases[i].regnum);
 
+/*teawater rec begin----------------------------------------------------------*/
+  set_gdbarch_record (gdbarch, mips_record);
+  set_gdbarch_record_dasm (gdbarch, mips_record_dasm);
+/*teawater rec end------------------------------------------------------------*/
+
   return gdbarch;
 }
 
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -0,0 +1,471 @@
+/* Record v0.1.2 for GDB, the GNU debugger.
+   Written by Teawater Zhu <teawater@gmail.com>
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "target.h"
+#include "exceptions.h"
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include "regcache.h"
+#include <ctype.h>
+#include <stdint.h>
+#include "mips-tdep.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/file.h>
+#include "frame-unwind.h"
+#include "gdbthread.h"
+#include "exceptions.h"
+#include "infcall.h"
+#include "source.h"
+#include "top.h"
+#include "record.h"
+
+#define RECORD_REC_PROMPT	"(rec) "
+#define RECORD_REV_PROMPT	"(rev) "
+
+extern struct breakpoint *breakpoint_chain;
+
+record_t		*record_list = NULL;
+record_t		*record_arch_list_head = NULL;
+record_t		*record_arch_list_tail = NULL;
+unsigned int		gdb_is_recording = 0;
+int			gdb_is_reverse = 0;
+int			debug_record = 0;
+int			record_wait_step = 0;
+int			record_delay_slot = 0;
+static sigset_t		record_maskall;
+static int		record_get_sig = 0;
+struct regcache		*record_regcache;
+static char		record_gdb_prompt[20];
+
+static void
+show_debug_record (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
+{
+	fprintf_filtered (file, _("Record debugging is %s.\n"), value);
+}
+
+static void
+record_list_release (record_t *rec)
+{
+	record_t	*tmp;
+
+	while (rec) {
+		tmp = rec;
+		rec = rec->prev;
+		xfree (tmp);
+	}
+}
+
+void
+record_message (void)
+{
+	int	ret;
+
+	record_arch_list_head = NULL;
+	record_arch_list_tail = NULL;
+	record_regcache = get_current_regcache ();
+
+	ret = gdbarch_record (current_gdbarch);
+	if (ret > 0) {
+		record_list_release (record_arch_list_tail);
+		error (_("record: record pause the program."));
+	}
+	if (ret < 0) {
+		record_delay_slot = 0;
+		record_list_release (record_arch_list_tail);
+		error (_("record: record message error."));
+	}
+
+	if (record_list) {
+		record_list->next = record_arch_list_head;
+		record_arch_list_head->prev = record_list;
+		record_list = record_arch_list_tail;
+	}
+	else {
+		record_list = record_arch_list_tail;
+	}
+}
+
+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;
+	}
+}
+
+int
+record_arch_list_add_reg (int num)
+{
+	record_t	*rec;
+
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: add reg num = %d to arch list.\n", num);
+	}
+
+	rec = (record_t *)xmalloc (sizeof (record_t));
+	if (!rec) {
+		fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+		return (-1);
+	}
+	rec->u.reg.val = (gdb_byte *)xmalloc (MAX_REGISTER_SIZE);
+	if (!rec->u.reg.val) {
+		fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+		xfree (rec);
+		return (-1);
+	}
+	rec->prev = NULL;
+	rec->next = NULL;
+	rec->type = 1;
+	rec->u.reg.num = num;
+
+	regcache_raw_read (record_regcache, num, rec->u.reg.val);
+
+	record_arch_list_add (rec);
+
+	return (0);
+}
+
+int
+record_arch_list_add_mem (CORE_ADDR addr, int len)
+{
+	record_t	*rec;
+
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: add mem addr = 0x%s len = %d to arch list.\n", paddr_nz (addr), len);
+	}
+
+	rec = (record_t *)xmalloc (sizeof (record_t));
+	if (!rec) {
+		fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+		return (-1);
+	}
+	rec->u.mem.val = (gdb_byte *)xmalloc (len);
+	if (!rec->u.mem.val) {
+		fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+		xfree (rec);
+		return (-1);
+	}
+	rec->prev = NULL;
+	rec->next = NULL;
+	rec->type = 2;
+	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);
+}
+
+int
+record_arch_list_add_end (int need_dasm)
+{
+	record_t	*rec;
+
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: add end need_dasm = %d to arch list.\n", need_dasm);
+	}
+
+	rec = (record_t *)xmalloc (sizeof (record_t));
+	if (!rec) {
+		fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n");
+		return (-1);
+	}
+	rec->prev = NULL;
+	rec->next = NULL;
+	rec->type = 0;
+
+	rec->u.need_dasm = need_dasm;
+
+	record_arch_list_add (rec);
+
+	return (0);
+}
+
+static void
+record_sig_handler (int signo)
+{
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: get a signal\n");
+	}
+	record_wait_step = 1;
+	record_get_sig = 1;
+}
+
+ptid_t
+record_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+	struct sigaction	act, old_act;
+	static int		state = 0;	/* 0 normal 1 to the end 2 to the begin */
+	int			con = 1;
+	int			insn_end = 0;
+	int			need_dasm = 0;
+	struct regcache		*regcache = get_current_regcache ();
+	
+	if (debug_record) {
+		fprintf_unfiltered (gdb_stdlog, "record: record_wait step = %d\n", record_wait_step);
+	}
+
+	record_get_sig = 0;
+	act.sa_handler = record_sig_handler;
+	act.sa_mask = record_maskall;
+	act.sa_flags = SA_RESTART;
+	if (sigaction (SIGINT, &act, &old_act)) {
+		perror_with_name (_("sigaction"));
+	}
+
+	do {
+		/* check state */
+		if ((gdb_is_reverse && !record_list->prev && state == 2) || (!gdb_is_reverse && !record_list->next && state == 1)) {
+			if (state == 1) {
+				fprintf_unfiltered (gdb_stdlog, "record: running to the end of record list.\n");
+			}
+			else if (state == 2) {
+				fprintf_unfiltered (gdb_stdlog, "record: running to the begin of record list.\n");
+			}
+			stop_soon = STOP_QUIETLY;
+			break;
+		}
+		state = 0;
+
+		/* set register and memory according to record_list */
+		if (record_list->type == 1) {
+			/* reg */
+			gdb_byte	reg[MAX_REGISTER_SIZE];
+			if (debug_record) {
+				fprintf_unfiltered (gdb_stdlog, "record: record_list reg num = %d to arch list.\n", record_list->u.reg.num);
+			}
+			regcache_cooked_read (regcache, record_list->u.reg.num, reg);
+			regcache_cooked_write (regcache, record_list->u.reg.num, record_list->u.reg.val);
+			memcpy (record_list->u.reg.val, reg, MAX_REGISTER_SIZE);
+		}
+		else if (record_list->type == 2) {
+			/* mem */
+			gdb_byte	mem[record_list->u.mem.len];
+			if (debug_record) {
+				fprintf_unfiltered (gdb_stdlog, "record: record_list mem addr = 0x%s len = %d to current.\n", paddr_nz (record_list->u.mem.addr), record_list->u.mem.len);
+			}
+			if (target_read_memory (record_list->u.mem.addr, mem, record_list->u.mem.len)) {
+				error (_("record: read memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len);
+			}
+			if (target_write_memory (record_list->u.mem.addr, record_list->u.mem.val, record_list->u.mem.len)) {
+				error (_("record: write memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len);
+			}
+			memcpy (record_list->u.mem.val, mem, record_list->u.mem.len);
+		}
+		else {
+			if (debug_record) {
+				fprintf_unfiltered (gdb_stdlog, "record: record_list end need_dasm = %d to current.\n", record_list->u.need_dasm);
+			}
+
+			need_dasm = record_list->u.need_dasm;
+			if (!gdb_is_reverse) {
+				insn_end = 1;
+			}
+		}
+
+		if (gdb_is_reverse) {
+			if (record_list->prev) {
+				record_list = record_list->prev;
+				if (!record_list->type) {
+					insn_end = 1;
+				}
+			}
+			else {
+				state = 2;
+				insn_end = 1;
+			}
+		}
+		else {
+			if (record_list->next) {
+				record_list = record_list->next;
+			}
+			else {
+				state = 1;
+			}
+		}
+
+		if (insn_end) {
+			struct breakpoint	*b;
+			CORE_ADDR		tmp_pc;
+
+			if (debug_record) {
+				fprintf_unfiltered (gdb_stdlog, "record: insn end need_dasm = %d to current.\n", need_dasm);
+			}
+
+			if (need_dasm) {
+				gdbarch_record_dasm (current_gdbarch);
+			}
+
+			//registers_changed ();
+			tmp_pc = read_pc ();
+
+			/* end */
+			if (record_wait_step) {
+				if (debug_record) {
+					fprintf_unfiltered (gdb_stdlog, "record: step.\n");
+				}
+				con = 0;
+			}
+
+			/* check breakpoint */
+			for (b = breakpoint_chain; b; b = b->next) {
+				if (b->loc->inserted) {
+					if (b->loc->target_info.placed_address == tmp_pc) {
+						if (debug_record) {
+							fprintf_unfiltered (gdb_stdlog, "record: break at 0x%s.\n", paddr_nz (tmp_pc));
+						}
+						con = 0;
+						break;
+					}
+				}
+			}
+
+			insn_end = 0;
+		}
+	} while (con);
+
+	if (sigaction (SIGALRM, &old_act, NULL)) {
+		perror_with_name (_("sigaction"));
+	}
+
+	status->kind = TARGET_WAITKIND_STOPPED;
+	if (record_get_sig) {
+		status->value.sig = TARGET_SIGNAL_INT;
+	}
+	else {
+		status->value.sig = TARGET_SIGNAL_TRAP;
+	}
+
+	return (inferior_ptid);
+}
+
+void
+record_close (void)
+{
+	gdb_is_recording = 0;
+	gdb_is_reverse = 0;
+	record_list_release (record_list);
+	record_list = NULL;
+	record_delay_slot = 0;
+	printf_unfiltered (_("record: record and reverse function is stopped.\n"));
+}
+
+static void
+cmd_record_start (char *args, int from_tty)
+{
+	/* check exec */
+	if (!target_has_execution) {
+		error (_("record: the program is not being run."));
+	}
+
+	if (!gdbarch_record_p (current_gdbarch)) {
+		error (_("record: the current gdbarch don't support record function."));
+	}
+
+	if (gdb_is_recording) {
+		printf_unfiltered (_("record: record and reverse function has already been started.\n"));
+	}
+	else {
+		char	*tmp;
+
+		gdb_is_recording = 1;
+		printf_unfiltered (_("record: record and reverse function is started.\n"));
+
+		tmp = get_prompt ();
+		snprintf (record_gdb_prompt, 20, "%s", tmp);
+		set_prompt (RECORD_REC_PROMPT);
+	}
+}
+
+static void
+cmd_record_stop (char *args, int from_tty)
+{
+	/* check exec */
+	if (!target_has_execution) {
+		error (_("record: the program is not being run."));
+	}
+
+	if (!gdbarch_record_p (current_gdbarch)) {
+		error (_("record: the current gdbarch don't support record function."));
+	}
+
+	if (gdb_is_recording) {
+		record_close ();
+		set_prompt (record_gdb_prompt);
+	}
+	else {
+		printf_unfiltered (_("record: record and reverse function is not started.\n"));
+	}
+}
+
+static void
+cmd_reverse (char *args, int from_tty)
+{
+	if (gdb_is_reverse) {
+		gdb_is_reverse = 0;
+		printf_unfiltered (_("record: GDB is set to normal debug mode.\n"));
+		set_prompt (RECORD_REC_PROMPT);
+	}
+	else {
+		if (!record_list) {
+			error (_("record: record and reverse function is not started."));
+		}
+		gdb_is_reverse = 1;
+		printf_unfiltered (_("record: GDB is set to reverse debug mode.\n"));
+		set_prompt (RECORD_REV_PROMPT);
+	}
+}
+
+void
+_initialize_record (void)
+{
+	/*  init record_maskall */
+	if (sigfillset (&record_maskall) == -1) {
+		perror_with_name (_("sigfillset"));
+	}
+
+	add_setshow_zinteger_cmd ("record", class_maintenance, &debug_record, _("Set record debugging."), _("Show record debugging."), _("When non-zero, record specific debugging is enabled."), NULL, show_debug_record, &setdebuglist, &showdebuglist);
+	add_com ("record", class_obscure, cmd_record_start, _("Start the record and reverse function."));
+	add_com_alias ("rec", "record", class_obscure, 1);
+	add_com ("stoprecord", class_obscure, cmd_record_stop, _("Stop the record and reverse function."));
+	add_com_alias ("srec", "stoprecord", class_obscure, 1);
+	add_com ("reverse", class_obscure, cmd_reverse, _("Set GDB to the reverse debug mode or the normal debug mode."));
+	add_com_alias ("rev", "reverse", class_obscure, 1);
+}
--- a/gdb/record.h
+++ b/gdb/record.h
@@ -0,0 +1,64 @@
+/* Record v0.1.2 for GDB, the GNU debugger.
+   Written by Teawater Zhu <teawater@gmail.com>
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _RECORD_H_
+#define _RECORD_H_
+
+typedef struct	record_reg_s {
+	int		num;
+	gdb_byte	*val;
+} record_reg_t;
+
+typedef struct	record_mem_s {
+	CORE_ADDR	addr;
+	int		len;
+	gdb_byte	*val;
+} record_mem_t;
+
+typedef struct	record_s {
+	struct	record_s	*prev;
+	struct	record_s	*next;
+	int	type;	/* 1 reg 2 mem 0 end */
+	union {
+		/* reg */
+		record_reg_t	reg;
+		/* mem */
+		record_mem_t	mem;
+		/* end */
+		int		need_dasm;
+	} u;
+} record_t;
+
+extern record_t		*record_list;
+extern record_t		*record_arch_list_head;
+extern record_t		*record_arch_list_tail;
+extern int		record_arch_need_dasm;
+extern unsigned int	gdb_is_recording;
+extern int		gdb_is_reverse;
+extern int		debug_record;
+extern int		record_wait_step;
+extern int		record_delay_slot;
+extern struct regcache	*record_regcache;
+
+extern void		record_message (void);
+extern int		record_arch_list_add_reg (int num);
+extern int		record_arch_list_add_mem (CORE_ADDR addr, int len);
+extern int		record_arch_list_add_end (int need_dasm);
+extern ptid_t		record_wait (ptid_t ptid, struct target_waitstatus * status);
+extern void		record_close (void);
+#endif	//_RECORD_H_
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -39,6 +39,9 @@
 #include "gdbcore.h"
 #include "exceptions.h"
 #include "target-descriptions.h"
+/*teawater rec begin----------------------------------------------------------*/
+#include "record.h"
+/*teawater rec end------------------------------------------------------------*/
 
 static void target_info (char *, int);
 
@@ -1702,6 +1705,17 @@ target_follow_fork (int follow_child)
 		  "could not find a target to follow fork");
 }
 
+/*teawater rec begin----------------------------------------------------------*/
+void
+target_mourn_inferior (void)
+{
+	if (gdb_is_recording) {
+		record_close ();
+	}
+	(*current_target.to_mourn_inferior) ();
+}
+/*teawater rec end------------------------------------------------------------*/
+
 /* Look for a target which can describe architectural features, starting
    from TARGET.  If we find one, return its description.  */
 
@@ -2065,6 +2079,11 @@ debug_to_close (int quitting)
 void
 target_close (struct target_ops *targ, int quitting)
 {
+/*teawater rec begin----------------------------------------------------------*/
+	if (gdb_is_recording) {
+		record_close ();
+	}
+/*teawater rec end------------------------------------------------------------*/
   if (targ->to_xclose != NULL)
     targ->to_xclose (targ, quitting);
   else if (targ->to_close != NULL)
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -861,8 +861,13 @@ int target_follow_fork (int follow_child
 
 /* The inferior process has died.  Do what is right.  */
 
+/*teawater rec begin----------------------------------------------------------*/
+/*
 #define	target_mourn_inferior()	\
      (*current_target.to_mourn_inferior) ()
+*/
+extern void	target_mourn_inferior (void);
+/*teawater rec end------------------------------------------------------------*/
 
 /* Does target have enough data to do a run or attach command? */
 
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1145,6 +1145,10 @@ print_gdb_version (struct ui_file *strea
 
   fprintf_filtered (stream, "GNU gdb %s\n", version);
 
+/*teawater rec begin----------------------------------------------------------*/
+	fprintf_filtered (stream, "Record 0.1.3\n");
+/*teawater rec end------------------------------------------------------------*/
+
   /* Second line is a copyright notice. */
 
   fprintf_filtered (stream, "Copyright (C) 2008 Free Software Foundation, Inc.\n");



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