OSDN Git Service

2009-09-21 Hui Zhu <teawater@gmail.com>
authorHui Zhu <teawater@gmail.com>
Mon, 21 Sep 2009 06:57:02 +0000 (06:57 +0000)
committerHui Zhu <teawater@gmail.com>
Mon, 21 Sep 2009 06:57:02 +0000 (06:57 +0000)
    Michael Snyder  <msnyder@vmware.com>

* amd64-linux-tdep.c (amd64_all_but_ip_registers_record): New
function.
(amd64_linux_syscall_record): Call
amd64_all_but_ip_registers_record if syscall is
sys_rt_sigreturn.
(AMD64_LINUX_redzone, AMD64_LINUX_xstate,
AMD64_LINUX_frame_size): New macros.
(amd64_linux_record_signal): New function.
(amd64_linux_init_abi): Call set_gdbarch_process_record_signal.

2009-09-21  Hui Zhu  <teawater@gmail.com>
    Michael Snyder  <msnyder@vmware.com>

* i386-linux-tdep.c (i386_all_but_ip_registers_record): New
function.
(i386_linux_intx80_sysenter_record): Call
i386_all_but_ip_registers_record if syscall is sys_sigreturn
or sys_rt_sigreturn.
(I386_LINUX_xstate, I386_LINUX_frame_size): New macros.
(i386_linux_record_signal): New function.
(i386_linux_init_abi): Call set_gdbarch_process_record_signal.

2009-09-21  Hui Zhu  <teawater@gmail.com>
    Michael Snyder  <msnyder@vmware.com>

* record.c (record_end_entry): New struct.
(record_type): Add end.
(record_arch_list_add_end): Set rec->u.end.sigval to
TARGET_SIGNAL_0.
(record_message_args): New struct.
(record_message): Call gdbarch_process_record_signal.
(do_record_message): Add argument "signal".
(record_resume): Ditto.
(record_wait): Ditto.  Check record_list->u.end.sigval
in replay mode.

2009-09-21  Hui Zhu  <teawater@gmail.com>
    Michael Snyder  <msnyder@vmware.com>

* gdbarch.sh (process_record_signal): New interface.

gdb/ChangeLog
gdb/amd64-linux-tdep.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/i386-linux-tdep.c
gdb/record.c

index dc5bef7..9168472 100644 (file)
@@ -1,3 +1,47 @@
+2009-09-21  Hui Zhu  <teawater@gmail.com>
+           Michael Snyder  <msnyder@vmware.com>
+
+       * amd64-linux-tdep.c (amd64_all_but_ip_registers_record): New
+       function.
+       (amd64_linux_syscall_record): Call
+       amd64_all_but_ip_registers_record if syscall is
+       sys_rt_sigreturn.
+       (AMD64_LINUX_redzone, AMD64_LINUX_xstate,
+       AMD64_LINUX_frame_size): New macros.
+       (amd64_linux_record_signal): New function.
+       (amd64_linux_init_abi): Call set_gdbarch_process_record_signal.
+
+2009-09-21  Hui Zhu  <teawater@gmail.com>
+           Michael Snyder  <msnyder@vmware.com>
+
+       * i386-linux-tdep.c (i386_all_but_ip_registers_record): New
+       function.
+       (i386_linux_intx80_sysenter_record): Call
+       i386_all_but_ip_registers_record if syscall is sys_sigreturn
+       or sys_rt_sigreturn.
+       (I386_LINUX_xstate, I386_LINUX_frame_size): New macros.
+       (i386_linux_record_signal): New function.
+       (i386_linux_init_abi): Call set_gdbarch_process_record_signal.
+
+2009-09-21  Hui Zhu  <teawater@gmail.com>
+           Michael Snyder  <msnyder@vmware.com>
+
+       * record.c (record_end_entry): New struct.
+       (record_type): Add end.
+       (record_arch_list_add_end): Set rec->u.end.sigval to
+       TARGET_SIGNAL_0.
+       (record_message_args): New struct.
+       (record_message): Call gdbarch_process_record_signal.
+       (do_record_message): Add argument "signal".
+       (record_resume): Ditto.
+       (record_wait): Ditto.  Check record_list->u.end.sigval
+       in replay mode.
+
+2009-09-21  Hui Zhu  <teawater@gmail.com>
+           Michael Snyder  <msnyder@vmware.com>
+
+       * gdbarch.sh (process_record_signal): New interface.
+
 2009-09-19  Maxim Grigoriev  <maxim2405@gmail.com>
 
        * xtensa-tdep.c (call0_analyze_prologue): Replace INT_MAX by UNIT_MAX.
