Patch to make make I386-Linux GDB support Reversible Debugging http://sourceforge.net/projects/record/ Signed-off-by: Hui Zhu --- Makefile.in | 14 gdbarch.c | 49 + gdbarch.h | 10 i386-linux-tdep.c | 2044 ++++++++++++++++++++++++++++++++++++++++++++++++++++ i386-tdep.c | 2097 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ i386-tdep.h | 5 infcmd.c | 40 + inferior.h | 3 infrun.c | 126 +++ mips-tdep.c | 623 ++++++++++++++++ record.c | 471 ++++++++++++ record.h | 64 + target.c | 19 target.h | 5 top.c | 4 15 files changed, 5564 insertions(+), 10 deletions(-) --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -230,6 +230,10 @@ struct gdbarch gdbarch_core_read_description_ftype *core_read_description; gdbarch_static_transform_name_ftype *static_transform_name; int sofun_address_maybe_missing; +/*teawater rec begin----------------------------------------------------------*/ + gdbarch_record_ftype *record; + gdbarch_record_dasm_ftype *record_dasm; +/*teawater rec end------------------------------------------------------------*/ }; @@ -352,6 +356,10 @@ struct gdbarch startup_gdbarch = 0, /* core_read_description */ 0, /* static_transform_name */ 0, /* sofun_address_maybe_missing */ +/*teawater rec begin----------------------------------------------------------*/ + NULL, + NULL, +/*teawater rec end------------------------------------------------------------*/ /* startup_gdbarch() */ }; @@ -3391,6 +3399,47 @@ deprecated_current_gdbarch_select_hack ( reinit_frame_cache (); } +/*teawater rec begin----------------------------------------------------------*/ +int +gdbarch_record_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return (gdbarch->record != NULL); +} + +int +gdbarch_record (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->record != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_record called\n"); + return (gdbarch->record ()); +} + +void +set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype *record) +{ + gdbarch->record = record; +} + +void +gdbarch_record_dasm (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->record_dasm != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_record_dasm called\n"); + gdbarch->record_dasm (); +} + +void +set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm) +{ + gdbarch->record_dasm = record_dasm; +} +/*teawater rec end------------------------------------------------------------*/ + extern void _initialize_gdbarch (void); void --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -900,4 +900,14 @@ extern int gdbarch_debug; extern void gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file); +/*teawater rec begin----------------------------------------------------------*/ +extern int gdbarch_record_p (struct gdbarch *gdbarch); +typedef int (gdbarch_record_ftype) (void); +extern int gdbarch_record (struct gdbarch *gdbarch); +extern void set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype *record); +typedef void (gdbarch_record_dasm_ftype) (void); +extern void gdbarch_record_dasm (struct gdbarch *gdbarch); +extern void set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm); +/*teawater rec end------------------------------------------------------------*/ + #endif --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -35,6 +35,11 @@ #include "solib-svr4.h" #include "symtab.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +#include +/*teawater rec end------------------------------------------------------------*/ + /* Return the name of register REG. */ static const char * @@ -335,6 +340,2041 @@ i386_linux_write_pc (struct regcache *re restarted. */ regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1); } + +/*teawater rec begin----------------------------------------------------------*/ +#include +#include + +#define RECORD_SIZE__old_kernel_stat 32 +#define RECORD_SIZE_tms 16 +#define RECORD_SIZE_loff_t 8 +#define RECORD_SIZE_flock 16 +#define RECORD_SIZE_oldold_utsname 45 +#define RECORD_SIZE_ustat 20 +#define RECORD_SIZE_old_sigaction 140 +#define RECORD_SIZE_old_sigset_t 128 +#define RECORD_SIZE_rlimit 8 +#define RECORD_SIZE_rusage 72 +#define RECORD_SIZE_timeval 8 +#define RECORD_SIZE_timezone 8 +#define RECORD_SIZE_old_gid_t 2 +#define RECORD_SIZE_old_uid_t 2 +#define RECORD_SIZE_fd_set 128 +#define RECORD_SIZE_dirent 268 +#define RECORD_SIZE_dirent64 276 +#define RECORD_SIZE_statfs 64 +#define RECORD_SIZE_statfs64 84 +#define RECORD_SIZE_sockaddr 16 +#define RECORD_SIZE_int 4 +#define RECORD_SIZE_long 4 +#define RECORD_SIZE_ulong 4 +#define RECORD_SIZE_msghdr 28 +#define RECORD_SIZE_itimerval 16 +#define RECORD_SIZE_stat 88 +#define RECORD_SIZE_old_utsname 325 +#define RECORD_SIZE_rusage 72 +#define RECORD_SIZE_sysinfo 64 +#define RECORD_SIZE_msqid_ds 88 +#define RECORD_SIZE_shmid_ds 84 +#define RECORD_SIZE_new_utsname 390 +#define RECORD_SIZE_timex 128 +#define RECORD_SIZE_mem_dqinfo 24 +#define RECORD_SIZE_if_dqblk 68 +#define RECORD_SIZE_fs_quota_stat 68 +#define RECORD_SIZE_timespec 8 +#define RECORD_SIZE_pollfd 8 +#define RECORD_SIZE_NFS_FHSIZE 32 +#define RECORD_SIZE_knfsd_fh 132 +#define RECORD_SIZE_TASK_COMM_LEN 16 +#define RECORD_SIZE_sigaction 140 +#define RECORD_SIZE_sigset_t 8 +#define RECORD_SIZE_siginfo_t 128 +#define RECORD_SIZE_cap_user_data_t 12 +#define RECORD_SIZE_stack_t 12 +#define RECORD_SIZE_off_t RECORD_SIZE_long +#define RECORD_SIZE_stat64 96 +#define RECORD_SIZE_gid_t 2 +#define RECORD_SIZE_uid_t 2 +#define RECORD_SIZE_uid_t 2 +#define RECORD_SIZE_PAGE_SIZE 4096 +#define RECORD_SIZE_flock64 24 +#define RECORD_SIZE_user_desc 16 +#define RECORD_SIZE_io_event 32 +#define RECORD_SIZE_iocb 64 +#define RECORD_SIZE_epoll_event 12 +#define RECORD_SIZE_itimerspec (RECORD_SIZE_timespec * 2) +#define RECORD_SIZE_mq_attr 32 +#define RECORD_SIZE_siginfo 128 +#define RECORD_SIZE_rusage 72 + +#define RECORD_SYS_SOCKET 1 +#define RECORD_SYS_BIND 2 +#define RECORD_SYS_CONNECT 3 +#define RECORD_SYS_LISTEN 4 +#define RECORD_SYS_ACCEPT 5 +#define RECORD_SYS_GETSOCKNAME 6 +#define RECORD_SYS_GETPEERNAME 7 +#define RECORD_SYS_SOCKETPAIR 8 +#define RECORD_SYS_SEND 9 +#define RECORD_SYS_RECV 10 +#define RECORD_SYS_SENDTO 11 +#define RECORD_SYS_RECVFROM 12 +#define RECORD_SYS_SHUTDOWN 13 +#define RECORD_SYS_SETSOCKOPT 14 +#define RECORD_SYS_GETSOCKOPT 15 +#define RECORD_SYS_SENDMSG 16 +#define RECORD_SYS_RECVMSG 17 + +#define RECORD_SEMOP 1 +#define RECORD_SEMGET 2 +#define RECORD_SEMCTL 3 +#define RECORD_SEMTIMEDOP 4 +#define RECORD_MSGSND 11 +#define RECORD_MSGRCV 12 +#define RECORD_MSGGET 13 +#define RECORD_MSGCTL 14 +#define RECORD_SHMAT 21 +#define RECORD_SHMDT 22 +#define RECORD_SHMGET 23 +#define RECORD_SHMCTL 24 + +#define RECORD_Q_GETFMT 0x800004 +#define RECORD_Q_GETINFO 0x800005 +#define RECORD_Q_GETQUOTA 0x800007 +#define RECORD_Q_XGETQSTAT (('5'<<8)+(5)) +#define RECORD_Q_XGETQUOTA (('3'<<8)+(3)) + +static int +i386_linux_intx80_sysenter_record (void) +{ + uint32_t tmpu32; + + regcache_raw_read (record_regcache, I386_EAX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + /* sys_restart_syscall */ + case 0:{ + int q; + target_terminal_ours (); + q = yquery (_("The next instruction is syscall restart. It will restart the computer. Do you want to pause the program.")); + target_terminal_inferior (); + if (q) { + return (1); + } + } + break; + + /* sys_exit */ + case 1:{ + int q; + target_terminal_ours (); + q = yquery (_("The next instruction is syscall exit. It will make the program exit. Do you want to pause the program.")); + target_terminal_inferior (); + if (q) { + return (1); + } + } + break; + + /* sys_fork */ + case 2: + break; + + /* sys_read */ + case 3: { + uint32_t addr, count; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&addr); + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&count); + if (record_arch_list_add_mem (addr, count)) { + return (-1); + } + } + break; + + /* sys_write */ + case 4: + /* sys_open */ + case 5: + /* sys_close */ + case 6: + /* sys_waitpid */ + case 7: + /* sys_creat */ + case 8: + /* sys_link */ + case 9: + /* sys_unlink */ + case 10: + /* sys_execve */ + case 11: + /* sys_chdir */ + case 12: + /* sys_time */ + case 13: + /* sys_mknod */ + case 14: + /* sys_chmod */ + case 15: + /* sys_lchown16 */ + case 16: + /* sys_ni_syscall */ + case 17: + break; + + /* sys_stat */ + case 18: + /* sys_fstat */ + case 28: + /* sys_lstat */ + case 84: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE__old_kernel_stat)) { + return (-1); + } + break; + + /* sys_lseek */ + case 19: + /* sys_getpid */ + case 20: + /* sys_mount */ + case 21: + /* sys_oldumount */ + case 22: + /* sys_setuid16 */ + case 23: + /* sys_getuid16 */ + case 24: + /* sys_stime */ + case 25: + break; + + /* sys_ptrace */ + case 26: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32 == PTRACE_PEEKTEXT || tmpu32 == PTRACE_PEEKDATA || tmpu32 == PTRACE_PEEKUSER) { + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, 4)) { + return (-1); + } + } + break; + + /* sys_alarm */ + case 27: + /* sys_pause */ + case 29: + /* sys_utime */ + case 30: + /* sys_ni_syscall */ + case 31: + /* sys_ni_syscall */ + case 32: + /* sys_access */ + case 33: + /* sys_nice */ + case 34: + /* sys_ni_syscall */ + case 35: + /* sys_sync */ + case 36: + /* sys_kill */ + case 37: + /* sys_rename */ + case 38: + /* sys_mkdir */ + case 39: + /* sys_rmdir */ + case 40: + /* sys_dup */ + case 41: + /* sys_pipe */ + case 42: + break; + + /* sys_times */ + case 43: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_tms)) { + return (-1); + } + break; + + /* sys_ni_syscall */ + case 44: + /* sys_brk */ + case 45: + /* sys_setgid16 */ + case 46: + /* sys_getgid16 */ + case 47: + /* sys_signal */ + case 48: + /* sys_geteuid16 */ + case 49: + /* sys_getegid16 */ + case 50: + /* sys_acct */ + case 51: + /* sys_umount */ + case 52: + /* sys_ni_syscall */ + case 53: + break; + + /* sys_ioctl */ + case 54: + /* XXX */ + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case FIOCLEX: + case FIONCLEX: + case FIONBIO: + case FIOASYNC: + break; + case FIOQSIZE: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_loff_t)) { + return (-1); + } + break; + default: + printf_unfiltered (_("record: record and reverse function don't support ioctl request 0x%08x\n"), tmpu32); + return (-1); + break; + } + break; + + /* sys_fcntl */ + case 55: + /* XXX */ + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); +sys_fcntl: + if (tmpu32 == F_GETLK) { + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_flock)) { + return (-1); + } + } + break; + + /* sys_ni_syscall */ + case 56: + /* sys_setpgid */ + case 57: + /* sys_ni_syscall */ + case 58: + break; + + /* sys_olduname */ + case 59: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_oldold_utsname)) { + return (-1); + } + break; + + /* sys_umask */ + case 60: + /* sys_chroot */ + case 61: + break; + + /* sys_ustat */ + case 62: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_ustat)) { + return (-1); + } + break; + + /* sys_dup2 */ + case 63: + /* sys_getppid */ + case 64: + /* sys_getpgrp */ + case 65: + /* sys_setsid */ + case 66: + break; + + /* sys_sigaction */ + case 67: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_sigaction)) { + return (-1); + } + break; + + /* sys_sgetmask */ + case 68: + /* sys_ssetmask */ + case 69: + /* sys_setreuid16 */ + case 70: + /* sys_setregid16 */ + case 71: + /* sys_sigsuspend */ + case 72: + break; + + /* sys_sigpending */ + case 73: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_sigset_t)) { + return (-1); + } + break; + + /* sys_sethostname */ + case 74: + /* sys_setrlimit */ + case 75: + break; + + /* sys_old_getrlimit */ + case 76: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_rlimit)) { + return (-1); + } + break; + + /* sys_getrusage */ + case 77: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_rusage)) { + return (-1); + } + break; + + /* sys_gettimeofday */ + case 78: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timeval)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timezone)) { + return (-1); + } + break; + + /* sys_settimeofday */ + case 79: + break; + + /* sys_getgroups16 */ + case 80: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_gid_t)) { + return (-1); + } + break; + + /* sys_setgroups16 */ + case 81: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_gid_t)) { + return (-1); + } + break; + + /* old_select */ + case 82: { + /* + struct sel_arg_struct { + unsigned long n; + fd_set *inp; + fd_set *outp; + fd_set *exp; + struct timeval *tvp; + }; + */ + struct sel_arg_struct { + uint32_t n; + uint32_t inp; + uint32_t outp; + uint32_t exp; + uint32_t tvp; + } sel; + + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)&sel, sizeof (sel))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (sel)); + return (-1); + } + if (record_arch_list_add_mem (sel.inp, RECORD_SIZE_fd_set)) { + return (-1); + } + if (record_arch_list_add_mem (sel.outp, RECORD_SIZE_fd_set)) { + return (-1); + } + if (record_arch_list_add_mem (sel.exp, RECORD_SIZE_fd_set)) { + return (-1); + } + if (record_arch_list_add_mem (sel.tvp, RECORD_SIZE_timeval)) { + return (-1); + } + } + } + break; + + /* sys_symlink */ + case 83: + break; + + /* sys_readlink */ + case 85: { + uint32_t len; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&len); + if (record_arch_list_add_mem (tmpu32, len)) { + return (-1); + } + } + break; + + /* sys_uselib */ + case 86: + /* sys_swapon */ + case 87: + break; + + /* sys_reboot */ + case 88:{ + int q; + target_terminal_ours (); + q = yquery (_("The next instruction is syscall reboot. It will restart the computer. Do you want to pause the program.")); + target_terminal_inferior (); + if (q) { + return (1); + } + } + break; + + /* old_readdir */ + case 89: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_dirent)) { + return (-1); + } + break; + + /* old_mmap */ + case 90: + break; + + /* sys_munmap */ + case 91:{ + int q; + uint32_t len; + + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&len); + target_terminal_ours (); + q = yquery (_("The next instruction is syscall munmap. It will free the memory addr = 0x%s len = %d. Do you want to pause the program."), paddr_nz (tmpu32), len); + target_terminal_inferior (); + if (q) { + return (1); + } + } + break; + + /* sys_truncate */ + case 92: + /* sys_ftruncate */ + case 93: + /* sys_fchmod */ + case 94: + /* sys_fchown16 */ + case 95: + /* sys_getpriority */ + case 96: + /* sys_setpriority */ + case 97: + /* sys_ni_syscall */ + case 98: + break; + + /* sys_statfs */ + case 99: + /* sys_fstatfs */ + case 100: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_statfs)) { + return (-1); + } + break; + + /* sys_ioperm */ + case 101: + break; + + /* sys_socketcall */ + case 102: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case RECORD_SYS_SOCKET: + case RECORD_SYS_BIND: + case RECORD_SYS_CONNECT: + case RECORD_SYS_LISTEN: + break; + case RECORD_SYS_ACCEPT: + case RECORD_SYS_GETSOCKNAME: + case RECORD_SYS_GETPEERNAME: { + uint32_t a[3]; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (record_arch_list_add_mem (a[1], RECORD_SIZE_sockaddr)) { + return (-1); + } + if (record_arch_list_add_mem (a[2], RECORD_SIZE_int)) { + return (-1); + } + } + } + break; + + case RECORD_SYS_SOCKETPAIR: { + uint32_t a[4]; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (record_arch_list_add_mem (a[3], RECORD_SIZE_int)) { + return (-1); + } + } + } + break; + case RECORD_SYS_SEND: + case RECORD_SYS_SENDTO: + break; + case RECORD_SYS_RECV: { + uint32_t a[3]; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (a[2]) { + if (target_read_memory (a[2], (gdb_byte *)&(a[2]), sizeof (a[2]))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (a[2]), sizeof (a[2])); + return (-1); + } + if (record_arch_list_add_mem (a[1], a[2])) { + return (-1); + } + } + } + } + break; + case RECORD_SYS_RECVFROM: { + uint32_t a[6]; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (a[2]) { + if (target_read_memory (a[2], (gdb_byte *)&(a[2]), sizeof (a[2]))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (a[2]), sizeof (a[2])); + return (-1); + } + if (record_arch_list_add_mem (a[1], a[2])) { + return (-1); + } + if (record_arch_list_add_mem (a[4], RECORD_SIZE_sockaddr)) { + return (-1); + } + if (record_arch_list_add_mem (a[5], RECORD_SIZE_int)) { + return (-1); + } + } + } + } + break; + case RECORD_SYS_SHUTDOWN: + case RECORD_SYS_SETSOCKOPT: + break; + case RECORD_SYS_GETSOCKOPT: { + uint32_t a[5]; + uint32_t av; + + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (a[4]) { + if (target_read_memory (a[4], (gdb_byte *)&av, sizeof (av))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (a[4]), sizeof (av)); + return (-1); + } + if (record_arch_list_add_mem (a[3], av)) { + return (-1); + } + if (record_arch_list_add_mem (a[4], RECORD_SIZE_int)) { + return (-1); + } + } + } + } + break; + case RECORD_SYS_SENDMSG: + break; + case RECORD_SYS_RECVMSG: { + uint32_t a[2], i; + struct record_msghdr { + uint32_t msg_name; + uint32_t msg_namelen; + uint32_t msg_iov; + uint32_t msg_iovlen; + uint32_t msg_control; + uint32_t msg_controllen; + uint32_t msg_flags; + }rec; + struct record_iovec { + uint32_t iov_base; + uint32_t iov_len; + } iov; + + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + if (target_read_memory (tmpu32, (gdb_byte *)a, sizeof (a))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), sizeof (a)); + return (-1); + } + if (record_arch_list_add_mem (a[1], RECORD_SIZE_msghdr)) { + return (-1); + } + if (a[1]) { + if (target_read_memory (a[1], (gdb_byte *)&rec, sizeof (rec))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (a[1]), sizeof (rec)); + return (-1); + } + if (record_arch_list_add_mem (rec.msg_name, rec.msg_namelen)) { + return (-1); + } + if (record_arch_list_add_mem (rec.msg_control, rec.msg_controllen)) { + return (-1); + } + if (rec.msg_iov) { + for (i = 0; i < rec.msg_iovlen; i++) { + if (target_read_memory (rec.msg_iov, (gdb_byte *)&iov, sizeof (iov))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (rec.msg_iov), sizeof (iov)); + return (-1); + } + if (record_arch_list_add_mem (iov.iov_base, iov.iov_len)) { + return (-1); + } + rec.msg_iov += sizeof (struct record_iovec); + } + } + } + } + } + break; + default: + printf_unfiltered (_("record: record and reverse function don't support socketcall call 0x%08x\n"), tmpu32); + return (-1); + break; + } + break; + + /* sys_syslog */ + case 103: + break; + + /* sys_setitimer */ + case 104: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_itimerval)) { + return (-1); + } + break; + + /* sys_getitimer */ + case 105: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_itimerval)) { + return (-1); + } + break; + + /* sys_newstat */ + case 106: + /* sys_newlstat */ + case 107: + /* sys_newfstat */ + case 108: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_stat)) { + return (-1); + } + break; + + /* sys_uname */ + case 109: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_utsname)) { + return (-1); + } + break; + + /* sys_iopl */ + case 110: + /* sys_vhangup */ + case 111: + /* sys_ni_syscall */ + case 112: + /* sys_vm86old */ + case 113: + break; + + /* sys_wait4 */ + case 114: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_rusage)) { + return (-1); + } + break; + + /* sys_swapoff */ + case 115: + break; + + /* sys_sysinfo */ + case 116: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_sysinfo)) { + return (-1); + } + break; + + /* sys_ipc */ + case 117: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case RECORD_MSGRCV: { + int32_t second; + uint32_t ptr; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&second); + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&ptr); + if (record_arch_list_add_mem (ptr, second + RECORD_SIZE_long)) { + return (-1); + } + } + break; + case RECORD_MSGCTL: + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_msqid_ds)) { + return (-1); + } + break; + case RECORD_SHMAT: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_ulong)) { + return (-1); + } + break; + case RECORD_SHMCTL: + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_shmid_ds)) { + return (-1); + } + break; + } + break; + + /* sys_fsync */ + case 118: + /* sys_sigreturn */ + case 119: + /* sys_clone */ + case 120: + /* sys_setdomainname */ + case 121: + break; + + /* sys_newuname */ + case 122: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_new_utsname)) { + return (-1); + } + break; + + /* sys_modify_ldt */ + case 123: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32 == 0 || tmpu32 == 2) { + uint32_t ptr, bytecount; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&ptr); + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&bytecount); + if (record_arch_list_add_mem (ptr, bytecount)) { + return (-1); + } + } + break; + + /* sys_adjtimex */ + case 124: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timex)) { + return (-1); + } + break; + + /* sys_mprotect */ + case 125: + break; + + /* sys_sigprocmask */ + case 126: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_sigset_t)) { + return (-1); + } + break; + + /* sys_ni_syscall */ + case 127: + /* sys_init_module */ + case 128: + /* sys_delete_module */ + case 129: + /* sys_ni_syscall */ + case 130: + break; + + /* sys_quotactl */ + case 131: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case RECORD_Q_GETFMT: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, 4)) { + return (-1); + } + break; + case RECORD_Q_GETINFO: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_mem_dqinfo)) { + return (-1); + } + break; + case RECORD_Q_GETQUOTA: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_if_dqblk)) { + return (-1); + } + break; + case RECORD_Q_XGETQSTAT: + case RECORD_Q_XGETQUOTA: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fs_quota_stat)) { + return (-1); + } + break; + } + break; + + /* sys_getpgid */ + case 132: + /* sys_fchdir */ + case 133: + /* sys_bdflush */ + case 134: + break; + + /* sys_sysfs */ + case 135: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32 == 2) { + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + /*XXX the size of memory is not very clear*/ + if (record_arch_list_add_mem (tmpu32, 10)) { + return (-1); + } + } + break; + + /* sys_personality */ + case 136: + /* sys_ni_syscall */ + case 137: + /* sys_setfsuid16 */ + case 138: + /* sys_setfsgid16 */ + case 139: + break; + + /* sys_llseek */ + case 140: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_loff_t)) { + return (-1); + } + break; + + /* sys_getdents */ + case 141: { + uint32_t count; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&count); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_dirent * count)) { + return (-1); + } + } + break; + + /* sys_select */ + case 142: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timeval)) { + return (-1); + } + break; + + /* sys_flock */ + case 143: + /* sys_msync */ + case 144: + break; + + /* sys_readv */ + case 145: { + uint32_t vec; + uint32_t vlen; + struct record_iovec { + uint32_t iov_base; + uint32_t iov_len; + } iov; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&vec); + if (vec) { + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&vlen); + for (tmpu32 = 0; tmpu32 < vlen; tmpu32++) { + if (target_read_memory (vec, (gdb_byte *)&iov, sizeof (struct record_iovec))) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (vec), sizeof (struct record_iovec)); + return (-1); + } + if (record_arch_list_add_mem (iov.iov_base, iov.iov_len)) { + return (-1); + } + vec += sizeof (struct record_iovec); + } + } + } + break; + + /* sys_writev */ + case 146: + /* sys_getsid */ + case 147: + /* sys_fdatasync */ + case 148: + /* sys_sysctl */ + case 149: + /* sys_mlock */ + case 150: + /* sys_munlock */ + case 151: + /* sys_mlockall */ + case 152: + /* sys_munlockall */ + case 153: + /* sys_sched_setparam */ + case 154: + break; + + /* sys_sched_getparam */ + case 155: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + + /* sys_sched_setscheduler */ + case 156: + /* sys_sched_getscheduler */ + case 157: + /* sys_sched_yield */ + case 158: + /* sys_sched_get_priority_max */ + case 159: + /* sys_sched_get_priority_min */ + case 160: + break; + + /* sys_sched_rr_get_interval */ + case 161: + /* sys_nanosleep */ + case 162: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_mremap */ + case 163: + /* sys_setresuid16 */ + case 164: + break; + + /* sys_getresuid16 */ + case 165: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_uid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_uid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_uid_t)) { + return (-1); + } + break; + + /* sys_vm86 */ + case 166: + /* sys_ni_syscall */ + case 167: + break; + + /* sys_poll */ + case 168: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t nfds; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&nfds); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_pollfd * nfds)) { + return (-1); + } + } + break; + + /* sys_nfsservctl */ + case 169: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32 == 7 || tmpu32 == 8) { + uint32_t rsize; + if (tmpu32 == 7) { + rsize = RECORD_SIZE_NFS_FHSIZE; + } + else { + rsize = RECORD_SIZE_knfsd_fh; + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, rsize)) { + return (-1); + } + } + break; + + /* sys_setresgid16 */ + case 170: + break; + + /* sys_getresgid16 */ + case 171: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_gid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_gid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_old_gid_t)) { + return (-1); + } + break; + + /* sys_prctl */ + case 172: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case 2: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + case 16: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_TASK_COMM_LEN)) { + return (-1); + } + break; + } + break; + + /* sys_rt_sigreturn */ + case 173: + break; + + /* sys_rt_sigaction */ + case 174: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_sigaction)) { + return (-1); + } + break; + + /* sys_rt_sigprocmask */ + case 175: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_sigset_t)) { + return (-1); + } + break; + + /* sys_rt_sigpending */ + case 176: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t sigsetsize; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&sigsetsize); + if (record_arch_list_add_mem (tmpu32, sigsetsize)) { + return (-1); + } + } + break; + + /* sys_rt_sigtimedwait */ + case 177: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_siginfo_t)) { + return (-1); + } + break; + + /* sys_rt_sigqueueinfo */ + case 178: + /* sys_rt_sigsuspend */ + case 179: + break; + + /* sys_pread64 */ + case 180: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t count; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&count); + if (record_arch_list_add_mem (tmpu32, count)) { + return (-1); + } + } + break; + + /* sys_pwrite64 */ + case 181: + /* sys_chown16 */ + case 182: + break; + + /* sys_getcwd */ + case 183: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t size; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&size); + if (record_arch_list_add_mem (tmpu32, size)) { + return (-1); + } + } + break; + + /* sys_capget */ + case 184: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_cap_user_data_t)) { + return (-1); + } + break; + + /* sys_capset */ + case 185: + break; + + /* sys_sigaltstack */ + case 186: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_stack_t)) { + return (-1); + } + break; + + /* sys_sendfile */ + case 187: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_off_t)) { + return (-1); + } + break; + + /* sys_ni_syscall */ + case 188: + /* sys_ni_syscall */ + case 189: + /* sys_vfork */ + case 190: + break; + + /* sys_getrlimit */ + case 191: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_rlimit)) { + return (-1); + } + break; + + /* sys_mmap2 */ + case 192: + break; + + /* sys_truncate64 */ + case 193: + /* sys_ftruncate64 */ + case 194: + break; + + /* sys_stat64 */ + case 195: + /* sys_lstat64 */ + case 196: + /* sys_fstat64 */ + case 197: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_stat64)) { + return (-1); + } + break; + + /* sys_lchown */ + case 198: + /* sys_getuid */ + case 199: + /* sys_getgid */ + case 200: + /* sys_geteuid */ + case 201: + /* sys_getegid */ + case 202: + /* sys_setreuid */ + case 203: + /* sys_setregid */ + case 204: + break; + + /* sys_getgroups */ + case 205: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int gidsetsize; + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&gidsetsize); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_gid_t * gidsetsize)) { + return (-1); + } + } + break; + + /* sys_setgroups */ + case 206: + /* sys_fchown */ + case 207: + /* sys_setresuid */ + case 208: + break; + + /* sys_getresuid */ + case 209: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_uid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_uid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_uid_t)) { + return (-1); + } + break; + + /* sys_setresgid */ + case 210: + break; + + /* sys_getresgid */ + case 211: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_gid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_gid_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_gid_t)) { + return (-1); + } + break; + + /* sys_chown */ + case 212: + /* sys_setuid */ + case 213: + /* sys_setgid */ + case 214: + /* sys_setfsuid */ + case 215: + /* sys_setfsgid */ + case 216: + /* sys_pivot_root */ + case 217: + break; + + /* sys_mincore */ + case 218: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_PAGE_SIZE)) { + return (-1); + } + break; + + /* sys_madvise */ + case 219: + break; + + /* sys_getdents64 */ + case 220:{ + uint32_t count; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&count); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_dirent64 * count)) { + return (-1); + } + } + break; + + /* sys_fcntl64 */ + case 221: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + switch (tmpu32) { + case F_GETLK64: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_flock64)) { + return (-1); + } + break; + case F_SETLK64: + case F_SETLKW64: + break; + default: + goto sys_fcntl; + break; + } + break; + + /* sys_ni_syscall */ + case 222: + /* sys_ni_syscall */ + case 223: + /* sys_gettid */ + case 224: + /* sys_readahead */ + case 225: + /* sys_setxattr */ + case 226: + /* sys_lsetxattr */ + case 227: + /* sys_fsetxattr */ + case 228: + break; + + /* sys_getxattr */ + case 229: + /* sys_lgetxattr */ + case 230: + /* sys_fgetxattr */ + case 231: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t size; + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&size); + if (record_arch_list_add_mem (tmpu32, size)) { + return (-1); + } + } + break; + + /* sys_listxattr */ + case 232: + /* sys_llistxattr */ + case 233: + /* sys_flistxattr */ + case 234: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t size; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&size); + if (record_arch_list_add_mem (tmpu32, size)) { + return (-1); + } + } + break; + + /* sys_removexattr */ + case 235: + /* sys_lremovexattr */ + case 236: + /* sys_fremovexattr */ + case 237: + /* sys_tkill */ + case 238: + break; + + /* sys_sendfile64 */ + case 239: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_loff_t)) { + return (-1); + } + break; + + /* sys_futex */ + case 240: + /* sys_sched_setaffinity */ + case 241: + break; + + /* sys_sched_getaffinity */ + case 242: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t len; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&len); + if (record_arch_list_add_mem (tmpu32, len)) { + return (-1); + } + } + break; + + /* sys_set_thread_area */ + case 243: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + + /* sys_get_thread_area */ + case 244: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_user_desc)) { + return (-1); + } + break; + + /* sys_io_setup */ + case 245: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_long)) { + return (-1); + } + break; + + /* sys_io_destroy */ + case 246: + break; + + /* sys_io_getevents */ + case 247: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int32_t nr; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&nr); + if (record_arch_list_add_mem (tmpu32, nr * RECORD_SIZE_io_event)) { + return (-1); + } + } + break; + + /* sys_io_submit */ + case 248: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int32_t i, nr; + uint32_t *iocbp; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&nr); + iocbp = (uint32_t *)alloca (nr * RECORD_SIZE_int); + if (target_read_memory (tmpu32, (gdb_byte *)iocbp, nr * RECORD_SIZE_int)) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (tmpu32), nr * RECORD_SIZE_int); + return (-1); + } + for (i = 0; i < nr; i++) { + if (record_arch_list_add_mem (iocbp[i], RECORD_SIZE_iocb)) { + return (-1); + } + } + } + break; + + /* sys_io_cancel */ + case 249: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_io_event)) { + return (-1); + } + break; + + /* sys_fadvise64 */ + case 250: + /* sys_ni_syscall */ + case 251: + break; + + /* sys_exit_group */ + case 252: { + int q; + target_terminal_ours (); + q = yquery (_("The next instruction is syscall exit_group. It will make the program exit. Do you want to pause the program.")); + target_terminal_inferior (); + if (q) { + return (1); + } + } + break; + + /* sys_lookup_dcookie */ + case 253: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t len; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&len); + if (record_arch_list_add_mem (tmpu32, len)) { + return (-1); + } + } + break; + + /* sys_epoll_create */ + case 254: + /* sys_epoll_ctl */ + case 255: + break; + + /* sys_epoll_wait */ + case 256: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int32_t maxevents; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&maxevents); + if (record_arch_list_add_mem (tmpu32, maxevents * RECORD_SIZE_epoll_event)) { + return (-1); + } + } + break; + + /* sys_remap_file_pages */ + case 257: + /* sys_set_tid_address */ + case 258: + break; + + /* sys_timer_create */ + case 259: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + + /* sys_timer_settime */ + case 260: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_itimerspec)) { + return (-1); + } + break; + + /* sys_timer_gettime */ + case 261: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_itimerspec)) { + return (-1); + } + break; + + /* sys_timer_getoverrun */ + case 262: + /* sys_timer_delete */ + case 263: + /* sys_clock_settime */ + case 264: + break; + + /* sys_clock_gettime */ + case 265: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_clock_getres */ + case 266: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_clock_nanosleep */ + case 267: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_statfs64 */ + case 268: + /* sys_fstatfs64 */ + case 269: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_statfs64)) { + return (-1); + } + break; + + /* sys_tgkill */ + case 270: + /* sys_utimes */ + case 271: + /* sys_fadvise64_64 */ + case 272: + /* sys_ni_syscall */ + case 273: + /* sys_mbind */ + case 274: + break; + + /* sys_get_mempolicy */ + case 275: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t maxnode; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&maxnode); + if (record_arch_list_add_mem (tmpu32, maxnode * RECORD_SIZE_long)) { + return (-1); + } + } + break; + + /* sys_set_mempolicy */ + case 276: + /* sys_mq_open */ + case 277: + /* sys_mq_unlink */ + case 278: + /* sys_mq_timedsend */ + case 279: + break; + + /* sys_mq_timedreceive */ + case 280: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t msg_len; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&msg_len); + if (record_arch_list_add_mem (tmpu32, msg_len)) { + return (-1); + } + } + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + + /* sys_mq_notify */ + case 281: + break; + + /* sys_mq_getsetattr */ + case 282: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_mq_attr)) { + return (-1); + } + break; + + /* sys_kexec_load */ + case 283: + break; + + /* sys_waitid */ + case 284: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_siginfo)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_rusage)) { + return (-1); + } + break; + + /* sys_ni_syscall */ + case 285: + /* sys_add_key */ + case 286: + /* sys_request_key */ + case 287: + break; + + /* sys_keyctl */ + case 288: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32 == 6 || tmpu32 == 11) { + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t buflen; + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&buflen); + if (record_arch_list_add_mem (tmpu32, buflen)) { + return (-1); + } + } + } + break; + + /* sys_ioprio_set */ + case 289: + /* sys_ioprio_get */ + case 290: + /* sys_inotify_init */ + case 291: + /* sys_inotify_add_watch */ + case 292: + /* sys_inotify_rm_watch */ + case 293: + /* sys_migrate_pages */ + case 294: + /* sys_openat */ + case 295: + /* sys_mkdirat */ + case 296: + /* sys_mknodat */ + case 297: + /* sys_fchownat */ + case 298: + /* sys_futimesat */ + case 299: + break; + + /* sys_fstatat64 */ + case 300: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_stat64)) { + return (-1); + } + break; + + /* sys_unlinkat */ + case 301: + /* sys_renameat */ + case 302: + /* sys_linkat */ + case 303: + /* sys_symlinkat */ + case 304: + break; + + /* sys_readlinkat */ + case 305: + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int32_t bufsiz; + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&bufsiz); + if (record_arch_list_add_mem (tmpu32, bufsiz)) { + return (-1); + } + } + break; + + /* sys_fchmodat */ + case 306: + /* sys_faccessat */ + case 307: + break; + + /* sys_pselect6 */ + case 308: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_fd_set)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_ppoll */ + case 309: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t nfds; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&nfds); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_pollfd * nfds)) { + return (-1); + } + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_timespec)) { + return (-1); + } + break; + + /* sys_unshare */ + case 310: + /* sys_set_robust_list */ + case 311: + break; + + /* sys_get_robust_list */ + case 312: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + break; + + /* sys_splice */ + case 313: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_loff_t)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_loff_t)) { + return (-1); + } + break; + + /* sys_sync_file_range */ + case 314: + /* sys_tee */ + case 315: + /* sys_vmsplice */ + case 316: + break; + + /* sys_move_pages */ + case 317: + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + uint32_t nr_pages; + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&nr_pages); + if (record_arch_list_add_mem (tmpu32, nr_pages * RECORD_SIZE_int)) { + return (-1); + } + } + break; + + /* sys_getcpu */ + case 318: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_int)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem (tmpu32, RECORD_SIZE_ulong * 2)) { + return (-1); + } + break; + + /* sys_epoll_pwait */ + case 319: + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&tmpu32); + if (tmpu32) { + int32_t maxevents; + regcache_raw_read (record_regcache, I386_EDX_REGNUM, (gdb_byte *)&maxevents); + if (record_arch_list_add_mem (tmpu32, maxevents * RECORD_SIZE_epoll_event)) { + return (-1); + } + } + break; + + default: + printf_unfiltered (_("record: record and reverse function don't support syscall number 0x%08x\n"), tmpu32); + return (-1); + break; + } + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + + return (0); +} +/*teawater rec end------------------------------------------------------------*/ + /* The register sets used in GNU/Linux ELF core-dumps are identical to @@ -428,6 +2468,10 @@ i386_linux_init_abi (struct gdbarch_info tdep->sigcontext_addr = i386_linux_sigcontext_addr; tdep->sc_reg_offset = i386_linux_sc_reg_offset; tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset); +/*teawater rec begin----------------------------------------------------------*/ + tdep->intx80_record = i386_linux_intx80_sysenter_record; + tdep->sysenter_record = i386_linux_intx80_sysenter_record; +/*teawater rec end------------------------------------------------------------*/ /* N_FUN symbols in shared libaries have 0 for their values and need to be relocated. */ --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -49,6 +49,11 @@ #include "i386-tdep.h" #include "i387-tdep.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +#include +/*teawater rec end------------------------------------------------------------*/ + /* Register names. */ static char *i386_register_names[] = @@ -2315,6 +2320,2094 @@ i386_fetch_pointer_argument (struct fram return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4); } +/*teawater rec begin----------------------------------------------------------*/ +#define PREFIX_REPZ 0x01 +#define PREFIX_REPNZ 0x02 +#define PREFIX_LOCK 0x04 +#define PREFIX_DATA 0x08 +#define PREFIX_ADDR 0x10 + +/* operand size */ +enum { + OT_BYTE = 0, + OT_WORD, + OT_LONG, +}; + +/* i386 arith/logic operations */ +enum { + OP_ADDL, + OP_ORL, + OP_ADCL, + OP_SBBL, + OP_ANDL, + OP_SUBL, + OP_XORL, + OP_CMPL, +}; + +static int aflag = 1; +static int dflag = 1; +static int override = 0; +static uint8_t modrm; +static uint8_t mod, reg, rm; +static int ot; +static CORE_ADDR i386_record_pc; + +static int +i386_record_modrm (void) +{ + if (target_read_memory (i386_record_pc, &modrm, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + mod = (modrm >> 6) & 3; + reg = (modrm >> 3) & 7; + rm = modrm & 7; + + return (0); +} + +static int +i386_record_lea_modrm_addr (uint32_t *addr) +{ + uint8_t tmpu8; + uint16_t tmpu16; + uint32_t tmpu32; + + *addr = 0; + if (aflag) { + /* 32 bits */ + int havesib = 0; + uint8_t scale = 0; + uint8_t index = 0; + uint8_t base = rm; + + if (base == 4) { + havesib = 1; + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + scale = (tmpu8 >> 6) & 3; + index = ((tmpu8 >> 3) & 7); + base = (tmpu8 & 7); + } + + switch (mod) { + case 0: + if ((base & 7) == 5) { + base = 0xff; + if (target_read_memory (i386_record_pc, (gdb_byte *)addr, 4)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 4; + } + else { + *addr = 0; + } + break; + case 1: + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + *addr = (int8_t)tmpu8; + break; + case 2: + if (target_read_memory (i386_record_pc, (gdb_byte *)addr, 4)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 4; + break; + } + + if (base != 0xff) { + regcache_raw_read (record_regcache, base, (gdb_byte *)&tmpu32); + *addr += tmpu32; + } + + /* XXX: index == 4 is always invalid */ + if (havesib && (index != 4 || scale != 0)) { + regcache_raw_read (record_regcache, index, (gdb_byte *)&tmpu32); + *addr += tmpu32 << scale; + } + +#if 0 + if (override) { + /* *addr += ((uint32_t)read_register (override)) << 4; */ + printf_unfiltered (_("record: cann't get the value of the segment register.\n")); + return (-1); + } +#endif + } + else { + /* 16 bits */ + switch (mod) { + case 0: + if (rm == 6) { + if (target_read_memory (i386_record_pc, (gdb_byte *)&tmpu16, 2)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 2; + *addr = (int16_t)tmpu16; + rm = 0; + goto no_rm; + } + else { + *addr = 0; + } + break; + case 1: + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + *addr = (int8_t)tmpu8; + break; + case 2: + if (target_read_memory (i386_record_pc, (gdb_byte *)&tmpu16, 2)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 2; + *addr = (int16_t)tmpu16; + break; + } + + switch(rm) { + case 0: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 1: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 2: + regcache_raw_read (record_regcache, I386_EBP_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 3: + regcache_raw_read (record_regcache, I386_EBP_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 4: + regcache_raw_read (record_regcache, I386_ESI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 5: + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 6: + regcache_raw_read (record_regcache, I386_EBP_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + case 7: + regcache_raw_read (record_regcache, I386_EBX_REGNUM, (gdb_byte *)&tmpu32); + *addr += tmpu32; + break; + } + *addr &= 0xffff; + +#if 0 +no_rm: + if (override) { + /* *addr += ((uint32_t)read_register (override)) << 4; */ + printf_unfiltered (_("record: cann't get the value of the segment register.\n")); + return (-1); + } +#endif + } + +no_rm: + return (0); +} + +static int +i386_record_lea_modrm () +{ + uint32_t addr; + + if (override) { + printf_unfiltered (_("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"), paddr_nz (read_pc ())); + return (0); + } + + if (i386_record_lea_modrm_addr (&addr)) { + return (-1); + } + + if (record_arch_list_add_mem (addr, 1 << ot)) { + return (-1); + } + + return (0); +} + +static int +i386_record (void) +{ + int prefixes = 0; + uint8_t tmpu8; + uint16_t tmpu16; + uint32_t tmpu32; + uint32_t opcode; + int need_dasm = 0; + + i386_record_pc = read_pc (); + aflag = 1; + dflag = 1; + override = 0; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: i386_record pc = 0x%s\n", paddr_nz (i386_record_pc)); + } + + /* prefixes */ + while(1) { + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc++; + switch(tmpu8) { + case 0xf3: + prefixes |= PREFIX_REPZ; + break; + case 0xf2: + prefixes |= PREFIX_REPNZ; + break; + case 0xf0: + prefixes |= PREFIX_LOCK; + break; + case 0x2e: + override = I386_CS_REGNUM; + break; + case 0x36: + override = I386_SS_REGNUM; + break; + case 0x3e: + override = I386_DS_REGNUM; + break; + case 0x26: + override = I386_ES_REGNUM; + break; + case 0x64: + override = I386_FS_REGNUM; + break; + case 0x65: + override = I386_GS_REGNUM; + break; + case 0x66: + prefixes |= PREFIX_DATA; + break; + case 0x67: + prefixes |= PREFIX_ADDR; + break; + default: + goto out_prefixes; + break; + } + } +out_prefixes: + if (prefixes & PREFIX_DATA) { + dflag ^= 1; + } + if (prefixes & PREFIX_ADDR) { + aflag ^= 1; + } + + /* now check op code */ + opcode = (uint32_t)tmpu8; +reswitch: + switch(opcode) { + case 0x0f: + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + opcode = (uint16_t)tmpu8 | 0x0f00; + goto reswitch; + break; + + /* arith & logic */ + case 0x00 ... 0x05: + case 0x08 ... 0x0d: + case 0x10 ... 0x15: + case 0x18 ... 0x1d: + case 0x20 ... 0x25: + case 0x28 ... 0x2d: + case 0x30 ... 0x35: + case 0x38 ... 0x3d: + if (((opcode >> 3) & 7) != OP_CMPL) { + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + switch((opcode >> 1) & 3) { + /* OP Ev, Gv */ + case 0: + if (i386_record_modrm ()) { + return (-1); + } + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + break; + /* OP Gv, Ev */ + case 1: + if (i386_record_modrm ()) { + return (-1); + } + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + break; + /* OP A, Iv */ + case 2: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + break; + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* GRP1 */ + case 0x80 ... 0x83: + if (i386_record_modrm ()) { + return (-1); + } + + if (reg != OP_CMPL) { + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* inv */ + case 0x40 ... 0x47: + /* dec */ + case 0x48 ... 0x4f: + if (record_arch_list_add_reg (opcode & 7)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* GRP3 */ + case 0xf6: + case 0xf7: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (i386_record_modrm ()) { + return (-1); + } + + switch (reg) { + /* test */ + case 0: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + /* not */ + case 2: + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + break; + /* neg */ + case 3: + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + /* mul */ + case 4: + /* imul */ + case 5: + /* div */ + case 6: + /* idiv */ + case 7: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (ot != OT_BYTE) { + if (record_arch_list_add_reg (I386_EDX_REGNUM)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + default: + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + break; + + /* GRP4 */ + case 0xfe: + /* GRP5 */ + case 0xff: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (i386_record_modrm ()) { + return (-1); + } + if (reg >= 2 && opcode == 0xfe) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + + switch (reg) { + /* inc */ + case 0: + /* dec */ + case 1: + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + /* call */ + case 2: + /* push */ + case 6: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+1)), (1<<(dflag+1)))) { + return (-1); + } + break; + /* lcall */ + case 3: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_CS_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+2)), (1<<(dflag+2)))) { + return (-1); + } + break; + /* jmp */ + case 4: + /* ljmp */ + case 5: + break; + default: + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + break; + + /* test */ + case 0x84: + case 0x85: + case 0xa8: + case 0xa9: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* CWDE/CBW */ + case 0x98: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + break; + + /* CDQ/CWD */ + case 0x99: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EDX_REGNUM)) { + return (-1); + } + break; + + /* imul */ + case 0x0faf: + case 0x69: + case 0x6b: + ot = dflag + OT_WORD; + if (i386_record_modrm ()) { + return (-1); + } + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* xadd */ + case 0x0fc0: + case 0x0fc1: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + if (i386_record_lea_modrm ()) { + return (-1); + } + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* cmpxchg */ + case 0x0fb0: + case 0x0fb1: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + } + else { + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (i386_record_lea_modrm ()) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* cmpxchg8b */ + case 0x0fc7: + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EDX_REGNUM)) { + return (-1); + } + if (i386_record_lea_modrm ()) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* push */ + case 0x50 ... 0x57: + case 0x68: + case 0x6a: + /* push es */ + case 0x06: + /* push cs */ + case 0x0e: + /* push ss */ + case 0x16: + /* push ds */ + case 0x1e: + /* push fs */ + case 0x0fa0: + /* push gs */ + case 0x0fa8: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+1)), (1<<(dflag+1)))) { + return (-1); + } + break; + + /* pop */ + case 0x58 ... 0x5f: + ot = dflag + OT_WORD; + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (ot == OT_BYTE) { + opcode &= 0x3; + } + if (record_arch_list_add_reg (opcode & 0x7)) { + return (-1); + } + break; + + /* pusha */ + case 0x60: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+4)), (1<<(dflag+4)))) { + return (-1); + } + break; + + /* popa */ + case 0x61: + for (tmpu8 = I386_EAX_REGNUM; tmpu8 <= I386_EDI_REGNUM; tmpu8++) { + if (record_arch_list_add_reg (tmpu8)) { + return (-1); + } + } + break; + + /* pop */ + case 0x8f: + ot = dflag + OT_WORD; + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + break; + + /* enter */ + case 0xc8: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EBP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+1)), (1<<(dflag+1)))) { + return (-1); + } + break; + + /* leave */ + case 0xc9: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EBP_REGNUM)) { + return (-1); + } + break; + + /* pop es */ + case 0x07: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_ES_REGNUM)) { + return (-1); + } + break; + + /* pop ss */ + case 0x17: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_SS_REGNUM)) { + return (-1); + } + break; + + /* pop ds */ + case 0x1f: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_DS_REGNUM)) { + return (-1); + } + break; + + /* pop fs */ + case 0x0fa1: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_FS_REGNUM)) { + return (-1); + } + break; + + /* pop gs */ + case 0x0fa9: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_GS_REGNUM)) { + return (-1); + } + break; + + /* mov */ + case 0x88: + case 0x89: + case 0xc6: + case 0xc7: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + if (i386_record_modrm ()) { + return (-1); + } + + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + /* mov */ + case 0x8a: + case 0x8b: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + if (i386_record_modrm ()) { + return (-1); + } + + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* mov seg */ + case 0x8e: + if (i386_record_modrm ()) { + return (-1); + } + + switch (reg) { + case 0: + tmpu8 = I386_ES_REGNUM; + break; + case 2: + tmpu8 = I386_SS_REGNUM; + break; + case 3: + tmpu8 = I386_DS_REGNUM; + break; + case 4: + tmpu8 = I386_FS_REGNUM; + break; + case 5: + tmpu8 = I386_GS_REGNUM; + break; + default: + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + if (record_arch_list_add_reg (tmpu8)) { + return (-1); + } + + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* mov seg */ + case 0x8c: + if (i386_record_modrm ()) { + return (-1); + } + if (reg > 5) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + + if (mod == 3) { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + ot = OT_WORD; + if (i386_record_lea_modrm ()) { + return (-1); + } + } + + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* movzbS */ + case 0x0fb6: + /* movzwS */ + case 0x0fb7: + /* movsbS */ + case 0x0fbe: + /* movswS */ + case 0x0fbf: + if (i386_record_modrm ()) { + return (-1); + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + break; + + /* lea */ + case 0x8d: + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + + ot = dflag; + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + break; + + /* mov EAX*/ + case 0xa0: + case 0xa1: + /* xlat */ + case 0xd7: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + break; + + /* mov EAX*/ + case 0xa2: + case 0xa3: { + uint32_t addr; + + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (aflag) { + if (target_read_memory (i386_record_pc, (gdb_byte *)&addr, 4)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 4; + } + else { + if (target_read_memory (i386_record_pc, (gdb_byte *)&tmpu16, 4)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc += 2; + addr = tmpu16; + } + if (record_arch_list_add_mem (addr, 1 << ot)) { + return (-1); + } + } + break; + + /* mov R, Ib */ + case 0xb0 ... 0xb7: + if (record_arch_list_add_reg ((opcode & 0x7) & 0x3)) { + return (-1); + } + break; + + /* mov R, Iv */ + case 0xb8 ... 0xbf: + if (record_arch_list_add_reg (opcode & 0x7)) { + return (-1); + } + break; + + /* xchg R, EAX */ + case 0x91 ... 0x97: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (opcode & 0x7)) { + return (-1); + } + break; + + /* xchg Ev, Gv */ + case 0x86: + case 0x87: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + if (i386_record_modrm ()) { + return (-1); + } + + if (mod == 3) { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + + if (ot == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + break; + + /* les Gv */ + case 0xc4: + /* lds Gv */ + case 0xc5: + /* lss Gv */ + case 0x0fb2: + /* lfs Gv */ + case 0x0fb4: + /* lgs Gv */ + case 0x0fb5: + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (opcode > 0xff) { + i386_record_pc -= 3; + } + else { + i386_record_pc -= 2; + } + opcode = opcode << 8 | modrm; + goto no_support; + } + + switch (opcode) { + /* les Gv */ + case 0xc4: + tmpu8 = I386_ES_REGNUM; + break; + /* lds Gv */ + case 0xc5: + tmpu8 = I386_DS_REGNUM; + break; + /* lss Gv */ + case 0x0fb2: + tmpu8 = I386_SS_REGNUM; + break; + /* lfs Gv */ + case 0x0fb4: + tmpu8 = I386_FS_REGNUM; + break; + /* lgs Gv */ + case 0x0fb5: + tmpu8 = I386_GS_REGNUM; + break; + } + if (record_arch_list_add_reg (tmpu8)) { + return (-1); + } + + if (record_arch_list_add_reg (reg)) { + return (-1); + } + break; + + /* shifts */ + case 0xc0: + case 0xc1: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + + if (i386_record_modrm ()) { + return (-1); + } + + if (mod != 3 && (opcode == 0xd2 || opcode == 0xd3)) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (ot == OT_BYTE) { + rm &= 0x3; + } + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + case 0x0fa4: + case 0x0fa5: + case 0x0fac: + case 0x0fad: + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + break; + + /* floats */ + /* XXX */ + + /* string ops */ + /* movsS */ + case 0xa4: + case 0xa5: + /* stosS */ + case 0xaa: + case 0xab: + /* insS */ + case 0x6c: + case 0x6d: { + uint32_t addr; + + if ((opcode & 1) == 0) { + ot = OT_BYTE; + } + else { + ot = dflag + OT_WORD; + } + if (opcode == 0xa4 || opcode == 0xa5) { + if (record_arch_list_add_reg (I386_ESI_REGNUM)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EDI_REGNUM)) { + return (-1); + } + + regcache_raw_read (record_regcache, I386_EDI_REGNUM, (gdb_byte *)&addr); + if (!aflag) { + addr &= 0xffff; + /* addr += ((uint32_t)read_register (I386_ES_REGNUM)) << 4; */ + printf_unfiltered (_("record: cann't get the value of the segment register.\n")); + return (-1); + } + + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { + uint32_t count; + + regcache_raw_read (record_regcache, I386_ECX_REGNUM, (gdb_byte *)&count); + if (!aflag) { + count &= 0xffff; + } + + regcache_raw_read (record_regcache, I386_EFLAGS_REGNUM, (gdb_byte *)&tmpu32); + if ((tmpu32 >> 10) & 0x1) { + addr -= (count - 1) * (1 << ot); + } + + if (record_arch_list_add_mem (addr, count * (1 << ot))) { + return (-1); + } + + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + } + else { + if (record_arch_list_add_mem (addr, 1 << ot)) { + return (-1); + } + } + } + break; + + /* lodsS */ + case 0xac: + case 0xad: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_ESI_REGNUM)) { + return (-1); + } + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + } + break; + + /* outsS */ + case 0x6e: + case 0x6f: + if (record_arch_list_add_reg (I386_ESI_REGNUM)) { + return (-1); + } + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + } + break; + + /* scasS */ + case 0xae: + case 0xaf: + if (record_arch_list_add_reg (I386_EDI_REGNUM)) { + return (-1); + } + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* cmpsS */ + case 0xa6: + case 0xa7: + if (record_arch_list_add_reg (I386_EDI_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_ESI_REGNUM)) { + return (-1); + } + if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* port I/O */ + case 0xe4: + case 0xe5: + case 0xec: + case 0xed: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + break; + + case 0xe6: + case 0xe7: + case 0xee: + case 0xef: + break; + + /* control */ + /* ret im */ + case 0xc2: + /* ret */ + case 0xc3: + /* lret im */ + case 0xca: + /* lret */ + case 0xcb: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_CS_REGNUM)) { + return (-1); + } + break; + + /* iret */ + case 0xcf: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_CS_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* call im */ + case 0xe8: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+1)), (1<<(dflag+1)))) { + return (-1); + } + break; + + /* lcall im */ + case 0x9a: + if (record_arch_list_add_reg (I386_CS_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+2)), (1<<(dflag+2)))) { + return (-1); + } + break; + + /* jmp im */ + case 0xe9: + /* ljmp im */ + case 0xea: + /* jmp Jb */ + case 0xeb: + /* jcc Jb */ + case 0x70 ... 0x7f: + /* jcc Jv */ + case 0x0f80 ... 0x0f8f: + break; + + /* setcc Gv */ + case 0x0f90 ... 0x0f9f: + ot = OT_BYTE; + if (i386_record_modrm ()) { + return (-1); + } + if (mod == 3) { + if (record_arch_list_add_reg (rm & 0x3)) { + return (-1); + } + } + else { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + break; + + /* cmov Gv, Ev */ + case 0x0f40 ... 0x0f4f: + if (i386_record_modrm ()) { + return (-1); + } + if (dflag == OT_BYTE) { + reg &= 0x3; + } + if (record_arch_list_add_reg (reg & 0x3)) { + return (-1); + } + break; + + /* flags */ + /* pushf */ + case 0x9c: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + regcache_raw_read (record_regcache, I386_ESP_REGNUM, (gdb_byte *)&tmpu32); + if (record_arch_list_add_mem ((CORE_ADDR)tmpu32 - (1<<(dflag+1)), (1<<(dflag+1)))) { + return (-1); + } + break; + + /* popf */ + case 0x9d: + if (record_arch_list_add_reg (I386_ESP_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* sahf */ + case 0x9e: + /* cmc */ + case 0xf5: + /* clc */ + case 0xf8: + /* stc */ + case 0xf9: + /* cld */ + case 0xfc: + /* std */ + case 0xfd: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* lahf */ + case 0x9f: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + break; + + /* bit operations */ + /* bt/bts/btr/btc Gv, im */ + case 0x0fba: + /* bts */ + case 0x0fab: + /* btr */ + case 0x0fb3: + /* btc */ + case 0x0fbb: + ot = dflag + OT_WORD; + if (i386_record_modrm ()) { + return (-1); + } + if (reg < 4) { + i386_record_pc -= 3; + opcode = opcode << 8 | modrm; + goto no_support; + } + reg -= 4; + if (reg != 0) { + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* bt Gv, Ev */ + case 0x0fa3: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* bsf */ + case 0x0fbc: + /* bsr */ + case 0x0fbd: + if (record_arch_list_add_reg (reg)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* bcd */ + /* daa */ + case 0x27: + /* das */ + case 0x2f: + /* aaa */ + case 0x37: + /* aas */ + case 0x3f: + /* aam */ + case 0xd4: + /* aad */ + case 0xd5: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* misc */ + /* nop */ + case 0x90: + if (prefixes & PREFIX_LOCK) { + i386_record_pc -= 1; + goto no_support; + } + break; + + /* fwait */ + /* XXX */ + case 0x9b: + printf_unfiltered (_("record: record and reverse function don't support instruction fwait.\n")); + i386_record_pc -= 1; + goto no_support; + break; + + /* int3 */ + /* XXX */ + case 0xcc: + printf_unfiltered (_("record: record and reverse function don't support instruction int3.\n")); + i386_record_pc -= 1; + goto no_support; + break; + + /* int */ + /* XXX */ + case 0xcd: { + int ret; + if (target_read_memory (i386_record_pc, &tmpu8, 1)) { + printf_unfiltered (_("record: read memeory 0x%s error.\n"), paddr_nz (i386_record_pc)); + return (-1); + } + i386_record_pc ++; + if (tmpu8 != 0x80 || gdbarch_tdep (current_gdbarch)->intx80_record == NULL) { + printf_unfiltered (_("record: record and reverse function don't support instruction int 0x%02x.\n"), tmpu8); + i386_record_pc -= 2; + goto no_support; + } + ret = gdbarch_tdep (current_gdbarch)->intx80_record (); + if (ret) { + return (ret); + } + } + break; + + /* into */ + /* XXX */ + case 0xce: + printf_unfiltered (_("record: record and reverse function don't support instruction into.\n")); + i386_record_pc -= 1; + goto no_support; + break; + + /* cli */ + case 0xfa: + /* sti */ + case 0xfb: + break; + + /* bound */ + case 0x62: + printf_unfiltered (_("record: record and reverse function don't support instruction bound.\n")); + i386_record_pc -= 1; + goto no_support; + break; + + /* bswap reg */ + case 0x0fc8 ... 0x0fcf: + if (record_arch_list_add_reg (opcode & 7)) { + return (-1); + } + break; + + /* salc */ + case 0xd6: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* loopnz */ + case 0xe0: + /* loopz */ + case 0xe1: + /* loop */ + case 0xe2: + /* jecxz */ + case 0xe3: + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + break; + + /* wrmsr */ + case 0x0f30: + printf_unfiltered (_("record: record and reverse function don't support instruction wrmsr.\n")); + i386_record_pc -= 2; + goto no_support; + break; + + /* rdmsr */ + case 0x0f32: + printf_unfiltered (_("record: record and reverse function don't support instruction rdmsr.\n")); + i386_record_pc -= 2; + goto no_support; + break; + + /* rdtsc */ + case 0x0f31: + printf_unfiltered (_("record: record and reverse function don't support instruction rdtsc.\n")); + i386_record_pc -= 2; + goto no_support; + break; + + /* sysenter */ + case 0x0f34: { + int ret; + if (gdbarch_tdep (current_gdbarch)->sysenter_record == NULL) { + printf_unfiltered (_("record: record and reverse function don't support instruction sysenter.\n")); + i386_record_pc -= 2; + goto no_support; + } + ret = gdbarch_tdep (current_gdbarch)->sysenter_record (); + if (ret) { + return (ret); + } + } + break; + + /* sysexit */ + case 0x0f35: + printf_unfiltered (_("record: record and reverse function don't support instruction sysexit.\n")); + i386_record_pc -= 2; + goto no_support; + break; + + /* cpuid */ + case 0x0fa2: + if (record_arch_list_add_reg (I386_EAX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_ECX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EDX_REGNUM)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EBX_REGNUM)) { + return (-1); + } + break; + + /* hlt */ + case 0xf4: + printf_unfiltered (_("record: record and reverse function don't support instruction hlt.\n")); + i386_record_pc -= 1; + goto no_support; + break; + + case 0x0f00: + if (i386_record_modrm ()) { + return (-1); + } + switch (reg) { + /* sldt */ + case 0: + /* str */ + case 1: + if (mod == 3) { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + ot = OT_WORD; + if (i386_record_lea_modrm ()) { + return (-1); + } + } + break; + /* lldt */ + case 2: + /* ltr */ + case 3: + break; + /* verr */ + case 4: + /* verw */ + case 5: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + default: + i386_record_pc -= 3; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + break; + + case 0x0f01: + if (i386_record_modrm ()) { + return (-1); + } + switch(reg) { + /* sgdt */ + case 0: { + uint32_t addr; + + if (mod == 3) { + i386_record_pc -= 3; + opcode = opcode << 8 | modrm; + goto no_support; + } + + if (override) { + printf_unfiltered (_("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"), paddr_nz (read_pc ())); + } + else { + if (i386_record_lea_modrm_addr (&addr)) { + return (-1); + } + if (record_arch_list_add_mem (addr, 2)) { + return (-1); + } + addr += 2; + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + } + } + break; + case 1: + if (mod == 3) { + switch (rm) { + /* monitor */ + case 0: + break; + /* mwait */ + case 1: + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + default: + i386_record_pc -= 3; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + } + else { + /* sidt */ + if (override) { + printf_unfiltered (_("record: cann't get the value of the segment register in address 0x%s. Record ignore this change.\n"), paddr_nz (read_pc ())); + } + else { + uint32_t addr; + + if (i386_record_lea_modrm_addr (&addr)) { + return (-1); + } + if (record_arch_list_add_mem (addr, 2)) { + return (-1); + } + addr += 2; + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + } + } + break; + /* lgdt */ + case 2: + /* lidt */ + case 3: + /* invlpg */ + case 7: + default: + if (mod == 3) { + i386_record_pc -= 3; + opcode = opcode << 8 | modrm; + goto no_support; + } + break; + /* smsw */ + case 4: + if (mod == 3) { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + else { + ot = OT_WORD; + if (i386_record_lea_modrm ()) { + return (-1); + } + } + break; + /* lmsw */ + case 6: + break; + } + break; + + /* invd */ + case 0x0f08: + /* wbinvd */ + case 0x0f09: + break; + + /* arpl */ + case 0x63: + ot = dflag ? OT_LONG : OT_WORD; + if (i386_record_modrm ()) { + return (-1); + } + if (mod != 3) { + if (i386_record_lea_modrm ()) { + return (-1); + } + } + else { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + /* lar */ + case 0x0f02: + /* lsl */ + case 0x0f03: + if (i386_record_modrm ()) { + return (-1); + } + if (record_arch_list_add_reg (reg)) { + return (-1); + } + if (record_arch_list_add_reg (I386_EFLAGS_REGNUM)) { + return (-1); + } + break; + + case 0x0f18: + break; + + /* nop (multi byte) */ + case 0x0f19 ... 0x0f1f: + break; + + /* mov reg, crN */ + case 0x0f20: + /* mov crN, reg */ + case 0x0f22: + if (i386_record_modrm ()) { + return (-1); + } + if ((modrm & 0xc0) != 0xc0) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + switch(reg) { + case 0: + case 2: + case 3: + case 4: + case 8: + if (opcode & 2) { + } + else { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + break; + default: + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + break; + } + break; + + /* mov reg, drN */ + case 0x0f21: + /* mov drN, reg */ + case 0x0f23: + if (i386_record_modrm ()) { + return (-1); + } + if ((modrm & 0xc0) != 0xc0 || reg == 4 || reg == 5 || reg >= 8) { + i386_record_pc -= 2; + opcode = opcode << 8 | modrm; + goto no_support; + } + if (opcode & 2) { + } + else { + if (record_arch_list_add_reg (rm)) { + return (-1); + } + } + break; + + /* clts */ + case 0x0f06: + break; + + /* MMX/SSE/SSE2/PNI support */ + /* XXX */ + + default: + if (opcode > 0xff) { + i386_record_pc -= 2; + } + else { + i386_record_pc -= 1; + } + goto no_support; + break; + } + + if (!need_dasm) { + if (record_arch_list_add_reg (I386_EIP_REGNUM)) { + return (-1); + } + } + if (record_arch_list_add_end (need_dasm)) { + return (-1); + } + + return (0); + +no_support: + printf_unfiltered (_("record: record and reverse function don't support instruction 0x%02x at address 0x%s.\n"), (unsigned int)(opcode), paddr_nz (i386_record_pc)); + return (-1); +} +/*teawater rec end------------------------------------------------------------*/ + static struct gdbarch * i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) @@ -2503,6 +4596,10 @@ i386_gdbarch_init (struct gdbarch_info i if (tdep->mm0_regnum == 0) tdep->mm0_regnum = gdbarch_num_regs (gdbarch); +/*teawater rec begin----------------------------------------------------------*/ + set_gdbarch_record (gdbarch, i386_record); +/*teawater rec end------------------------------------------------------------*/ + return gdbarch; } --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -106,6 +106,11 @@ struct gdbarch_tdep /* ISA-specific data types. */ struct type *i386_mmx_type; struct type *i386_sse_type; + +/*teawater rec begin----------------------------------------------------------*/ + int (*intx80_record) (void); + int (*sysenter_record) (void); +/*teawater rec end------------------------------------------------------------*/ }; /* Floating-point registers. */ --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -49,6 +49,10 @@ #include "target-descriptions.h" #include "user-regs.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +/*teawater rec end------------------------------------------------------------*/ + /* Functions exported for general use, in inferior.h: */ void all_registers_info (char *, int); @@ -188,6 +192,9 @@ CORE_ADDR step_range_end; /* Exclusive * and how to set the frame for the breakpoint used to step out. */ struct frame_id step_frame_id; +/*teawater rec begin----------------------------------------------------------*/ +struct frame_id step_prev_frame_id; +/*teawater rec end------------------------------------------------------------*/ enum step_over_calls_kind step_over_calls; @@ -737,6 +744,17 @@ step_1 (int skip_subroutines, int single if (!frame) /* Avoid coredump here. Why tho? */ error (_("No current frame")); step_frame_id = get_frame_id (frame); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse) { + frame = get_prev_frame (frame); + if (frame) { + step_prev_frame_id = get_frame_id (frame); + } + else { + step_prev_frame_id = null_frame_id; + } + } +/*teawater rec end------------------------------------------------------------*/ if (!single_inst) { @@ -836,6 +854,17 @@ step_once (int skip_subroutines, int sin if (!frame) /* Avoid coredump here. Why tho? */ error (_("No current frame")); step_frame_id = get_frame_id (frame); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse) { + frame = get_prev_frame (frame); + if (frame) { + step_prev_frame_id = get_frame_id (frame); + } + else { + step_prev_frame_id = null_frame_id; + } + } +/*teawater rec end------------------------------------------------------------*/ if (!single_inst) { @@ -1088,6 +1117,17 @@ until_next_command (int from_tty) step_over_calls = STEP_OVER_ALL; step_frame_id = get_frame_id (frame); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse) { + frame = get_prev_frame (frame); + if (frame) { + step_prev_frame_id = get_frame_id (frame); + } + else { + step_prev_frame_id = null_frame_id; + } + } +/*teawater rec end------------------------------------------------------------*/ step_multi = 0; /* Only one call to proceed */ --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -317,6 +317,9 @@ extern CORE_ADDR step_range_end; /* Excl and how to set the frame for the breakpoint used to step out. */ extern struct frame_id step_frame_id; +/*teawater rec begin----------------------------------------------------------*/ +extern struct frame_id step_prev_frame_id; +/*teawater rec end------------------------------------------------------------*/ /* 1 means step over all subroutine calls. -1 means step over calls to undebuggable functions. */ --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -49,6 +49,11 @@ #include "gdb_assert.h" #include "mi/mi-common.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +static int record_resume_step = 0; +/*teawater rec end------------------------------------------------------------*/ + /* Prototypes for local functions */ static void signals_info (char *, int); @@ -518,6 +523,20 @@ resume (int step, enum target_signal sig fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d)\n", step, sig); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_recording) { + if (record_list && (record_list->next || gdb_is_reverse)) { + discard_cleanups (old_cleanups); + record_wait_step = step; + return; + } + else { + step = 1; + record_message (); + } + } +/*teawater rec end------------------------------------------------------------*/ + /* FIXME: calling breakpoint_here_p (read_pc ()) three times! */ @@ -1026,10 +1045,19 @@ wait_for_inferior (int treat_exec_as_sig while (1) { +/*teawater rec begin----------------------------------------------------------*/ + if (record_list && (record_list->next || gdb_is_reverse)) { + ecs->ptid = record_wait (ecs->waiton_ptid, ecs->wp); + } + else { +/*teawater rec end------------------------------------------------------------*/ if (deprecated_target_wait_hook) ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp); else ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp); +/*teawater rec begin----------------------------------------------------------*/ + } +/*teawater rec end------------------------------------------------------------*/ if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD) { @@ -2003,11 +2031,19 @@ handle_inferior_event (struct execution_ be necessary for call dummies on a non-executable stack on SPARC. */ - if (stop_signal == TARGET_SIGNAL_TRAP) - ecs->random_signal - = !(bpstat_explains_signal (stop_bpstat) - || stepping_over_breakpoint - || (step_range_end && step_resume_breakpoint == NULL)); +/*teawater rec begin----------------------------------------------------------*/ + if (stop_signal == TARGET_SIGNAL_TRAP) { + if (gdb_is_reverse || gdb_is_recording) { + ecs->random_signal = 0; + } + else { + ecs->random_signal + = !(bpstat_explains_signal (stop_bpstat) + || stepping_over_breakpoint + || (step_range_end && step_resume_breakpoint == NULL)); + } + } +/*teawater rec end------------------------------------------------------------*/ else { ecs->random_signal = !bpstat_explains_signal (stop_bpstat); @@ -2489,6 +2525,16 @@ process_event_stop_test: /* We're doing a "next", set a breakpoint at callee's return address (the address at which the caller will resume). */ + +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + insert_step_resume_breakpoint_at_caller (get_current_frame ()); keep_going (ecs); return; @@ -2551,6 +2597,15 @@ process_event_stop_test: return; } +/*teawater rec begin----------------------------------------------------------*/ + if ((gdb_is_reverse || gdb_is_recording) && step_over_calls == STEP_OVER_UNDEBUGGABLE) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + /* Set a breakpoint at callee's return address (the address at which the caller will resume). */ insert_step_resume_breakpoint_at_caller (get_current_frame ()); @@ -2605,6 +2660,15 @@ process_event_stop_test: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n"); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + /* The inferior just stepped into, or returned to, an undebuggable function (where there is no debugging information and no line number corresponding to the address where the @@ -2654,15 +2718,51 @@ process_event_stop_test: or can this happen as a result of a return or longjmp?). */ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n"); + +/*teawater rec begin----------------------------------------------------------*/ + if ((step_over_calls == STEP_OVER_ALL && gdb_is_reverse) || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + stop_step = 1; print_stop_reason (END_STEPPING_RANGE, 0); stop_stepping (ecs); return; } - if ((stop_pc == ecs->sal.pc) +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse && frame_id_eq (get_frame_id (get_current_frame ()), step_prev_frame_id)) { + if (debug_infrun) { + fprintf_unfiltered (gdb_stdlog, "infrun: return to the prev function\n"); + } + stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + return; + } + + if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id) && (gdb_is_reverse || gdb_is_recording)) { + if ((stop_pc != ecs->sal.pc && gdb_is_reverse) || ( step_over_calls == STEP_OVER_ALL && gdb_is_recording)) { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: maybe stepped into subroutine\n"); + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } + } +/*teawater rec end------------------------------------------------------------*/ + +/*teawater rec begin----------------------------------------------------------*/ + //if ((stop_pc == ecs->sal.pc) + if (((stop_pc == ecs->sal.pc && !gdb_is_reverse) || (stop_pc >= ecs->sal.pc && stop_pc < ecs->sal.end && gdb_is_reverse)) && (ecs->current_line != ecs->sal.line || ecs->current_symtab != ecs->sal.symtab)) +/*teawater rec end------------------------------------------------------------*/ { /* We are at the start of a different line. So stop. Note that we don't stop if we step into the middle of a different line. @@ -2670,6 +2770,16 @@ process_event_stop_test: better. */ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n"); + +/*teawater rec begin----------------------------------------------------------*/ +#if 0 + if (gdb_is_recording) { + keep_going (ecs); + return; + } +#endif +/*teawater rec end------------------------------------------------------------*/ + stop_step = 1; print_stop_reason (END_STEPPING_RANGE, 0); stop_stepping (ecs); @@ -2726,11 +2836,13 @@ process_event_stop_test: static int currently_stepping (struct execution_control_state *ecs) { +/*teawater rec begin----------------------------------------------------------*/ return ((!ecs->handling_longjmp && ((step_range_end && step_resume_breakpoint == NULL) || stepping_over_breakpoint)) || ecs->stepping_through_solib_after_catch - || bpstat_should_step ()); + || bpstat_should_step () || record_resume_step); +/*teawater rec end------------------------------------------------------------*/ } /* Subroutine call with source code we should not step over. Do step --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -51,7 +51,9 @@ includedir = @includedir@ top_builddir = . SHELL = @SHELL@ -EXEEXT = @EXEEXT@ +#teawater rec begin------------------------------------------------------------- +EXEEXT = @EXEEXT@record +#teawater rec end--------------------------------------------------------------- AWK = @AWK@ LN_S = @LN_S@ @@ -586,6 +588,7 @@ TARGET_FLAGS_TO_PASS = \ # Links made at configuration time should not be specified here, since # SFILES is used in building the distribution archive. +#teawater rec begin------------------------------------------------------------- SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \ addrmap.c \ auxv.c ax-general.c ax-gdb.c \ @@ -633,7 +636,9 @@ SFILES = ada-exp.y ada-lang.c ada-typepr user-regs.c \ valarith.c valops.c valprint.c value.c varobj.c vec.c \ wrapper.c \ - xml-tdesc.c xml-support.c + xml-tdesc.c xml-support.c \ + record.c +#teawater rec end--------------------------------------------------------------- LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -1022,6 +1027,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_ $(CONFIG_SRCS) TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) +#teawater rec begin------------------------------------------------------------- COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ version.o \ annotate.o \ @@ -1072,7 +1078,9 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ tramp-frame.o \ solib.o solib-null.o \ prologue-value.o memory-map.o xml-support.o \ - target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o + target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ + record.o +#teawater rec end--------------------------------------------------------------- TSOBS = inflow.o --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -58,6 +58,11 @@ #include "dwarf2-frame.h" #include "user-regs.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +#include +/*teawater rec end------------------------------------------------------------*/ + static const struct objfile_data *mips_pdr_data; static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum); @@ -5213,6 +5218,619 @@ value_of_mips_user_reg (struct frame_inf return value_of_register (*reg_p, frame); } +/*teawater rec begin----------------------------------------------------------*/ +static CORE_ADDR mips_delay_slot_addr; +static CORE_ADDR mips_target_addr; + +static int +mips_record_32 (CORE_ADDR pc) +{ + uint32_t insn = (uint32_t)mips_fetch_instruction (pc); + uint32_t opcode; + const struct mips_regnum *regnum = mips_regnum (current_gdbarch); + int add_pc = 1; + uint32_t tmpu32; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: mips_record_32 insn = 0x%08x\n", (unsigned int)insn); + } + + opcode = insn >> 26; + switch (opcode) { + case 0x00: + switch ((insn >> 0) & 0x3f) { + /* sll */ + case 0x00: + /* srl */ + case 0x02: + /* sra */ + case 0x03: + /* sllv */ + case 0x04: + /* srlv */ + case 0x06: + /* srav */ + case 0x07: + /* movz */ + case 0x0a: + /* movn */ + case 0x0b: + /* mfhi */ + case 0x10: + /* mflo */ + case 0x12: + /* add */ + case 0x20: + /* addu */ + case 0x21: + /* sub */ + case 0x22: + /* subu */ + case 0x23: + /* and */ + case 0x24: + /* or */ + case 0x25: + /* xor */ + case 0x26: + /* nor */ + case 0x27: + /* slt */ + case 0x2a: + /* sltu */ + case 0x2b: + goto set_rd; + break; + /* jr */ + case 0x08: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&mips_target_addr); + goto set_delay_slot_pc; + break; + /* jalr */ + case 0x09: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&mips_target_addr); + goto set_delay_slot_pc; + } + break; + /* sync */ + case 0x0f: + break; + /* mthi */ + case 0x11: + if (record_arch_list_add_reg (regnum->hi)) { + return (-1); + } + break; + /* mtlo */ + case 0x13: + if (record_arch_list_add_reg (regnum->lo)) { + return (-1); + } + break; + /* mult */ + case 0x18: + /* multu */ + case 0x19: + /* div */ + case 0x1a: + /* divu */ + case 0x1b: + goto set_hi_lo; + break; + default: + goto no_support; + break; + } + break; + + case 0x01: + switch ((insn >> 16) & 0x1f) { + /* bltz */ + case 0x00: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 < 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bgez */ + case 0x01: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 >= 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bltzl */ + case 0x02: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 < 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bgezl */ + case 0x03: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 >= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bltzal */ + case 0x10: + if (record_arch_list_add_reg (31)) { + return (-1); + } + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 < 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bgezal */ + case 0x11: + if (record_arch_list_add_reg (31)) { + return (-1); + } + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 >= 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bltzall */ + case 0x12: + if (record_arch_list_add_reg (31)) { + return (-1); + } + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 < 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bgezall */ + case 0x13: + if (record_arch_list_add_reg (31)) { + return (-1); + } + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&tmpu32); + if (tmpu32 >= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + default: + goto no_support; + break; + } + break; + + /* j */ + case 0x02: + mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2); + goto set_delay_slot_pc; + break; + + /* beq */ + case 0x04: { + uint32_t tmp; + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp); + if (tmpu32 == tmp) { + goto set_imm_delay_slot_pc; + } + } + break; + + /* bne */ + case 0x05: { + uint32_t tmp; + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp); + if (tmpu32 != tmp) { + goto set_imm_delay_slot_pc; + } + } + break; + + /* blez */ + case 0x06: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + if (tmpu32 <= 0) { + goto set_imm_delay_slot_pc; + } + break; + + /* bgtz */ + case 0x07: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + if (tmpu32 > 0) { + goto set_imm_delay_slot_pc; + } + break; + + /* beql */ + case 0x14: { + uint32_t tmp; + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp); + if (tmpu32 == tmp) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + } + break; + + /* bnel */ + case 0x15: { + uint32_t tmp; + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + regcache_raw_read (record_regcache, (insn >> 16) & 0x1f), (gdb_byte *)&tmp); + if (tmpu32 == tmp) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + } + break; + + /* blezl */ + case 0x16: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + if (tmpu32 <= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* bgtzl */ + case 0x17: + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f), (gdb_byte *)&tmpu32); + if (tmpu32 > 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* jal */ + case 0x03: + if (record_arch_list_add_reg (31)) { + return (-1); + } + mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2); + goto set_delay_slot_pc; + break; + + /* jalx */ + case 0x1d: + goto no_support; + break; + + /* addi */ + case 0x08: + /* addiu */ + case 0x09: + /* slti */ + case 0x0a: + /* sltiu */ + case 0x0b: + /* andi */ + case 0x0c: + /* ori */ + case 0x0d: + /* xori */ + case 0x0e: + /* lui */ + case 0x0f: + goto set_rt; + break; + + /* COP0 */ + case 0x10: + if ((insn >> 25) & 0x1) { + switch ((insn >> 0) & 0x3f) { + /* eret */ + case 0x18: + goto set_pc; + break; + default: + goto no_support; + break; + } + } + else { + switch ((insn >> 21) & 0x1f) { + /* mfc0 */ + case 0x00: + goto set_rt; + break; + /* mtc0 */ + case 0x04: + { + switch ((insn >> 11) & 0x1f) { + case 13: + /* Cause */ + if (record_arch_list_add_reg (regnum->cause)) { + return (-1); + } + case 8: + /* badvaddr */ + if (record_arch_list_add_reg (regnum->badvaddr)) { + return (-1); + } + } + } + break; + default: + goto no_support; + break; + } + } + break; + + case 0x1c: + switch ((insn >> 0) & 0x3f) { + /* madd */ + case 0x00: + /* maddu */ + case 0x01: + /* msub */ + case 0x04: + /* msubu */ + case 0x05: + goto set_hi_lo; + break; + /* mul */ + case 0x02: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + goto set_hi_lo; + } + break; + /* clo */ + case 0x21: + /* clz */ + case 0x20: + goto set_rd; + break; + default: + goto no_support; + break; + } + break; + + /* lb */ + case 0x20: + /* lh */ + case 0x21: + /* lwl */ + case 0x22: + /* lw */ + case 0x23: + /* lbu */ + case 0x24: + /* lhu */ + case 0x25: + /* lwr */ + case 0x26: + /* ll */ + case 0x30: + goto set_rt; + break; + + /* sb */ + case 0x28: + /* sh */ + case 0x29: + /* swl */ + case 0x2a: + /* sw */ + case 0x2b: + /* swr */ + case 0x2e: + /* sc */ + case 0x38: + { + uint32_t addr; + + /* addr */ + /* base */ + regcache_raw_read (record_regcache, (insn >> 21) & 0x1f, (gdb_byte *)&addr); + /* offset */ + addr += (insn >> 0) & 0xffff; + + switch (opcode) { + /* sb */ + case 0x28: + if (record_arch_list_add_mem (addr, 1)) { + return (-1); + } + break; + /* sh */ + case 0x29: + if (record_arch_list_add_mem (addr, 2)) { + return (-1); + } + break; + /* swl */ + case 0x2a: + /* swr */ + case 0x2e: + if (record_arch_list_add_mem (addr & 0xffffff00, 2)) { + return (-1); + } + break; + /* sw */ + case 0x2b: + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + break; + /* sc */ + case 0x38: + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + goto set_rt; + break; + } + } + break; + /* pref */ + case 0x33: + break; + + default: + goto no_support; + break; + } + +out: + if (record_delay_slot) { + if (add_pc) { + if (record_arch_list_add_reg (regnum->pc)) { + return (-1); + } + add_pc = 0; + } + } + if (record_arch_list_add_end (add_pc)) { + return (-1); + } + return (0); + +no_support: + printf_unfiltered (_("record: record and reverse function don't support 32 bits instruction 0x%08x.\n"), (unsigned int)insn); + return (-1); + +set_rd: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + } + goto out; + +set_rt: + { + uint32_t rt = (insn >> 16) & 0x1f; + if (rt != 0) { + if (record_arch_list_add_reg (rt)) { + return (-1); + } + } + } + goto out; + +set_imm_delay_slot_pc: + { + uint32_t imm = (insn >> 0) & 0xffff; + if (imm >> 15) { + imm |= 0xffff0000; + } + imm <<= 2; + mips_target_addr = pc + 4 + imm; + } + goto set_delay_slot_pc; + +set_delay_slot_pc: + mips_delay_slot_addr = pc + 4; + record_delay_slot ++; + goto set_pc; + +set_pc: + if (record_arch_list_add_reg (regnum->pc)) { + return (-1); + } + add_pc = 0; + goto out; + +set_hi_lo: + if (record_arch_list_add_reg (regnum->hi)) { + return (-1); + } + if (record_arch_list_add_reg (regnum->lo)) { + return (-1); + } + goto out; +} + +static int +mips_record (void) +{ + CORE_ADDR pc = read_pc (); + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: mips_record pc = 0x%s\n", paddr_nz (pc)); + } + + if (mips_pc_is_mips16 (pc)) { + printf_unfiltered (_("record: record and reverse function don't support mips16.\n")); + return (-1); + } + + if (record_delay_slot) { + if (mips_record_32 (mips_delay_slot_addr)) { + return (-1); + } + if (mips_record_32 (mips_target_addr)) { + return (-1); + } + record_delay_slot --; + } + return (mips_record_32 (pc)); +} + +static void +mips_record_dasm (void) +{ + const struct mips_regnum *regnum; + ULONGEST pc; + + if (mips_pc_is_mips16 (read_pc ())) { + error (_("record: record and reverse function don't support mips16.\n")); + } + + regnum = mips_regnum (current_gdbarch); + regcache_cooked_read_unsigned (record_regcache, regnum->pc, &pc); + if (gdb_is_reverse) { + pc -= 4; + } + else { + pc += 4; + } + regcache_cooked_write_unsigned (record_regcache, regnum->pc, pc); +} +/*teawater rec end------------------------------------------------------------*/ + static struct gdbarch * mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { @@ -5877,6 +6495,11 @@ mips_gdbarch_init (struct gdbarch_info i user_reg_add (gdbarch, mips_register_aliases[i].name, value_of_mips_user_reg, &mips_register_aliases[i].regnum); +/*teawater rec begin----------------------------------------------------------*/ + set_gdbarch_record (gdbarch, mips_record); + set_gdbarch_record_dasm (gdbarch, mips_record_dasm); +/*teawater rec end------------------------------------------------------------*/ + return gdbarch; } --- a/gdb/record.c +++ b/gdb/record.c @@ -0,0 +1,471 @@ +/* Record v0.1.2 for GDB, the GNU debugger. + Written by Teawater Zhu + + 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 . */ + +#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 +#include +#include "mips-tdep.h" +#include +#include +#include +#include +#include "frame-unwind.h" +#include "gdbthread.h" +#include "exceptions.h" +#include "infcall.h" +#include "source.h" +#include "top.h" +#include "record.h" + +#define RECORD_REC_PROMPT "(rec) " +#define RECORD_REV_PROMPT "(rev) " + +extern struct breakpoint *breakpoint_chain; + +record_t *record_list = NULL; +record_t *record_arch_list_head = NULL; +record_t *record_arch_list_tail = NULL; +unsigned int gdb_is_recording = 0; +int gdb_is_reverse = 0; +int debug_record = 0; +int record_wait_step = 0; +int record_delay_slot = 0; +static sigset_t record_maskall; +static int record_get_sig = 0; +struct regcache *record_regcache; +static char record_gdb_prompt[20]; + +static void +show_debug_record (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Record debugging is %s.\n"), value); +} + +static void +record_list_release (record_t *rec) +{ + record_t *tmp; + + while (rec) { + tmp = rec; + rec = rec->prev; + xfree (tmp); + } +} + +void +record_message (void) +{ + int ret; + + record_arch_list_head = NULL; + record_arch_list_tail = NULL; + record_regcache = get_current_regcache (); + + ret = gdbarch_record (current_gdbarch); + if (ret > 0) { + record_list_release (record_arch_list_tail); + error (_("record: record pause the program.")); + } + if (ret < 0) { + record_delay_slot = 0; + record_list_release (record_arch_list_tail); + error (_("record: record message error.")); + } + + if (record_list) { + record_list->next = record_arch_list_head; + record_arch_list_head->prev = record_list; + record_list = record_arch_list_tail; + } + else { + record_list = record_arch_list_tail; + } +} + +static void +record_arch_list_add (record_t *rec) +{ + if (record_arch_list_tail) { + record_arch_list_tail->next = rec; + rec->prev = record_arch_list_tail; + record_arch_list_tail = rec; + } + else { + record_arch_list_head = rec; + record_arch_list_tail = rec; + } +} + +int +record_arch_list_add_reg (int num) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add reg num = %d to arch list.\n", num); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->u.reg.val = (gdb_byte *)xmalloc (MAX_REGISTER_SIZE); + if (!rec->u.reg.val) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + xfree (rec); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 1; + rec->u.reg.num = num; + + regcache_raw_read (record_regcache, num, rec->u.reg.val); + + record_arch_list_add (rec); + + return (0); +} + +int +record_arch_list_add_mem (CORE_ADDR addr, int len) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add mem addr = 0x%s len = %d to arch list.\n", paddr_nz (addr), len); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->u.mem.val = (gdb_byte *)xmalloc (len); + if (!rec->u.mem.val) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + xfree (rec); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 2; + rec->u.mem.addr = addr; + rec->u.mem.len = len; + + if (target_read_memory (addr, rec->u.mem.val, len)) { + fprintf_unfiltered (gdb_stdlog, "record: read memory addr = 0x%s len = %d error.\n", paddr_nz (addr), len); + xfree (rec->u.mem.val); + xfree (rec); + return (-1); + } + + record_arch_list_add (rec); + + return (0); +} + +int +record_arch_list_add_end (int need_dasm) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add end need_dasm = %d to arch list.\n", need_dasm); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 0; + + rec->u.need_dasm = need_dasm; + + record_arch_list_add (rec); + + return (0); +} + +static void +record_sig_handler (int signo) +{ + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: get a signal\n"); + } + record_wait_step = 1; + record_get_sig = 1; +} + +ptid_t +record_wait (ptid_t ptid, struct target_waitstatus *status) +{ + struct sigaction act, old_act; + static int state = 0; /* 0 normal 1 to the end 2 to the begin */ + int con = 1; + int insn_end = 0; + int need_dasm = 0; + struct regcache *regcache = get_current_regcache (); + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_wait step = %d\n", record_wait_step); + } + + record_get_sig = 0; + act.sa_handler = record_sig_handler; + act.sa_mask = record_maskall; + act.sa_flags = SA_RESTART; + if (sigaction (SIGINT, &act, &old_act)) { + perror_with_name (_("sigaction")); + } + + do { + /* check state */ + if ((gdb_is_reverse && !record_list->prev && state == 2) || (!gdb_is_reverse && !record_list->next && state == 1)) { + if (state == 1) { + fprintf_unfiltered (gdb_stdlog, "record: running to the end of record list.\n"); + } + else if (state == 2) { + fprintf_unfiltered (gdb_stdlog, "record: running to the begin of record list.\n"); + } + stop_soon = STOP_QUIETLY; + break; + } + state = 0; + + /* set register and memory according to record_list */ + if (record_list->type == 1) { + /* reg */ + gdb_byte reg[MAX_REGISTER_SIZE]; + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list reg num = %d to arch list.\n", record_list->u.reg.num); + } + regcache_cooked_read (regcache, record_list->u.reg.num, reg); + regcache_cooked_write (regcache, record_list->u.reg.num, record_list->u.reg.val); + memcpy (record_list->u.reg.val, reg, MAX_REGISTER_SIZE); + } + else if (record_list->type == 2) { + /* mem */ + gdb_byte mem[record_list->u.mem.len]; + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list mem addr = 0x%s len = %d to current.\n", paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + if (target_read_memory (record_list->u.mem.addr, mem, record_list->u.mem.len)) { + error (_("record: read memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + if (target_write_memory (record_list->u.mem.addr, record_list->u.mem.val, record_list->u.mem.len)) { + error (_("record: write memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + memcpy (record_list->u.mem.val, mem, record_list->u.mem.len); + } + else { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list end need_dasm = %d to current.\n", record_list->u.need_dasm); + } + + need_dasm = record_list->u.need_dasm; + if (!gdb_is_reverse) { + insn_end = 1; + } + } + + if (gdb_is_reverse) { + if (record_list->prev) { + record_list = record_list->prev; + if (!record_list->type) { + insn_end = 1; + } + } + else { + state = 2; + insn_end = 1; + } + } + else { + if (record_list->next) { + record_list = record_list->next; + } + else { + state = 1; + } + } + + if (insn_end) { + struct breakpoint *b; + CORE_ADDR tmp_pc; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: insn end need_dasm = %d to current.\n", need_dasm); + } + + if (need_dasm) { + gdbarch_record_dasm (current_gdbarch); + } + + //registers_changed (); + tmp_pc = read_pc (); + + /* end */ + if (record_wait_step) { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: step.\n"); + } + con = 0; + } + + /* check breakpoint */ + for (b = breakpoint_chain; b; b = b->next) { + if (b->loc->inserted) { + if (b->loc->target_info.placed_address == tmp_pc) { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: break at 0x%s.\n", paddr_nz (tmp_pc)); + } + con = 0; + break; + } + } + } + + insn_end = 0; + } + } while (con); + + if (sigaction (SIGALRM, &old_act, NULL)) { + perror_with_name (_("sigaction")); + } + + status->kind = TARGET_WAITKIND_STOPPED; + if (record_get_sig) { + status->value.sig = TARGET_SIGNAL_INT; + } + else { + status->value.sig = TARGET_SIGNAL_TRAP; + } + + return (inferior_ptid); +} + +void +record_close (void) +{ + gdb_is_recording = 0; + gdb_is_reverse = 0; + record_list_release (record_list); + record_list = NULL; + record_delay_slot = 0; + printf_unfiltered (_("record: record and reverse function is stopped.\n")); +} + +static void +cmd_record_start (char *args, int from_tty) +{ + /* check exec */ + if (!target_has_execution) { + error (_("record: the program is not being run.")); + } + + if (!gdbarch_record_p (current_gdbarch)) { + error (_("record: the current gdbarch don't support record function.")); + } + + if (gdb_is_recording) { + printf_unfiltered (_("record: record and reverse function has already been started.\n")); + } + else { + char *tmp; + + gdb_is_recording = 1; + printf_unfiltered (_("record: record and reverse function is started.\n")); + + tmp = get_prompt (); + snprintf (record_gdb_prompt, 20, "%s", tmp); + set_prompt (RECORD_REC_PROMPT); + } +} + +static void +cmd_record_stop (char *args, int from_tty) +{ + /* check exec */ + if (!target_has_execution) { + error (_("record: the program is not being run.")); + } + + if (!gdbarch_record_p (current_gdbarch)) { + error (_("record: the current gdbarch don't support record function.")); + } + + if (gdb_is_recording) { + record_close (); + set_prompt (record_gdb_prompt); + } + else { + printf_unfiltered (_("record: record and reverse function is not started.\n")); + } +} + +static void +cmd_reverse (char *args, int from_tty) +{ + if (gdb_is_reverse) { + gdb_is_reverse = 0; + printf_unfiltered (_("record: GDB is set to normal debug mode.\n")); + set_prompt (RECORD_REC_PROMPT); + } + else { + if (!record_list) { + error (_("record: record and reverse function is not started.")); + } + gdb_is_reverse = 1; + printf_unfiltered (_("record: GDB is set to reverse debug mode.\n")); + set_prompt (RECORD_REV_PROMPT); + } +} + +void +_initialize_record (void) +{ + /* init record_maskall */ + if (sigfillset (&record_maskall) == -1) { + perror_with_name (_("sigfillset")); + } + + add_setshow_zinteger_cmd ("record", class_maintenance, &debug_record, _("Set record debugging."), _("Show record debugging."), _("When non-zero, record specific debugging is enabled."), NULL, show_debug_record, &setdebuglist, &showdebuglist); + add_com ("record", class_obscure, cmd_record_start, _("Start the record and reverse function.")); + add_com_alias ("rec", "record", class_obscure, 1); + add_com ("stoprecord", class_obscure, cmd_record_stop, _("Stop the record and reverse function.")); + add_com_alias ("srec", "stoprecord", class_obscure, 1); + add_com ("reverse", class_obscure, cmd_reverse, _("Set GDB to the reverse debug mode or the normal debug mode.")); + add_com_alias ("rev", "reverse", class_obscure, 1); +} --- a/gdb/record.h +++ b/gdb/record.h @@ -0,0 +1,64 @@ +/* Record v0.1.2 for GDB, the GNU debugger. + Written by Teawater Zhu + + 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 . */ + +#ifndef _RECORD_H_ +#define _RECORD_H_ + +typedef struct record_reg_s { + int num; + gdb_byte *val; +} record_reg_t; + +typedef struct record_mem_s { + CORE_ADDR addr; + int len; + gdb_byte *val; +} record_mem_t; + +typedef struct record_s { + struct record_s *prev; + struct record_s *next; + int type; /* 1 reg 2 mem 0 end */ + union { + /* reg */ + record_reg_t reg; + /* mem */ + record_mem_t mem; + /* end */ + int need_dasm; + } u; +} record_t; + +extern record_t *record_list; +extern record_t *record_arch_list_head; +extern record_t *record_arch_list_tail; +extern int record_arch_need_dasm; +extern unsigned int gdb_is_recording; +extern int gdb_is_reverse; +extern int debug_record; +extern int record_wait_step; +extern int record_delay_slot; +extern struct regcache *record_regcache; + +extern void record_message (void); +extern int record_arch_list_add_reg (int num); +extern int record_arch_list_add_mem (CORE_ADDR addr, int len); +extern int record_arch_list_add_end (int need_dasm); +extern ptid_t record_wait (ptid_t ptid, struct target_waitstatus * status); +extern void record_close (void); +#endif //_RECORD_H_ --- a/gdb/target.c +++ b/gdb/target.c @@ -39,6 +39,9 @@ #include "gdbcore.h" #include "exceptions.h" #include "target-descriptions.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +/*teawater rec end------------------------------------------------------------*/ static void target_info (char *, int); @@ -1702,6 +1705,17 @@ target_follow_fork (int follow_child) "could not find a target to follow fork"); } +/*teawater rec begin----------------------------------------------------------*/ +void +target_mourn_inferior (void) +{ + if (gdb_is_recording) { + record_close (); + } + (*current_target.to_mourn_inferior) (); +} +/*teawater rec end------------------------------------------------------------*/ + /* Look for a target which can describe architectural features, starting from TARGET. If we find one, return its description. */ @@ -2065,6 +2079,11 @@ debug_to_close (int quitting) void target_close (struct target_ops *targ, int quitting) { +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_recording) { + record_close (); + } +/*teawater rec end------------------------------------------------------------*/ if (targ->to_xclose != NULL) targ->to_xclose (targ, quitting); else if (targ->to_close != NULL) --- a/gdb/target.h +++ b/gdb/target.h @@ -861,8 +861,13 @@ int target_follow_fork (int follow_child /* The inferior process has died. Do what is right. */ +/*teawater rec begin----------------------------------------------------------*/ +/* #define target_mourn_inferior() \ (*current_target.to_mourn_inferior) () +*/ +extern void target_mourn_inferior (void); +/*teawater rec end------------------------------------------------------------*/ /* Does target have enough data to do a run or attach command? */ --- a/gdb/top.c +++ b/gdb/top.c @@ -1145,6 +1145,10 @@ print_gdb_version (struct ui_file *strea fprintf_filtered (stream, "GNU gdb %s\n", version); +/*teawater rec begin----------------------------------------------------------*/ + fprintf_filtered (stream, "Record 0.1.3\n"); +/*teawater rec end------------------------------------------------------------*/ + /* Second line is a copyright notice. */ fprintf_filtered (stream, "Copyright (C) 2008 Free Software Foundation, Inc.\n");