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