index f527b7e..0955331 100644 (file)
@@ -289,16 +289,48 @@ amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
   regcache_cooked_write_unsigned (regcache, AMD64_LINUX_ORIG_RAX_REGNUM, -1);
 }
 
-/* Parse the arguments of current system call instruction and record
-   the values of the registers and memory that will be changed into
-   "record_arch_list".  This instruction is "syscall".
-
-   Return -1 if something wrong.  */
+/* Record all registers but IP register for process-record.  */
 
-static struct linux_record_tdep amd64_linux_record_tdep;
+static int
+amd64_all_but_ip_registers_record (struct regcache *regcache)
+{
+  if (record_arch_list_add_reg (regcache, AMD64_RAX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RCX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RDX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RBX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RSP_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RBP_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RSI_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_RDI_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R8_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R9_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R10_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R12_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R13_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R14_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_R15_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, AMD64_EFLAGS_REGNUM))
+    return -1;
 
-#define RECORD_ARCH_GET_FS     0x1003
-#define RECORD_ARCH_GET_GS     0x1004
+  return 0;
+}
 
 /* amd64_canonicalize_syscall maps from the native amd64 Linux set 
    of syscall ids into a canonical set of syscall ids used by 
@@ -1111,6 +1143,17 @@ amd64_canonicalize_syscall (enum amd64_syscall syscall)
   }
 }
 
+/* Parse the arguments of current system call instruction and record
+   the values of the registers and memory that will be changed into
+   "record_arch_list".  This instruction is "syscall".
+
+   Return -1 if something wrong.  */
+
+static struct linux_record_tdep amd64_linux_record_tdep;
+
+#define RECORD_ARCH_GET_FS     0x1003
+#define RECORD_ARCH_GET_GS     0x1004
+
 static int
 amd64_linux_syscall_record (struct regcache *regcache)
 {
@@ -1120,27 +1163,39 @@ amd64_linux_syscall_record (struct regcache *regcache)
 
   regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &syscall_native);
 
-  syscall_gdb = amd64_canonicalize_syscall (syscall_native);
-
-  if (syscall_native == amd64_sys_arch_prctl) 
+  switch (syscall_native)
     {
-      ULONGEST arg3;
-
-      regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3,
-                                 &arg3);
-      if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS)
-      {
-       CORE_ADDR addr;
-
-       regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg2,
-                                   &addr);
-       if (record_arch_list_add_mem (addr, 
-                                     amd64_linux_record_tdep.size_ulong))
-         return -1;
-      }
-      goto record_regs;
+    case amd64_sys_rt_sigreturn:
+      if (amd64_all_but_ip_registers_record (regcache))
+        return -1;
+      return 0;
+      break;
+
+    case amd64_sys_arch_prctl:
+      if (syscall_native == amd64_sys_arch_prctl)
+        {
+          ULONGEST arg3;
+
+          regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3,
+                                      &arg3);
+          if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS)
+            {
+             CORE_ADDR addr;
+
+             regcache_raw_read_unsigned (regcache,
+                                          amd64_linux_record_tdep.arg2,
+                                          &addr);
+             if (record_arch_list_add_mem (addr,
+                                            amd64_linux_record_tdep.size_ulong))
+                return -1;
+            }
+          goto record_regs;
+        }
+      break;
     }
 
+  syscall_gdb = amd64_canonicalize_syscall (syscall_native);
+
   if (syscall_gdb < 0)
     {
       printf_unfiltered (_("Process record and replay target doesn't "
@@ -1163,6 +1218,44 @@ amd64_linux_syscall_record (struct regcache *regcache)
   if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
     return -1;
 
+  return 0;
+}
+
+#define AMD64_LINUX_redzone    128
+#define AMD64_LINUX_xstate     512
+#define AMD64_LINUX_frame_size 560
+
+int
+amd64_linux_record_signal (struct gdbarch *gdbarch,
+                           struct regcache *regcache,
+                           enum target_signal signal)
+{
+  ULONGEST rsp;
+
+  if (amd64_all_but_ip_registers_record (regcache))
+    return -1;
+
+  if (record_arch_list_add_reg (regcache, AMD64_RIP_REGNUM))
+    return -1;
+
+  /* Record the change in the stack.  */
+  regcache_raw_read_unsigned (regcache, AMD64_RSP_REGNUM, &rsp);
+  /* redzone
+     sp -= 128; */
+  rsp -= AMD64_LINUX_redzone;
+  /* This is for xstate.
+     sp -= sizeof (struct _fpstate);  */
+  rsp -= AMD64_LINUX_xstate;
+  /* This is for frame_size.
+     sp -= sizeof (struct rt_sigframe);  */
+  rsp -= AMD64_LINUX_frame_size;
+  if (record_arch_list_add_mem (rsp, AMD64_LINUX_redzone
+                                     + AMD64_LINUX_xstate
+                                     + AMD64_LINUX_frame_size))
+    return -1;
+
+  if (record_arch_list_add_end ())
+    return -1;
 
   return 0;
 }
@@ -1218,6 +1311,7 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 
   set_gdbarch_process_record (gdbarch, i386_process_record);
+  set_gdbarch_process_record_signal (gdbarch, amd64_linux_record_signal);
 
   /* Initialize the amd64_linux_record_tdep.  */
   /* These values are the size of the type that will be used in a system
index e1b9d0d..2ae3835 100644 (file)
@@ -240,6 +240,7 @@ struct gdbarch
   gdbarch_static_transform_name_ftype *static_transform_name;
   int sofun_address_maybe_missing;
   gdbarch_process_record_ftype *process_record;
+  gdbarch_process_record_signal_ftype *process_record_signal;
   gdbarch_target_signal_from_host_ftype *target_signal_from_host;
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
   gdbarch_get_siginfo_type_ftype *get_siginfo_type;
@@ -378,6 +379,7 @@ struct gdbarch startup_gdbarch =
   0,  /* static_transform_name */
   0,  /* sofun_address_maybe_missing */
   0,  /* process_record */
+  0,  /* process_record_signal */
   default_target_signal_from_host,  /* target_signal_from_host */
   default_target_signal_to_host,  /* target_signal_to_host */
   0,  /* get_siginfo_type */
@@ -635,6 +637,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of static_transform_name, has predicate */
   /* Skip verify of sofun_address_maybe_missing, invalid_p == 0 */
   /* Skip verify of process_record, has predicate */
+  /* Skip verify of process_record_signal, has predicate */
   /* Skip verify of target_signal_from_host, invalid_p == 0 */
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
   /* Skip verify of get_siginfo_type, has predicate */
@@ -971,6 +974,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: process_record = <%s>\n",
                       host_address_to_string (gdbarch->process_record));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_process_record_signal_p() = %d\n",
+                      gdbarch_process_record_signal_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: process_record_signal = <%s>\n",
+                      host_address_to_string (gdbarch->process_record_signal));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: ps_regnum = %s\n",
                       plongest (gdbarch->ps_regnum));
   fprintf_unfiltered (file,
@@ -3307,6 +3316,30 @@ set_gdbarch_process_record (struct gdbarch *gdbarch,
   gdbarch->process_record = process_record;
 }
 
+int
+gdbarch_process_record_signal_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->process_record_signal != NULL;
+}
+
+int
+gdbarch_process_record_signal (struct gdbarch *gdbarch, struct regcache *regcache, enum target_signal signal)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->process_record_signal != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_process_record_signal called\n");
+  return gdbarch->process_record_signal (gdbarch, regcache, signal);
+}
+
+void
+set_gdbarch_process_record_signal (struct gdbarch *gdbarch,
+                                   gdbarch_process_record_signal_ftype process_record_signal)
+{
+  gdbarch->process_record_signal = process_record_signal;
+}
+
 enum target_signal
 gdbarch_target_signal_from_host (struct gdbarch *gdbarch, int signo)
 {
index 027541d..950b7ca 100644 (file)
@@ -822,6 +822,15 @@ typedef int (gdbarch_process_record_ftype) (struct gdbarch *gdbarch, struct regc
 extern int gdbarch_process_record (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr);
 extern void set_gdbarch_process_record (struct gdbarch *gdbarch, gdbarch_process_record_ftype *process_record);
 
+/* Save process state after a signal.
+   Return -1 if something goes wrong, 0 otherwise. */
+
+extern int gdbarch_process_record_signal_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_process_record_signal_ftype) (struct gdbarch *gdbarch, struct regcache *regcache, enum target_signal signal);
+extern int gdbarch_process_record_signal (struct gdbarch *gdbarch, struct regcache *regcache, enum target_signal signal);
+extern void set_gdbarch_process_record_signal (struct gdbarch *gdbarch, gdbarch_process_record_signal_ftype *process_record_signal);
+
 /* Signal translation: translate inferior's signal (host's) number into
    GDB's representation. */
 
index 3a6e483..1546342 100755 (executable)
@@ -709,6 +709,10 @@ v:int:sofun_address_maybe_missing:::0:0::0
 # Return -1 if something goes wrong, 0 otherwise.
 M:int:process_record:struct regcache *regcache, CORE_ADDR addr:regcache, addr
 
+# Save process state after a signal.
+# Return -1 if something goes wrong, 0 otherwise.
+M:int:process_record_signal:struct regcache *regcache, enum target_signal signal:regcache, signal
+
 # Signal translation: translate inferior's signal (host's) number into
 # GDB's representation.
 m:enum target_signal:target_signal_from_host:int signo:signo::default_target_signal_from_host::0
index 78fe88e..354daf3 100644 (file)
@@ -358,7 +358,32 @@ i386_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
   regcache_cooked_write_unsigned (regcache, I386_LINUX_ORIG_EAX_REGNUM, -1);
 }
 
-static struct linux_record_tdep i386_linux_record_tdep;
+/* Record all registers but IP register for process-record.  */
+
+static int
+i386_all_but_ip_registers_record (struct regcache *regcache)
+{
+  if (record_arch_list_add_reg (regcache, I386_EAX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_ECX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_EDX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_EBX_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_ESP_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_EBP_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_ESI_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_EDI_REGNUM))
+    return -1;
+  if (record_arch_list_add_reg (regcache, I386_EFLAGS_REGNUM))
+    return -1;
+
+  return 0;
+}
 
 /* i386_canonicalize_syscall maps from the native i386 Linux set
    of syscall ids into a canonical set of syscall ids used by
@@ -383,6 +408,8 @@ i386_canonicalize_syscall (int syscall)
 
    Return -1 if something wrong.  */
 
+static struct linux_record_tdep i386_linux_record_tdep;
+
 static int
 i386_linux_intx80_sysenter_record (struct regcache *regcache)
 {
@@ -402,6 +429,14 @@ i386_linux_intx80_sysenter_record (struct regcache *regcache)
       return -1;
     }
 
+  if (syscall_gdb == gdb_sys_sigreturn
+      || syscall_gdb == gdb_sys_rt_sigreturn)
+   {
+     if (i386_all_but_ip_registers_record (regcache))
+       return -1;
+     return 0;
+   }
+
   ret = record_linux_system_call (syscall_gdb, regcache,
                                  &i386_linux_record_tdep);
   if (ret)
@@ -413,6 +448,40 @@ i386_linux_intx80_sysenter_record (struct regcache *regcache)
 
   return 0;
 }
+
+#define I386_LINUX_xstate      270
+#define I386_LINUX_frame_size  732
+
+int
+i386_linux_record_signal (struct gdbarch *gdbarch,
+                          struct regcache *regcache,
+                          enum target_signal signal)
+{
+  ULONGEST esp;
+
+  if (i386_all_but_ip_registers_record (regcache))
+    return -1;
+
+  if (record_arch_list_add_reg (regcache, I386_EIP_REGNUM))
+    return -1;
+
+  /* Record the change in the stack.  */
+  regcache_raw_read_unsigned (regcache, I386_ESP_REGNUM, &esp);
+  /* This is for xstate.
+     sp -= sizeof (struct _fpstate);  */
+  esp -= I386_LINUX_xstate;
+  /* This is for frame_size.
+     sp -= sizeof (struct rt_sigframe);  */
+  esp -= I386_LINUX_frame_size;
+  if (record_arch_list_add_mem (esp,
+                                I386_LINUX_xstate + I386_LINUX_frame_size))
+    return -1;
+
+  if (record_arch_list_add_end ())
+    return -1;
+
+  return 0;
+}
 \f
 
 static LONGEST
@@ -529,6 +598,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->sc_num_regs = ARRAY_SIZE (i386_linux_sc_reg_offset);
 
   set_gdbarch_process_record (gdbarch, i386_process_record);
+  set_gdbarch_process_record_signal (gdbarch, i386_linux_record_signal);
 
   /* Initialize the i386_linux_record_tdep.  */
   /* These values are the size of the type that will be used in a system
index fbf0003..8ad5bf8 100644 (file)
@@ -59,6 +59,11 @@ struct record_mem_entry
   gdb_byte *val;
 };
 
+struct record_end_entry
+{
+  enum target_signal sigval;
+};
+
 enum record_type
 {
   record_end = 0,
@@ -77,6 +82,8 @@ struct record_entry
     struct record_reg_entry reg;
     /* mem */
     struct record_mem_entry mem;
+    /* end */
+    struct record_end_entry end;
   } u;
 };
 
@@ -314,6 +321,7 @@ record_arch_list_add_end (void)
   rec->prev = NULL;
   rec->next = NULL;
   rec->type = record_end;
+  rec->u.end.sigval = TARGET_SIGNAL_0;
 
   record_arch_list_add (rec);
 
@@ -360,11 +368,17 @@ record_message_cleanups (void *ignore)
   record_list_release (record_arch_list_tail);
 }
 
+struct record_message_args {
+  struct regcache *regcache;
+  enum target_signal signal;
+};
+
 static int
 record_message (void *args)
 {
   int ret;
-  struct regcache *regcache = args;
+  struct record_message_args *myargs = args;
+  struct gdbarch *gdbarch = get_regcache_arch (myargs->regcache);
   struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0);
 
   record_arch_list_head = NULL;
@@ -373,9 +387,44 @@ record_message (void *args)
   /* Check record_insn_num.  */
   record_check_insn_num (1);
 
-  ret = gdbarch_process_record (get_regcache_arch (regcache),
-                               regcache,
-                               regcache_read_pc (regcache));
+  /* If gdb sends a signal value to target_resume,
+     save it in the 'end' field of the previous instruction.
+
+     Maybe process record should record what really happened,
+     rather than what gdb pretends has happened.
+
+     So if Linux delivered the signal to the child process during
+     the record mode, we will record it and deliver it again in
+     the replay mode.
+
+     If user says "ignore this signal" during the record mode, then
+     it will be ignored again during the replay mode (no matter if
+     the user says something different, like "deliver this signal"
+     during the replay mode).
+
+     User should understand that nothing he does during the replay
+     mode will change the behavior of the child.  If he tries,
+     then that is a user error.
+
+     But we should still deliver the signal to gdb during the replay,
+     if we delivered it during the recording.  Therefore we should
+     record the signal during record_wait, not record_resume.  */
+  if (record_list != &record_first)    /* FIXME better way to check */
+    {
+      gdb_assert (record_list->type == record_end);
+      record_list->u.end.sigval = myargs->signal;
+    }
+
+  if (myargs->signal == TARGET_SIGNAL_0
+      || !gdbarch_process_record_signal_p (gdbarch))
+    ret = gdbarch_process_record (gdbarch,
+                                 myargs->regcache,
+                                 regcache_read_pc (myargs->regcache));
+  else
+    ret = gdbarch_process_record_signal (gdbarch,
+                                        myargs->regcache,
+                                        myargs->signal);
+
   if (ret > 0)
     error (_("Process record: inferior program stopped."));
   if (ret < 0)
@@ -396,9 +445,14 @@ record_message (void *args)
 }
 
 static int
-do_record_message (struct regcache *regcache)
+do_record_message (struct regcache *regcache,
+                  enum target_signal signal)
 {
-  return catch_errors (record_message, regcache, NULL, RETURN_MASK_ALL);
+  struct record_message_args args;
+
+  args.regcache = regcache;
+  args.signal = signal;
+  return catch_errors (record_message, &args, NULL, RETURN_MASK_ALL);
 }
 
 /* Set to 1 if record_store_registers and record_xfer_partial
@@ -520,13 +574,13 @@ static int record_resume_error;
 
 static void
 record_resume (struct target_ops *ops, ptid_t ptid, int step,
-               enum target_signal siggnal)
+               enum target_signal signal)
 {
   record_resume_step = step;
 
   if (!RECORD_IS_REPLAY)
     {
-      if (do_record_message (get_current_regcache ()))
+      if (do_record_message (get_current_regcache (), signal))
         {
           record_resume_error = 0;
         }
@@ -536,7 +590,7 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step,
           return;
         }
       record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                siggnal);
+                                signal);
     }
 }
 
@@ -611,15 +665,16 @@ record_wait (struct target_ops *ops,
              ret = record_beneath_to_wait (record_beneath_to_wait_ops,
                                            ptid, status, options);
 
+             /* Is this a SIGTRAP?  */
              if (status->kind == TARGET_WAITKIND_STOPPED
                  && status->value.sig == TARGET_SIGNAL_TRAP)
                {
-                 /* Check if there is a breakpoint.  */
+                 /* Yes -- check if there is a breakpoint.  */
                  registers_changed ();
                  tmp_pc = regcache_read_pc (get_current_regcache ());
                  if (breakpoint_inserted_here_p (tmp_pc))
                    {
-                     /* There is a breakpoint.  */
+                     /* There is a breakpoint.  GDB will want to stop.  */
                      CORE_ADDR decr_pc_after_break =
                        gdbarch_decr_pc_after_break
                        (get_regcache_arch (get_current_regcache ()));
@@ -631,8 +686,12 @@ record_wait (struct target_ops *ops,
                    }
                  else
                    {
-                     /* There is not a breakpoint.  */
-                     if (!do_record_message (get_current_regcache ()))
+                     /* There is not a breakpoint, and gdb is not
+                        stepping, therefore gdb will not stop.
+                        Therefore we will not return to gdb.
+                        Record the insn and resume.  */
+                     if (!do_record_message (get_current_regcache (),
+                                             TARGET_SIGNAL_0))
                        {
                           break;
                        }
@@ -827,6 +886,10 @@ record_wait (struct target_ops *ops,
                                           gdbarch_decr_pc_after_break (gdbarch));
                      continue_flag = 0;
                    }
+                 /* Check target signal */
+                 if (record_list->u.end.sigval != TARGET_SIGNAL_0)
+                   /* FIXME: better way to check */
+                   continue_flag = 0;
                }
            }
 
@@ -851,6 +914,9 @@ record_wait (struct target_ops *ops,
 replay_out:
       if (record_get_sig)
        status->value.sig = TARGET_SIGNAL_INT;
+      else if (record_list->u.end.sigval != TARGET_SIGNAL_0)
+       /* FIXME: better way to check */
+       status->value.sig = record_list->u.end.sigval;
       else
        status->value.sig = TARGET_SIGNAL_TRAP;