Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Add support of software single step to process record
@ 2009-12-18  8:21 Hui Zhu
  2009-12-18 19:37 ` Michael Snyder
  2009-12-22 18:23 ` Tom Tromey
  0 siblings, 2 replies; 18+ messages in thread
From: Hui Zhu @ 2009-12-18  8:21 UTC (permalink / raw)
  To: gdb-patches ml; +Cc: Michael Snyder, shuchang zhou, paawan oza

[-- Attachment #1: Type: text/plain, Size: 4235 bytes --]

Hi guys,

This patch to make prec support software single step.
I just try it with i386.  Shuchang, please help me try it on mips.  :)

BTW, There are still some other patches for record_resume and
record_wait. And other arch patch is still not begin to be review.  So
this patch is not very urgency.  It just help the guys that are
working on prec arch porting.

Thanks,
Hui

2009-12-18  Hui Zhu  <teawater@gmail.com>

	* breakpoint.c (inserted_single_step_breakpoint_p): New
	function.
	* breakpoint.h (inserted_single_step_breakpoint_p): Extern.
	* record.c (record_resume): Add code for software single step.
	(record_wait): Ditto.

---
 breakpoint.c |   12 ++++++++++++
 breakpoint.h |    1 +
 record.c     |   35 ++++++++++++++++++++++++++++++-----
 3 files changed, 43 insertions(+), 5 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -9624,6 +9624,18 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }

+/* Check if the breakpoints used for software single stepping
inserted or not.  */
+
+int
+inserted_single_step_breakpoint_p (void)
+{
+  if (single_step_breakpoints[0] != NULL
+      || single_step_breakpoints[1] != NULL)
+    return 1;
+
+  return 1;
+}
+
 /* Remove and delete any breakpoints used for software single step.  */

 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int inserted_single_step_breakpoint_p (void);
 extern void remove_single_step_breakpoints (void);

 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -995,6 +995,8 @@ record_resume (struct target_ops *ops, p

   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = get_current_arch ();
+
       if (do_record_message (get_current_regcache (), signal))
         {
           record_resume_error = 0;
@@ -1004,8 +1006,18 @@ record_resume (struct target_ops *ops, p
           record_resume_error = 1;
           return;
         }
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (gdbarch_software_single_step_p (gdbarch))
+        {
+          if (!inserted_single_step_breakpoint_p ())
+            gdbarch_software_single_step (gdbarch, get_current_frame ());
+          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                    ptid, step, signal);
+          record_resume_step = 0;
+        }
+      else
+        record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+                                  signal);
     }
 }

@@ -1086,6 +1098,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = get_current_arch ();

 	  while (1)
 	    {
@@ -1108,6 +1121,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);

+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1133,9 +1149,18 @@ record_wait (struct target_ops *ops,
 		      if (!do_record_message (regcache, TARGET_SIGNAL_0))
 			break;

-		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
-						TARGET_SIGNAL_0);
+                      if (gdbarch_software_single_step_p (gdbarch))
+                        {
+                          gdbarch_software_single_step (gdbarch,
+                                                        get_current_frame ());
+                          record_beneath_to_resume
(record_beneath_to_resume_ops,
+                                                    ptid, 0,
+                                                    TARGET_SIGNAL_0);
+                        }
+                      else
+		        record_beneath_to_resume (record_beneath_to_resume_ops,
+						  ptid, 1,
+						  TARGET_SIGNAL_0);
 		      continue;
 		    }
 		}

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 3606 bytes --]

---
 breakpoint.c |   12 ++++++++++++
 breakpoint.h |    1 +
 record.c     |   35 ++++++++++++++++++++++++++++++-----
 3 files changed, 43 insertions(+), 5 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -9624,6 +9624,18 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping inserted or not.  */
+
+int
+inserted_single_step_breakpoint_p (void)
+{
+  if (single_step_breakpoints[0] != NULL
+      || single_step_breakpoints[1] != NULL)
+    return 1;
+
+  return 1;
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int inserted_single_step_breakpoint_p (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -995,6 +995,8 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = get_current_arch ();
+
       if (do_record_message (get_current_regcache (), signal))
         {
           record_resume_error = 0;
@@ -1004,8 +1006,18 @@ record_resume (struct target_ops *ops, p
           record_resume_error = 1;
           return;
         }
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (gdbarch_software_single_step_p (gdbarch))
+        {
+          if (!inserted_single_step_breakpoint_p ())
+            gdbarch_software_single_step (gdbarch, get_current_frame ());
+          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                    ptid, step, signal);
+          record_resume_step = 0;
+        }
+      else
+        record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+                                  signal);
     }
 }
 
@@ -1086,6 +1098,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = get_current_arch ();
 
 	  while (1)
 	    {
@@ -1108,6 +1121,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1133,9 +1149,18 @@ record_wait (struct target_ops *ops,
 		      if (!do_record_message (regcache, TARGET_SIGNAL_0))
 			break;
 
-		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
-						TARGET_SIGNAL_0);
+                      if (gdbarch_software_single_step_p (gdbarch))
+                        {
+                          gdbarch_software_single_step (gdbarch,
+                                                        get_current_frame ());
+                          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                                    ptid, 0,
+                                                    TARGET_SIGNAL_0);
+                        }
+                      else
+		        record_beneath_to_resume (record_beneath_to_resume_ops,
+						  ptid, 1,
+						  TARGET_SIGNAL_0);
 		      continue;
 		    }
 		}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-18  8:21 [RFC] Add support of software single step to process record Hui Zhu
@ 2009-12-18 19:37 ` Michael Snyder
  2009-12-20 13:48   ` Joel Brobecker
  2009-12-22 18:23 ` Tom Tromey
  1 sibling, 1 reply; 18+ messages in thread
From: Michael Snyder @ 2009-12-18 19:37 UTC (permalink / raw)
  To: Hui Zhu; +Cc: gdb-patches ml, shuchang zhou, paawan oza

Hui Zhu wrote:
> Hi guys,
> 
> This patch to make prec support software single step.
> I just try it with i386.  Shuchang, please help me try it on mips.  :)
> 
> BTW, There are still some other patches for record_resume and
> record_wait. And other arch patch is still not begin to be review.  So
> this patch is not very urgency.  It just help the guys that are
> working on prec arch porting.

Seems OK in principle.  Thanks for adding a nice clean API to breakpoint.


> 2009-12-18  Hui Zhu  <teawater@gmail.com>
> 
> 	* breakpoint.c (inserted_single_step_breakpoint_p): New
> 	function.
> 	* breakpoint.h (inserted_single_step_breakpoint_p): Extern.
> 	* record.c (record_resume): Add code for software single step.
> 	(record_wait): Ditto.
> 
> ---
>  breakpoint.c |   12 ++++++++++++
>  breakpoint.h |    1 +
>  record.c     |   35 ++++++++++++++++++++++++++++++-----
>  3 files changed, 43 insertions(+), 5 deletions(-)
> 
> --- a/breakpoint.c
> +++ b/breakpoint.c
> @@ -9624,6 +9624,18 @@ insert_single_step_breakpoint (struct gd
>  	     paddress (gdbarch, next_pc));
>  }
> 
> +/* Check if the breakpoints used for software single stepping
> inserted or not.  */
> +
> +int
> +inserted_single_step_breakpoint_p (void)
> +{
> +  if (single_step_breakpoints[0] != NULL
> +      || single_step_breakpoints[1] != NULL)
> +    return 1;
> +
> +  return 1;
> +}
> +
>  /* Remove and delete any breakpoints used for software single step.  */
> 
>  void
> --- a/breakpoint.h
> +++ b/breakpoint.h
> @@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
>     twice before remove is called.  */
>  extern void insert_single_step_breakpoint (struct gdbarch *,
>  					   struct address_space *, CORE_ADDR);
> +extern int inserted_single_step_breakpoint_p (void);
>  extern void remove_single_step_breakpoints (void);
> 
>  /* Manage manual breakpoints, separate from the normal chain of
> --- a/record.c
> +++ b/record.c
> @@ -995,6 +995,8 @@ record_resume (struct target_ops *ops, p
> 
>    if (!RECORD_IS_REPLAY)
>      {
> +      struct gdbarch *gdbarch = get_current_arch ();
> +
>        if (do_record_message (get_current_regcache (), signal))
>          {
>            record_resume_error = 0;
> @@ -1004,8 +1006,18 @@ record_resume (struct target_ops *ops, p
>            record_resume_error = 1;
>            return;
>          }
> -      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
> -                                signal);
> +
> +      if (gdbarch_software_single_step_p (gdbarch))
> +        {
> +          if (!inserted_single_step_breakpoint_p ())
> +            gdbarch_software_single_step (gdbarch, get_current_frame ());
> +          record_beneath_to_resume (record_beneath_to_resume_ops,
> +                                    ptid, step, signal);
> +          record_resume_step = 0;
> +        }
> +      else
> +        record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
> +                                  signal);
>      }
>  }
> 
> @@ -1086,6 +1098,7 @@ record_wait (struct target_ops *ops,
>  	  /* This is not a single step.  */
>  	  ptid_t ret;
>  	  CORE_ADDR tmp_pc;
> +          struct gdbarch *gdbarch = get_current_arch ();
> 
>  	  while (1)
>  	    {
> @@ -1108,6 +1121,9 @@ record_wait (struct target_ops *ops,
>  		  tmp_pc = regcache_read_pc (regcache);
>  		  aspace = get_regcache_aspace (regcache);
> 
> +                  if (gdbarch_software_single_step_p (gdbarch))
> +                    remove_single_step_breakpoints ();
> +
>  		  if (target_stopped_by_watchpoint ())
>  		    {
>  		      /* Always interested in watchpoints.  */
> @@ -1133,9 +1149,18 @@ record_wait (struct target_ops *ops,
>  		      if (!do_record_message (regcache, TARGET_SIGNAL_0))
>  			break;
> 
> -		      record_beneath_to_resume (record_beneath_to_resume_ops,
> -						ptid, 1,
> -						TARGET_SIGNAL_0);
> +                      if (gdbarch_software_single_step_p (gdbarch))
> +                        {
> +                          gdbarch_software_single_step (gdbarch,
> +                                                        get_current_frame ());
> +                          record_beneath_to_resume
> (record_beneath_to_resume_ops,
> +                                                    ptid, 0,
> +                                                    TARGET_SIGNAL_0);
> +                        }
> +                      else
> +		        record_beneath_to_resume (record_beneath_to_resume_ops,
> +						  ptid, 1,
> +						  TARGET_SIGNAL_0);
>  		      continue;
>  		    }
>  		}


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-18 19:37 ` Michael Snyder
@ 2009-12-20 13:48   ` Joel Brobecker
  2009-12-23  6:38     ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2009-12-20 13:48 UTC (permalink / raw)
  To: Michael Snyder; +Cc: Hui Zhu, gdb-patches ml, shuchang zhou, paawan oza

Hui:

> >2009-12-18  Hui Zhu  <teawater@gmail.com>
> >
> >	* breakpoint.c (inserted_single_step_breakpoint_p): New
> >	function.
> >	* breakpoint.h (inserted_single_step_breakpoint_p): Extern.
> >	* record.c (record_resume): Add code for software single step.
> >	(record_wait): Ditto.

I understand Michael's answer as approval.  I do not see any problem
with it, but my knowledge of the target stack in the resume/wait area
is pretty sketchy.

Just a stylistic comment on the patch:

> >+/* Check if the breakpoints used for software single stepping
> >inserted or not.  */

Formatting and missing "are".

/* Check if the breakpoints used for software single stepping
   are inserted or not.  */

> >+int
> >+inserted_single_step_breakpoint_p (void)

Can you rename this function to:

        single_step_breakpoints_inserted

The "inserted" already conveys the idea of a condition/predicate,
so the _p is superfluous in this case.

I'm also a little worried about the code adding calls to functions
that in essence return a global variable. For instance, you are
introducing calls to get_current_frame or current_gdbarch().
Ulrich is one of our specialists in this area, whereas I'm not sure,
but I am wondering if we are introducing any latent issue by using
these routines...

-- 
Joel


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-18  8:21 [RFC] Add support of software single step to process record Hui Zhu
  2009-12-18 19:37 ` Michael Snyder
@ 2009-12-22 18:23 ` Tom Tromey
  2009-12-23  3:09   ` Hui Zhu
  1 sibling, 1 reply; 18+ messages in thread
From: Tom Tromey @ 2009-12-22 18:23 UTC (permalink / raw)
  To: Hui Zhu; +Cc: gdb-patches ml, Michael Snyder, shuchang zhou, paawan oza

>>>>> ">" == Hui Zhu <teawater@gmail.com> writes:

>> This patch to make prec support software single step.
>> I just try it with i386.  Shuchang, please help me try it on mips.  :)

>> +int
>> +inserted_single_step_breakpoint_p (void)
>> +{
>> +  if (single_step_breakpoints[0] != NULL
>> +      || single_step_breakpoints[1] != NULL)
>> +    return 1;
>> +
>> +  return 1;
>> +}

This always returns 1.
That seems suspicious to me.

Tom


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-22 18:23 ` Tom Tromey
@ 2009-12-23  3:09   ` Hui Zhu
  0 siblings, 0 replies; 18+ messages in thread
From: Hui Zhu @ 2009-12-23  3:09 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches ml, Michael Snyder, shuchang zhou, paawan oza

Faint.  Shuchang told me this patch cannot be used.  I just tried find
out why it happen.
Thanks a lot.  :)

Best Regards,
Hui

On Wed, Dec 23, 2009 at 02:23, Tom Tromey <tromey@redhat.com> wrote:
>
> >>>>> ">" == Hui Zhu <teawater@gmail.com> writes:
>
> >> This patch to make prec support software single step.
> >> I just try it with i386.  Shuchang, please help me try it on mips.  :)
>
> >> +int
> >> +inserted_single_step_breakpoint_p (void)
> >> +{
> >> +  if (single_step_breakpoints[0] != NULL
> >> +      || single_step_breakpoints[1] != NULL)
> >> +    return 1;
> >> +
> >> +  return 1;
> >> +}
>
> This always returns 1.
> That seems suspicious to me.
>
> Tom


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-20 13:48   ` Joel Brobecker
@ 2009-12-23  6:38     ` Hui Zhu
  2009-12-23  6:52       ` Joel Brobecker
  0 siblings, 1 reply; 18+ messages in thread
From: Hui Zhu @ 2009-12-23  6:38 UTC (permalink / raw)
  To: Joel Brobecker, Michael Snyder, shuchang zhou, paawan oza, Tom Tromey
  Cc: gdb-patches ml

[-- Attachment #1: Type: text/plain, Size: 1782 bytes --]

Hi guys,

I make a new patch according to your comment.

Shuchang, please help me try this patch?

Joel, I remove the current_gdbarch() from this patch, but for
get_current_frame, I cannot find any function that fit for replace it.
 Could you help me with it?

Thanks,
Hui

On Sun, Dec 20, 2009 at 21:30, Joel Brobecker <brobecker@adacore.com> wrote:
> Hui:
>
>> >2009-12-18  Hui Zhu  <teawater@gmail.com>
>> >
>> >     * breakpoint.c (inserted_single_step_breakpoint_p): New
>> >     function.
>> >     * breakpoint.h (inserted_single_step_breakpoint_p): Extern.
>> >     * record.c (record_resume): Add code for software single step.
>> >     (record_wait): Ditto.
>
> I understand Michael's answer as approval.  I do not see any problem
> with it, but my knowledge of the target stack in the resume/wait area
> is pretty sketchy.
>
> Just a stylistic comment on the patch:
>
>> >+/* Check if the breakpoints used for software single stepping
>> >inserted or not.  */
>
> Formatting and missing "are".
>
> /* Check if the breakpoints used for software single stepping
>   are inserted or not.  */
>
>> >+int
>> >+inserted_single_step_breakpoint_p (void)
>
> Can you rename this function to:
>
>        single_step_breakpoints_inserted
>
> The "inserted" already conveys the idea of a condition/predicate,
> so the _p is superfluous in this case.
>
> I'm also a little worried about the code adding calls to functions
> that in essence return a global variable. For instance, you are
> introducing calls to get_current_frame or current_gdbarch().
> Ulrich is one of our specialists in this area, whereas I'm not sure,
> but I am wondering if we are introducing any latent issue by using
> these routines...
>
> --
> Joel
>

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 3450 bytes --]

---
 breakpoint.c |   13 +++++++++++++
 breakpoint.h |    1 +
 record.c     |   33 ++++++++++++++++++++++++++++++---
 3 files changed, 44 insertions(+), 3 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -9624,6 +9624,19 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  if (single_step_breakpoints[0] != NULL
+      || single_step_breakpoints[1] != NULL)
+    return 1;
+
+  return 0;
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -1002,9 +1002,23 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
       record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
                                 signal);
+
+       if (gdbarch_software_single_step_p (gdbarch))
+         {
+           if (!inserted_single_step_breakpoint_p ())
+             gdbarch_software_single_step (gdbarch, get_current_frame ());
+           record_beneath_to_resume (record_beneath_to_resume_ops,
+                                     ptid, step, signal);
+           record_resume_step = 0;
+         }
+       else
+         record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+                                   signal);
     }
 }
 
@@ -1077,6 +1091,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
@@ -1099,6 +1114,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1129,9 +1147,18 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
-		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
-						TARGET_SIGNAL_0);
+                      if (gdbarch_software_single_step_p (gdbarch))
+                        {
+                          gdbarch_software_single_step (gdbarch,
+                                                        get_current_frame ());
+                          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                                    ptid, 0,
+                                                    TARGET_SIGNAL_0);
+                        }
+                      else
+		        record_beneath_to_resume (record_beneath_to_resume_ops,
+						  ptid, 1,
+						  TARGET_SIGNAL_0);
 		      continue;
 		    }
 		}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-23  6:38     ` Hui Zhu
@ 2009-12-23  6:52       ` Joel Brobecker
  2009-12-23  9:24         ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Joel Brobecker @ 2009-12-23  6:52 UTC (permalink / raw)
  To: Hui Zhu
  Cc: Michael Snyder, shuchang zhou, paawan oza, Tom Tromey, gdb-patches ml

> Joel, I remove the current_gdbarch() from this patch, but for
> get_current_frame, I cannot find any function that fit for replace it.
>  Could you help me with it?

Upon further investigation, I believe that this is the only way to do
this.  I don't think you can get the frame from the arguments provided
to "resume". I did a quick research and infrun.c:resume does the same
thing (actually, it's maybe_software_singlestep).

> +  if (single_step_breakpoints[0] != NULL
> +      || single_step_breakpoints[1] != NULL)
> +    return 1;
> +
> +  return 0;

Style nit: You really don't have to fix this, as this is a matter of
style more than correctness, but we usually write the above code as

  return (single_step_breakpoints[0] != NULL
          || single_step_breakpoints[1] != NULL)

This avoids the type of mistake you made.  I tend to like the style
you used when there are several consecutive if conditions that allow
me to return early (a type of soft assert), or to avoid unreasonable
nesting levels.

-- 
Joel


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-23  6:52       ` Joel Brobecker
@ 2009-12-23  9:24         ` Hui Zhu
       [not found]           ` <8d62b6fe0912231751p1202294cw83430e8d53af0951@mail.gmail.com>
  2009-12-24 17:38           ` Pedro Alves
  0 siblings, 2 replies; 18+ messages in thread
From: Hui Zhu @ 2009-12-23  9:24 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Michael Snyder, shuchang zhou, paawan oza, Tom Tromey, gdb-patches ml

[-- Attachment #1: Type: text/plain, Size: 1284 bytes --]

Cool.  I think your idea is more better than I did.  Thanks.

This is the new patch.

Best regards,
Hui

On Wed, Dec 23, 2009 at 14:51, Joel Brobecker <brobecker@adacore.com> wrote:
>> Joel, I remove the current_gdbarch() from this patch, but for
>> get_current_frame, I cannot find any function that fit for replace it.
>>  Could you help me with it?
>
> Upon further investigation, I believe that this is the only way to do
> this.  I don't think you can get the frame from the arguments provided
> to "resume". I did a quick research and infrun.c:resume does the same
> thing (actually, it's maybe_software_singlestep).
>
>> +  if (single_step_breakpoints[0] != NULL
>> +      || single_step_breakpoints[1] != NULL)
>> +    return 1;
>> +
>> +  return 0;
>
> Style nit: You really don't have to fix this, as this is a matter of
> style more than correctness, but we usually write the above code as
>
>  return (single_step_breakpoints[0] != NULL
>          || single_step_breakpoints[1] != NULL)
>
> This avoids the type of mistake you made.  I tend to like the style
> you used when there are several consecutive if conditions that allow
> me to return early (a type of soft assert), or to avoid unreasonable
> nesting levels.
>
> --
> Joel
>

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 3426 bytes --]

---
 breakpoint.c |   10 ++++++++++
 breakpoint.h |    1 +
 record.c     |   33 ++++++++++++++++++++++++++++++---
 3 files changed, 41 insertions(+), 3 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -9624,6 +9624,16 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -1002,9 +1002,23 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
       record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
                                 signal);
+
+       if (gdbarch_software_single_step_p (gdbarch))
+         {
+           if (!inserted_single_step_breakpoint_p ())
+             gdbarch_software_single_step (gdbarch, get_current_frame ());
+           record_beneath_to_resume (record_beneath_to_resume_ops,
+                                     ptid, step, signal);
+           record_resume_step = 0;
+         }
+       else
+         record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+                                   signal);
     }
 }
 
@@ -1077,6 +1091,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
@@ -1099,6 +1114,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1129,9 +1147,18 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
-		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
-						TARGET_SIGNAL_0);
+                      if (gdbarch_software_single_step_p (gdbarch))
+                        {
+                          gdbarch_software_single_step (gdbarch,
+                                                        get_current_frame ());
+                          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                                    ptid, 0,
+                                                    TARGET_SIGNAL_0);
+                        }
+                      else
+		        record_beneath_to_resume (record_beneath_to_resume_ops,
+						  ptid, 1,
+						  TARGET_SIGNAL_0);
 		      continue;
 		    }
 		}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Fwd: [RFC] Add support of software single step to process record
       [not found]           ` <8d62b6fe0912231751p1202294cw83430e8d53af0951@mail.gmail.com>
@ 2009-12-24  1:54             ` shuchang zhou
  0 siblings, 0 replies; 18+ messages in thread
From: shuchang zhou @ 2009-12-24  1:54 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 4600 bytes --]

---------- Forwarded message ----------
From: shuchang zhou <shuchang.zhou@gmail.com>
Date: Thu, Dec 24, 2009 at 9:51 AM
Subject: Re: [RFC] Add support of software single step to process record
To: Hui Zhu <teawater@gmail.com>
Cc: gdb-patches@sourceware.org, msnyder@vmware.com


Still get errors. Current patch is in attachment (I just integrated
the patch you sent me with mine, basically dropping my version of
linux-mips-tdep.c).

(gdb) b main
Breakpoint 1 at 0x400730: file t.c, line 17.
(gdb) set debug infrun 1
(gdb) set debug record 1
(gdb) r
Starting program: /root/tmpd/a.out
infrun: proceed (addr=0xffffffff, signal=0, step=0)
infrun: resume (step=0, signal=0), trap_expected=0
infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
infrun: target_wait (-1, status) =
infrun:   12655 [process 12655],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x2aaba7c0
infrun: BPSTAT_WHAT_CHECK_SHLIBS
infrun: no stepping, continue
infrun: resume (step=1, signal=0), trap_expected=1
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   12655 [process 12655],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x2aaab620
infrun: software single step trap for process 12655
infrun: no stepping, continue
infrun: resume (step=0, signal=0), trap_expected=0
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   12655 [process 12655],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x2aaba7c0
infrun: BPSTAT_WHAT_CHECK_SHLIBS
infrun: no stepping, continue
infrun: resume (step=1, signal=0), trap_expected=1
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   12655 [process 12655],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x2aaabff0
infrun: software single step trap for process 12655
infrun: no stepping, continue
infrun: resume (step=0, signal=0), trap_expected=0
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   12655 [process 12655],
infrun:   status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x400730
infrun: BPSTAT_WHAT_STOP_NOISY
infrun: stop_stepping

Breakpoint 1, main () at t.c:17
17      xyz = 0;      /* break in main */
(gdb) record
Process record: record_open
Process record: record_open
(gdb) n
infrun: clear_proceed_status_thread (process 12655)
infrun: proceed (addr=0xffffffff, signal=144, step=1)
infrun: resume (step=1, signal=0), trap_expected=1
record: mips_record_32 insn = 0x8f828034
main () at t.c:17
17      xyz = 0;      /* break in main */
ptrace: Input/output error.
(gdb)
(gdb) quit
A debugging session is active.

    Inferior 1 [process 12655] will be killed.

Quit anyway? (y or n) y
Process record: record_kill
Process record: record_close

And then it hangs the terminal.

On Wed, Dec 23, 2009 at 5:23 PM, Hui Zhu <teawater@gmail.com> wrote:
>
> Cool.  I think your idea is more better than I did.  Thanks.
>
> This is the new patch.
>
> Best regards,
> Hui
>
> On Wed, Dec 23, 2009 at 14:51, Joel Brobecker <brobecker@adacore.com> wrote:
> >> Joel, I remove the current_gdbarch() from this patch, but for
> >> get_current_frame, I cannot find any function that fit for replace it.
> >>  Could you help me with it?
> >
> > Upon further investigation, I believe that this is the only way to do
> > this.  I don't think you can get the frame from the arguments provided
> > to "resume". I did a quick research and infrun.c:resume does the same
> > thing (actually, it's maybe_software_singlestep).
> >
> >> +  if (single_step_breakpoints[0] != NULL
> >> +      || single_step_breakpoints[1] != NULL)
> >> +    return 1;
> >> +
> >> +  return 0;
> >
> > Style nit: You really don't have to fix this, as this is a matter of
> > style more than correctness, but we usually write the above code as
> >
> >  return (single_step_breakpoints[0] != NULL
> >          || single_step_breakpoints[1] != NULL)
> >
> > This avoids the type of mistake you made.  I tend to like the style
> > you used when there are several consecutive if conditions that allow
> > me to return early (a type of soft assert), or to avoid unreasonable
> > nesting levels.
> >
> > --
> > Joel
> >

[-- Attachment #2: gdb3.diff --]
[-- Type: text/plain, Size: 78398 bytes --]

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
old mode 100644
new mode 100755
index 47a10f6..f5ab6c4
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -9624,6 +9624,16 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 5ebd36c..bb56515 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 69b1f27..fe58d1f 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -337,7 +337,8 @@ mips*-sgi-irix6*)
 mips*-*-linux*)
 	# Target: Linux/MIPS
 	gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
-			corelow.o solib.o solib-svr4.o symfile-mem.o"
+			corelow.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o linux-record.o"
 	gdb_sim=../sim/mips/libsim.a
 	build_gdbserver=yes
 	;;
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
old mode 100644
new mode 100755
index 56401e5..7d7dbc2
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -39,6 +39,10 @@
 #include "mips-linux-tdep.h"
 #include "glibc-tdep.h"
 
+#include "record.h"
+#include "linux-record.h"
+#include <stdint.h>
+
 static struct target_so_ops mips_svr4_so_ops;
 
 /* Figure out where the longjmp will land.
@@ -1133,6 +1137,926 @@ mips_linux_syscall_next_pc (struct frame_info *frame)
   return pc + 4;
 }
 
+static int
+mips_all_but_ip_registers_record (struct regcache *regcache)
+{
+  int i;
+  
+  for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++)
+    if (record_arch_list_add_reg (regcache, i))
+      return -1;
+
+  /* save fsr */
+  if (record_arch_list_add_reg (regcache, MIPS_EMBED_FP0_REGNUM + 32))
+    return -1;
+
+  return 0;
+}
+
+/* mips_canonicalize_syscall maps from the native MIPS Linux set
+   of syscall ids into a canonical set of syscall ids used by
+   process record.  */
+
+static enum gdb_syscall
+mips_canonicalize_syscall (int syscall)
+{
+  switch (syscall) {
+    case mips_sys_O32_exit:
+    case mips_sys_exit:
+    case mips_sys_N32_exit:
+      return gdb_sys_exit;
+    case mips_sys_O32_fork:
+    case mips_sys_fork:
+    case mips_sys_N32_fork:
+      return gdb_sys_fork;
+    case mips_sys_O32_read:
+    case mips_sys_read:
+    case mips_sys_N32_read:
+      return gdb_sys_read;
+    case mips_sys_O32_write:
+    case mips_sys_write:
+    case mips_sys_N32_write:
+      return gdb_sys_write;
+    case mips_sys_O32_open:
+    case mips_sys_open:
+    case mips_sys_N32_open:
+      return gdb_sys_open;
+    case mips_sys_O32_close:
+    case mips_sys_close:
+    case mips_sys_N32_close:
+      return gdb_sys_close;
+    case mips_sys_O32_waitpid:
+      return gdb_sys_waitpid;
+    case mips_sys_O32_creat:
+    case mips_sys_creat:
+    case mips_sys_N32_creat:
+      return gdb_sys_creat;
+    case mips_sys_O32_link:
+    case mips_sys_link:
+    case mips_sys_N32_link:
+      return gdb_sys_link;
+    case mips_sys_O32_unlink:
+    case mips_sys_unlink:
+    case mips_sys_N32_unlink:
+      return gdb_sys_unlink;
+    case mips_sys_O32_execve:
+    case mips_sys_execve:
+    case mips_sys_N32_execve:
+      return gdb_sys_execve;
+    case mips_sys_O32_chdir:
+    case mips_sys_chdir:
+    case mips_sys_N32_chdir:
+      return gdb_sys_chdir;
+    case mips_sys_O32_time:
+    case mips_sys_N32_time:
+      return gdb_sys_time;
+    case mips_sys_O32_mknod:
+    case mips_sys_mknod:
+    case mips_sys_N32_mknod:
+      return gdb_sys_mknod;
+    case mips_sys_O32_chmod:
+    case mips_sys_chmod:
+    case mips_sys_N32_chmod:
+      return gdb_sys_chmod;
+    case mips_sys_O32_stat:
+    case mips_sys_stat:
+    case mips_sys_N32_stat:
+      return gdb_sys_stat;
+    case mips_sys_O32_lseek:
+    case mips_sys_lseek:
+    case mips_sys_N32_lseek:
+      return gdb_sys_lseek;
+    case mips_sys_O32_getpid:
+    case mips_sys_getpid:
+    case mips_sys_N32_getpid:
+      return gdb_sys_getpid;
+    case mips_sys_O32_mount:
+    case mips_sys_mount:
+    case mips_sys_N32_mount:
+      return gdb_sys_mount;
+    case mips_sys_O32_stime:
+      return gdb_sys_stime;
+    case mips_sys_O32_ptrace:
+    case mips_sys_ptrace:
+    case mips_sys_N32_ptrace:
+      return gdb_sys_ptrace;
+    case mips_sys_O32_alarm:
+    case mips_sys_alarm:
+    case mips_sys_N32_alarm:
+      return gdb_sys_alarm;
+    case mips_sys_O32_fstat:
+    case mips_sys_fstat:
+    case mips_sys_N32_fstat:
+      return gdb_sys_fstat;
+    case mips_sys_O32_pause:
+    case mips_sys_pause:
+    case mips_sys_N32_pause:
+      return gdb_sys_pause;
+    case mips_sys_O32_utime:
+    case mips_sys_utime:
+    case mips_sys_N32_utime:
+      return gdb_sys_utime;
+    case mips_sys_O32_access:
+    case mips_sys_access:
+    case mips_sys_N32_access:
+      return gdb_sys_access;
+    case mips_sys_O32_nice:
+      return gdb_sys_nice;
+    case mips_sys_O32_sync:
+    case mips_sys_sync:
+    case mips_sys_N32_sync:
+      return gdb_sys_sync;
+    case mips_sys_O32_kill:
+    case mips_sys_kill:
+    case mips_sys_N32_kill:
+      return gdb_sys_kill;
+    case mips_sys_O32_rename:
+    case mips_sys_rename:
+    case mips_sys_N32_rename:
+      return gdb_sys_rename;
+    case mips_sys_O32_mkdir:
+    case mips_sys_mkdir:
+    case mips_sys_N32_mkdir:
+      return gdb_sys_mkdir;
+    case mips_sys_O32_rmdir:
+    case mips_sys_rmdir:
+    case mips_sys_N32_rmdir:
+      return gdb_sys_rmdir;
+    case mips_sys_O32_dup:
+    case mips_sys_dup:
+    case mips_sys_N32_dup:
+      return gdb_sys_dup;
+    case mips_sys_O32_pipe:
+    case mips_sys_pipe:
+    case mips_sys_N32_pipe:
+      return gdb_sys_pipe;
+    case mips_sys_O32_times:
+    case mips_sys_times:
+    case mips_sys_N32_times:
+      return gdb_sys_times;
+    case mips_sys_O32_brk:
+    case mips_sys_brk:
+    case mips_sys_N32_brk:
+      return gdb_sys_brk;
+    case mips_sys_O32_signal:
+      return gdb_sys_signal;
+    case mips_sys_O32_acct:
+    case mips_sys_acct:
+    case mips_sys_N32_acct:
+      return gdb_sys_acct;
+    case mips_sys_O32_umount:
+      return gdb_sys_umount;
+    case mips_sys_O32_ioctl:
+    case mips_sys_ioctl:
+    case mips_sys_N32_ioctl:
+      return gdb_sys_ioctl;
+    case mips_sys_O32_fcntl:
+    case mips_sys_fcntl:
+    case mips_sys_N32_fcntl:
+      return gdb_sys_fcntl;
+    case mips_sys_O32_setpgid:
+    case mips_sys_setpgid:
+    case mips_sys_N32_setpgid:
+      return gdb_sys_setpgid;
+    case mips_sys_O32_umask:
+    case mips_sys_umask:
+    case mips_sys_N32_umask:
+      return gdb_sys_umask;
+    case mips_sys_O32_chroot:
+    case mips_sys_chroot:
+    case mips_sys_N32_chroot:
+      return gdb_sys_chroot;
+    case mips_sys_O32_ustat:
+    case mips_sys_ustat:
+    case mips_sys_N32_ustat:
+      return gdb_sys_ustat;
+    case mips_sys_O32_dup2:
+    case mips_sys_dup2:
+    case mips_sys_N32_dup2:
+      return gdb_sys_dup2;
+    case mips_sys_O32_getppid:
+    case mips_sys_getppid:
+    case mips_sys_N32_getppid:
+      return gdb_sys_getppid;
+    case mips_sys_O32_getpgrp:
+    case mips_sys_getpgrp:
+    case mips_sys_N32_getpgrp:
+      return gdb_sys_getpgrp;
+    case mips_sys_O32_setsid:
+    case mips_sys_setsid:
+    case mips_sys_N32_setsid:
+      return gdb_sys_setsid;
+    case mips_sys_O32_sigaction:
+      return gdb_sys_sigaction;
+    case mips_sys_O32_sgetmask:
+      return gdb_sys_sgetmask;
+    case mips_sys_O32_ssetmask:
+      return gdb_sys_ssetmask;
+    case mips_sys_O32_sigsuspend:
+      return gdb_sys_sigsuspend;
+    case mips_sys_O32_sigpending:
+      return gdb_sys_sigpending;
+    case mips_sys_O32_sethostname:
+    case mips_sys_sethostname:
+    case mips_sys_N32_sethostname:
+      return gdb_sys_sethostname;
+    case mips_sys_O32_setrlimit:
+    case mips_sys_setrlimit:
+    case mips_sys_N32_setrlimit:
+      return gdb_sys_setrlimit;
+    case mips_sys_O32_getrusage:
+    case mips_sys_getrusage:
+    case mips_sys_N32_getrusage:
+      return gdb_sys_getrusage;
+    case mips_sys_O32_gettimeofday:
+    case mips_sys_gettimeofday:
+    case mips_sys_N32_gettimeofday:
+      return gdb_sys_gettimeofday;
+    case mips_sys_O32_settimeofday:
+    case mips_sys_settimeofday:
+    case mips_sys_N32_settimeofday:
+      return gdb_sys_settimeofday;
+    case mips_sys_O32_symlink:
+    case mips_sys_symlink:
+    case mips_sys_N32_symlink:
+      return gdb_sys_symlink;
+    case mips_sys_O32_lstat:
+    case mips_sys_lstat:
+    case mips_sys_N32_lstat:
+      return gdb_sys_lstat;
+    case mips_sys_O32_readlink:
+    case mips_sys_readlink:
+    case mips_sys_N32_readlink:
+      return gdb_sys_readlink;
+    case mips_sys_O32_uselib:
+      return gdb_sys_uselib;
+    case mips_sys_O32_swapon:
+    case mips_sys_swapon:
+    case mips_sys_N32_swapon:
+      return gdb_sys_swapon;
+    case mips_sys_O32_reboot:
+    case mips_sys_reboot:
+    case mips_sys_N32_reboot:
+      return gdb_sys_reboot;
+    case mips_sys_O32_munmap:
+    case mips_sys_munmap:
+    case mips_sys_N32_munmap:
+      return gdb_sys_munmap;
+    case mips_sys_O32_truncate:
+    case mips_sys_truncate:
+    case mips_sys_N32_truncate:
+      return gdb_sys_truncate;
+    case mips_sys_O32_ftruncate:
+    case mips_sys_ftruncate:
+    case mips_sys_N32_ftruncate:
+      return gdb_sys_ftruncate;
+    case mips_sys_O32_fchmod:
+    case mips_sys_fchmod:
+    case mips_sys_N32_fchmod:
+      return gdb_sys_fchmod;
+    case mips_sys_O32_getpriority:
+    case mips_sys_getpriority:
+    case mips_sys_N32_getpriority:
+      return gdb_sys_getpriority;
+    case mips_sys_O32_setpriority:
+    case mips_sys_setpriority:
+    case mips_sys_N32_setpriority:
+      return gdb_sys_setpriority;
+    case mips_sys_O32_statfs:
+    case mips_sys_statfs:
+    case mips_sys_N32_statfs:
+      return gdb_sys_statfs;
+    case mips_sys_O32_fstatfs:
+    case mips_sys_fstatfs:
+    case mips_sys_N32_fstatfs:
+      return gdb_sys_fstatfs;
+    case mips_sys_O32_ioperm:
+      return gdb_sys_ioperm;
+    case mips_sys_O32_socketcall:
+      return gdb_sys_socketcall;
+    case mips_sys_O32_syslog:
+    case mips_sys_syslog:
+    case mips_sys_N32_syslog:
+      return gdb_sys_syslog;
+    case mips_sys_O32_setitimer:
+    case mips_sys_setitimer:
+    case mips_sys_N32_setitimer:
+      return gdb_sys_setitimer;
+    case mips_sys_O32_getitimer:
+    case mips_sys_getitimer:
+    case mips_sys_N32_getitimer:
+      return gdb_sys_getitimer;
+    case mips_sys_O32_uname:
+    case mips_sys_uname:
+    case mips_sys_N32_uname:
+      return gdb_sys_uname;
+    case mips_sys_O32_iopl:
+      return gdb_sys_iopl;
+    case mips_sys_O32_vhangup:
+    case mips_sys_vhangup:
+    case mips_sys_N32_vhangup:
+      return gdb_sys_vhangup;
+    case mips_sys_O32_wait4:
+    case mips_sys_wait4:
+    case mips_sys_N32_wait4:
+      return gdb_sys_wait4;
+    case mips_sys_O32_swapoff:
+    case mips_sys_swapoff:
+    case mips_sys_N32_swapoff:
+      return gdb_sys_swapoff;
+    case mips_sys_O32_sysinfo:
+    case mips_sys_sysinfo:
+    case mips_sys_N32_sysinfo:
+      return gdb_sys_sysinfo;
+    case mips_sys_O32_ipc:
+      return gdb_sys_ipc;
+    case mips_sys_O32_fsync:
+    case mips_sys_fsync:
+    case mips_sys_N32_fsync:
+      return gdb_sys_fsync;
+    case mips_sys_O32_sigreturn:
+      return gdb_sys_sigreturn;
+    case mips_sys_O32_clone:
+    case mips_sys_clone:
+    case mips_sys_N32_clone:
+      return gdb_sys_clone;
+    case mips_sys_O32_setdomainname:
+    case mips_sys_setdomainname:
+    case mips_sys_N32_setdomainname:
+      return gdb_sys_setdomainname;
+    case mips_sys_O32_modify_ldt:
+      return gdb_sys_modify_ldt;
+    case mips_sys_O32_adjtimex:
+    case mips_sys_adjtimex:
+    case mips_sys_N32_adjtimex:
+      return gdb_sys_adjtimex;
+    case mips_sys_O32_mprotect:
+    case mips_sys_mprotect:
+    case mips_sys_N32_mprotect:
+      return gdb_sys_mprotect;
+    case mips_sys_O32_sigprocmask:
+      return gdb_sys_sigprocmask;
+    case mips_sys_O32_init_module:
+    case mips_sys_init_module:
+    case mips_sys_N32_init_module:
+      return gdb_sys_init_module;
+    case mips_sys_O32_delete_module:
+    case mips_sys_delete_module:
+    case mips_sys_N32_delete_module:
+      return gdb_sys_delete_module;
+    case mips_sys_O32_quotactl:
+    case mips_sys_quotactl:
+    case mips_sys_N32_quotactl:
+      return gdb_sys_quotactl;
+    case mips_sys_O32_getpgid:
+    case mips_sys_getpgid:
+    case mips_sys_N32_getpgid:
+      return gdb_sys_getpgid;
+    case mips_sys_O32_fchdir:
+    case mips_sys_fchdir:
+    case mips_sys_N32_fchdir:
+      return gdb_sys_fchdir;
+    case mips_sys_O32_bdflush:
+      return gdb_sys_bdflush;
+    case mips_sys_O32_sysfs:
+    case mips_sys_sysfs:
+    case mips_sys_N32_sysfs:
+      return gdb_sys_sysfs;
+    case mips_sys_O32_personality:
+    case mips_sys_personality:
+    case mips_sys_N32_personality:
+      return gdb_sys_personality;
+    case mips_sys_O32_getdents:
+    case mips_sys_getdents:
+    case mips_sys_N32_getdents:
+      return gdb_sys_getdents;
+    case mips_sys_O32_flock:
+    case mips_sys_flock:
+    case mips_sys_N32_flock:
+      return gdb_sys_flock;
+    case mips_sys_O32_msync:
+    case mips_sys_msync:
+    case mips_sys_N32_msync:
+      return gdb_sys_msync;
+    case mips_sys_O32_readv:
+    case mips_sys_readv:
+    case mips_sys_N32_readv:
+      return gdb_sys_readv;
+    case mips_sys_O32_writev:
+    case mips_sys_writev:
+    case mips_sys_N32_writev:
+      return gdb_sys_writev;
+    case mips_sys_O32_getsid:
+    case mips_sys_getsid:
+    case mips_sys_N32_getsid:
+      return gdb_sys_getsid;
+    case mips_sys_O32_fdatasync:
+    case mips_sys_fdatasync:
+    case mips_sys_N32_fdatasync:
+      return gdb_sys_fdatasync;
+    case mips_sys_O32_mlock:
+    case mips_sys_mlock:
+    case mips_sys_N32_mlock:
+      return gdb_sys_mlock;
+    case mips_sys_O32_munlock:
+    case mips_sys_munlock:
+    case mips_sys_N32_munlock:
+      return gdb_sys_munlock;
+    case mips_sys_O32_mlockall:
+    case mips_sys_mlockall:
+    case mips_sys_N32_mlockall:
+      return gdb_sys_mlockall;
+    case mips_sys_O32_munlockall:
+    case mips_sys_munlockall:
+    case mips_sys_N32_munlockall:
+      return gdb_sys_munlockall;
+    case mips_sys_O32_sched_setparam:
+    case mips_sys_sched_setparam:
+    case mips_sys_N32_sched_setparam:
+      return gdb_sys_sched_setparam;
+    case mips_sys_O32_sched_getparam:
+    case mips_sys_sched_getparam:
+    case mips_sys_N32_sched_getparam:
+      return gdb_sys_sched_getparam;
+    case mips_sys_O32_sched_setscheduler:
+    case mips_sys_sched_setscheduler:
+    case mips_sys_N32_sched_setscheduler:
+      return gdb_sys_sched_setscheduler;
+    case mips_sys_O32_sched_getscheduler:
+    case mips_sys_sched_getscheduler:
+    case mips_sys_N32_sched_getscheduler:
+      return gdb_sys_sched_getscheduler;
+    case mips_sys_O32_sched_yield:
+    case mips_sys_sched_yield:
+    case mips_sys_N32_sched_yield:
+      return gdb_sys_sched_yield;
+    case mips_sys_O32_sched_get_priority_max:
+    case mips_sys_sched_get_priority_max:
+    case mips_sys_N32_sched_get_priority_max:
+      return gdb_sys_sched_get_priority_max;
+    case mips_sys_O32_sched_get_priority_min:
+    case mips_sys_sched_get_priority_min:
+    case mips_sys_N32_sched_get_priority_min:
+      return gdb_sys_sched_get_priority_min;
+    case mips_sys_O32_sched_rr_get_interval:
+    case mips_sys_sched_rr_get_interval:
+    case mips_sys_N32_sched_rr_get_interval:
+      return gdb_sys_sched_rr_get_interval;
+    case mips_sys_O32_nanosleep:
+    case mips_sys_nanosleep:
+    case mips_sys_N32_nanosleep:
+      return gdb_sys_nanosleep;
+    case mips_sys_O32_mremap:
+    case mips_sys_mremap:
+    case mips_sys_N32_mremap:
+      return gdb_sys_mremap;
+    case mips_sys_O32_vm86:
+      return gdb_sys_vm86;
+    case mips_sys_O32_poll:
+    case mips_sys_poll:
+    case mips_sys_N32_poll:
+      return gdb_sys_poll;
+    case mips_sys_O32_nfsservctl:
+    case mips_sys_nfsservctl:
+    case mips_sys_N32_nfsservctl:
+      return gdb_sys_nfsservctl;
+    case mips_sys_O32_prctl:
+    case mips_sys_prctl:
+    case mips_sys_N32_prctl:
+      return gdb_sys_prctl;
+    case mips_sys_O32_rt_sigreturn:
+    case mips_sys_rt_sigreturn:
+    case mips_sys_N32_rt_sigreturn:
+      return gdb_sys_rt_sigreturn;
+    case mips_sys_O32_rt_sigaction:
+    case mips_sys_rt_sigaction:
+    case mips_sys_N32_rt_sigaction:
+      return gdb_sys_rt_sigaction;
+    case mips_sys_O32_rt_sigprocmask:
+    case mips_sys_rt_sigprocmask:
+    case mips_sys_N32_rt_sigprocmask:
+      return gdb_sys_rt_sigprocmask;
+    case mips_sys_O32_rt_sigpending:
+    case mips_sys_rt_sigpending:
+    case mips_sys_N32_rt_sigpending:
+      return gdb_sys_rt_sigpending;
+    case mips_sys_O32_rt_sigtimedwait:
+    case mips_sys_rt_sigtimedwait:
+    case mips_sys_N32_rt_sigtimedwait:
+      return gdb_sys_rt_sigtimedwait;
+    case mips_sys_O32_rt_sigqueueinfo:
+    case mips_sys_rt_sigqueueinfo:
+    case mips_sys_N32_rt_sigqueueinfo:
+      return gdb_sys_rt_sigqueueinfo;
+    case mips_sys_O32_rt_sigsuspend:
+    case mips_sys_rt_sigsuspend:
+    case mips_sys_N32_rt_sigsuspend:
+      return gdb_sys_rt_sigsuspend;
+    case mips_sys_O32_getcwd:
+    case mips_sys_getcwd:
+    case mips_sys_N32_getcwd:
+      return gdb_sys_getcwd;
+    case mips_sys_O32_capget:
+    case mips_sys_capget:
+    case mips_sys_N32_capget:
+      return gdb_sys_capget;
+    case mips_sys_O32_capset:
+    case mips_sys_capset:
+    case mips_sys_N32_capset:
+      return gdb_sys_capset;
+    case mips_sys_O32_sigaltstack:
+    case mips_sys_sigaltstack:
+    case mips_sys_N32_sigaltstack:
+      return gdb_sys_sigaltstack;
+    case mips_sys_O32_sendfile:
+    case mips_sys_sendfile:
+    case mips_sys_N32_sendfile:
+      return gdb_sys_sendfile;
+    case mips_sys_O32_getrlimit:
+    case mips_sys_getrlimit:
+    case mips_sys_N32_getrlimit:
+      return gdb_sys_getrlimit;
+    case mips_sys_O32_mmap2:
+      return gdb_sys_mmap2;
+    case mips_sys_O32_truncate64:
+      return gdb_sys_truncate64;
+    case mips_sys_O32_ftruncate64:
+      return gdb_sys_ftruncate64;
+    case mips_sys_O32_stat64:
+      return gdb_sys_stat64;
+    case mips_sys_O32_lstat64:
+      return gdb_sys_lstat64;
+    case mips_sys_O32_fstat64:
+      return gdb_sys_fstat64;
+    case mips_sys_O32_lchown:
+    case mips_sys_lchown:
+    case mips_sys_N32_lchown:
+      return gdb_sys_lchown;
+    case mips_sys_O32_getuid:
+    case mips_sys_getuid:
+    case mips_sys_N32_getuid:
+      return gdb_sys_getuid;
+    case mips_sys_O32_getgid:
+    case mips_sys_getgid:
+    case mips_sys_N32_getgid:
+      return gdb_sys_getgid;
+    case mips_sys_O32_geteuid:
+    case mips_sys_geteuid:
+    case mips_sys_N32_geteuid:
+      return gdb_sys_geteuid;
+    case mips_sys_O32_getegid:
+    case mips_sys_getegid:
+    case mips_sys_N32_getegid:
+      return gdb_sys_getegid;
+    case mips_sys_O32_setreuid:
+    case mips_sys_setreuid:
+    case mips_sys_N32_setreuid:
+      return gdb_sys_setreuid;
+    case mips_sys_O32_setregid:
+    case mips_sys_setregid:
+    case mips_sys_N32_setregid:
+      return gdb_sys_setregid;
+    case mips_sys_O32_getgroups:
+    case mips_sys_getgroups:
+    case mips_sys_N32_getgroups:
+      return gdb_sys_getgroups;
+    case mips_sys_O32_setgroups:
+    case mips_sys_setgroups:
+    case mips_sys_N32_setgroups:
+      return gdb_sys_setgroups;
+    case mips_sys_O32_fchown:
+    case mips_sys_fchown:
+    case mips_sys_N32_fchown:
+      return gdb_sys_fchown;
+    case mips_sys_O32_setresuid:
+    case mips_sys_setresuid:
+    case mips_sys_N32_setresuid:
+      return gdb_sys_setresuid;
+    case mips_sys_O32_getresuid:
+    case mips_sys_getresuid:
+    case mips_sys_N32_getresuid:
+      return gdb_sys_getresuid;
+    case mips_sys_O32_setresgid:
+    case mips_sys_setresgid:
+    case mips_sys_N32_setresgid:
+      return gdb_sys_setresgid;
+    case mips_sys_O32_getresgid:
+    case mips_sys_getresgid:
+    case mips_sys_N32_getresgid:
+      return gdb_sys_getresgid;
+    case mips_sys_O32_chown:
+    case mips_sys_chown:
+    case mips_sys_N32_chown:
+      return gdb_sys_chown;
+    case mips_sys_O32_setuid:
+    case mips_sys_setuid:
+    case mips_sys_N32_setuid:
+      return gdb_sys_setuid;
+    case mips_sys_O32_setgid:
+    case mips_sys_setgid:
+    case mips_sys_N32_setgid:
+      return gdb_sys_setgid;
+    case mips_sys_O32_setfsuid:
+    case mips_sys_setfsuid:
+    case mips_sys_N32_setfsuid:
+      return gdb_sys_setfsuid;
+    case mips_sys_O32_setfsgid:
+    case mips_sys_setfsgid:
+    case mips_sys_N32_setfsgid:
+      return gdb_sys_setfsgid;
+    case mips_sys_pivot_root:
+    case mips_sys_N32_pivot_root:
+      return gdb_sys_pivot_root;
+    case mips_sys_O32_mincore:
+    case mips_sys_mincore:
+    case mips_sys_N32_mincore:
+      return gdb_sys_mincore;
+    case mips_sys_O32_madvise:
+    case mips_sys_madvise:
+    case mips_sys_N32_madvise:
+      return gdb_sys_madvise;
+    case mips_sys_O32_getdents64:
+      return gdb_sys_getdents64;
+    case mips_sys_O32_fcntl64:
+    case mips_sys_N32_fcntl64:
+      return gdb_sys_fcntl64;
+    case mips_sys_O32_gettid:
+    case mips_sys_gettid:
+    case mips_sys_N32_gettid:
+      return gdb_sys_gettid;
+    case mips_sys_O32_readahead:
+    case mips_sys_readahead:
+    case mips_sys_N32_readahead:
+      return gdb_sys_readahead;
+    case mips_sys_O32_setxattr:
+    case mips_sys_setxattr:
+    case mips_sys_N32_setxattr:
+      return gdb_sys_setxattr;
+    case mips_sys_O32_lsetxattr:
+    case mips_sys_lsetxattr:
+    case mips_sys_N32_lsetxattr:
+      return gdb_sys_lsetxattr;
+    case mips_sys_O32_fsetxattr:
+    case mips_sys_fsetxattr:
+    case mips_sys_N32_fsetxattr:
+      return gdb_sys_fsetxattr;
+    case mips_sys_O32_getxattr:
+    case mips_sys_getxattr:
+    case mips_sys_N32_getxattr:
+      return gdb_sys_getxattr;
+    case mips_sys_O32_lgetxattr:
+    case mips_sys_lgetxattr:
+    case mips_sys_N32_lgetxattr:
+      return gdb_sys_lgetxattr;
+    case mips_sys_O32_fgetxattr:
+    case mips_sys_fgetxattr:
+    case mips_sys_N32_fgetxattr:
+      return gdb_sys_fgetxattr;
+    case mips_sys_O32_listxattr:
+    case mips_sys_listxattr:
+    case mips_sys_N32_listxattr:
+      return gdb_sys_listxattr;
+    case mips_sys_O32_llistxattr:
+    case mips_sys_llistxattr:
+    case mips_sys_N32_llistxattr:
+      return gdb_sys_llistxattr;
+    case mips_sys_O32_flistxattr:
+    case mips_sys_flistxattr:
+    case mips_sys_N32_flistxattr:
+      return gdb_sys_flistxattr;
+    case mips_sys_O32_removexattr:
+    case mips_sys_removexattr:
+    case mips_sys_N32_removexattr:
+      return gdb_sys_removexattr;
+    case mips_sys_O32_lremovexattr:
+    case mips_sys_lremovexattr:
+    case mips_sys_N32_lremovexattr:
+      return gdb_sys_lremovexattr;
+    case mips_sys_O32_fremovexattr:
+    case mips_sys_fremovexattr:
+    case mips_sys_N32_fremovexattr:
+      return gdb_sys_fremovexattr;
+    case mips_sys_O32_tkill:
+    case mips_sys_tkill:
+    case mips_sys_N32_tkill:
+      return gdb_sys_tkill;
+    case mips_sys_O32_sendfile64:
+    case mips_sys_N32_sendfile64:
+      return gdb_sys_sendfile64;
+    case mips_sys_O32_futex:
+    case mips_sys_futex:
+    case mips_sys_N32_futex:
+      return gdb_sys_futex;
+    case mips_sys_O32_sched_setaffinity:
+    case mips_sys_sched_setaffinity:
+    case mips_sys_N32_sched_setaffinity:
+      return gdb_sys_sched_setaffinity;
+    case mips_sys_O32_sched_getaffinity:
+    case mips_sys_sched_getaffinity:
+    case mips_sys_N32_sched_getaffinity:
+      return gdb_sys_sched_getaffinity;
+    case mips_sys_O32_socket:
+    case mips_sys_socket:
+    case mips_sys_N32_socket:
+      return gdb_sys_socket;
+    case mips_sys_O32_connect:
+    case mips_sys_connect:
+    case mips_sys_N32_connect:
+      return gdb_sys_connect;
+    case mips_sys_O32_accept:
+    case mips_sys_accept:
+    case mips_sys_N32_accept:
+      return gdb_sys_accept;
+    case mips_sys_O32_sendto:
+    case mips_sys_sendto:
+    case mips_sys_N32_sendto:
+      return gdb_sys_sendto;
+    case mips_sys_O32_recvfrom:
+    case mips_sys_recvfrom:
+    case mips_sys_N32_recvfrom:
+      return gdb_sys_recvfrom;
+    case mips_sys_O32_sendmsg:
+    case mips_sys_sendmsg:
+    case mips_sys_N32_sendmsg:
+      return gdb_sys_sendmsg;
+    case mips_sys_O32_recvmsg:
+    case mips_sys_recvmsg:
+    case mips_sys_N32_recvmsg:
+      return gdb_sys_recvmsg;
+    case mips_sys_O32_shutdown:
+    case mips_sys_shutdown:
+    case mips_sys_N32_shutdown:
+      return gdb_sys_shutdown;
+    case mips_sys_O32_bind:
+    case mips_sys_bind:
+    case mips_sys_N32_bind:
+      return gdb_sys_bind;
+    case mips_sys_O32_listen:
+    case mips_sys_listen:
+    case mips_sys_N32_listen:
+      return gdb_sys_listen;
+    case mips_sys_O32_getsockname:
+    case mips_sys_getsockname:
+    case mips_sys_N32_getsockname:
+      return gdb_sys_getsockname;
+    case mips_sys_O32_getpeername:
+    case mips_sys_getpeername:
+    case mips_sys_N32_getpeername:
+      return gdb_sys_getpeername;
+    case mips_sys_O32_socketpair:
+    case mips_sys_socketpair:
+    case mips_sys_N32_socketpair:
+      return gdb_sys_socketpair;
+    case mips_sys_O32_setsockopt:
+    case mips_sys_setsockopt:
+    case mips_sys_N32_setsockopt:
+      return gdb_sys_setsockopt;
+    case mips_sys_O32_getsockopt:
+    case mips_sys_getsockopt:
+    case mips_sys_N32_getsockopt:
+      return gdb_sys_getsockopt;
+    case mips_sys_O32_recv:
+      return gdb_sys_recv;
+    case mips_sys_shmget:
+    case mips_sys_N32_shmget:
+      return gdb_sys_shmget;
+    case mips_sys_shmat:
+    case mips_sys_N32_shmat:
+      return gdb_sys_shmat;
+    case mips_sys_shmctl:
+    case mips_sys_N32_shmctl:
+      return gdb_sys_shmctl;
+    case mips_sys_semget:
+    case mips_sys_N32_semget:
+      return gdb_sys_semget;
+    case mips_sys_semop:
+    case mips_sys_N32_semop:
+      return gdb_sys_semop;
+    case mips_sys_semctl:
+    case mips_sys_N32_semctl:
+      return gdb_sys_semctl;
+    case mips_sys_shmdt:
+    case mips_sys_N32_shmdt:
+      return gdb_sys_shmdt;
+    case mips_sys_msgget:
+    case mips_sys_N32_msgget:
+      return gdb_sys_msgget;
+    case mips_sys_msgsnd:
+    case mips_sys_N32_msgsnd:
+      return gdb_sys_msgsnd;
+    case mips_sys_msgrcv:
+    case mips_sys_N32_msgrcv:
+      return gdb_sys_msgrcv;
+    case mips_sys_msgctl:
+    case mips_sys_N32_msgctl:
+      return gdb_sys_msgctl;
+    case mips_sys_semtimedop:
+    case mips_sys_N32_semtimedop:
+      return gdb_sys_semtimedop;
+
+  default:
+    return -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.  */
+
+static struct linux_record_tdep mips_linux_record_tdep;
+
+static int
+mips_linux_syscall_record (struct regcache *regcache)
+{
+  int ret;
+  LONGEST syscall_native;
+  enum gdb_syscall syscall_gdb;
+
+  regcache_raw_read_signed (regcache, MIPS_V0_REGNUM, &syscall_native);
+
+  syscall_gdb = mips_canonicalize_syscall (syscall_native);
+
+  if (syscall_gdb < 0)
+  {
+    printf_unfiltered (_("Process record and replay target doesn't "
+        "support syscall number %s\n"), 
+        plongest (syscall_native));
+    return -1;
+  }
+
+  if (syscall_gdb == gdb_sys_sigreturn
+      || syscall_gdb == gdb_sys_rt_sigreturn)
+  {
+    if (mips_all_but_ip_registers_record (regcache))
+      return -1;
+    return 0;
+  }
+
+  ret = record_linux_system_call (syscall_gdb, regcache,
+                                  &mips_linux_record_tdep);
+  if (ret)
+    return ret;
+
+  /* Record the return value of the system call.  */
+  if (record_arch_list_add_reg (regcache, MIPS_V0_REGNUM))
+    return -1;
+
+  return 0;
+}
+
+#define MIPS_LINUX_xstate 270
+#define MIPS_LINUX_frame_size 732
+
+int
+mips_linux_record_signal (struct gdbarch *gdbarch,
+                              struct regcache *regcache,
+                              enum target_signal signal)
+{
+  ULONGEST sp;
+
+  if (mips_all_but_ip_registers_record (regcache))
+    return -1;
+
+  if (record_arch_list_add_reg (regcache, MIPS_SP_REGNUM))
+    return -1;
+
+  /* Record the change in the stack.  */
+  regcache_raw_read_unsigned (regcache, MIPS_SP_REGNUM, &sp);
+  /* This is for xstate.
+  sp -= sizeof (struct _fpstate);  */
+  sp -= MIPS_LINUX_xstate;
+  /* This is for frame_size.
+  sp -= sizeof (struct rt_sigframe);  */
+  sp -= MIPS_LINUX_frame_size;
+  if (record_arch_list_add_mem (sp,
+      MIPS_LINUX_xstate + MIPS_LINUX_frame_size))
+    return -1;
+
+  if (record_arch_list_add_end ())
+    return -1;
+
+  return 0;
+}
+
+int
+mips_syscall (enum mips_abi abi, enum mips_syscall_offset offset)
+{
+  switch (abi) {
+    case MIPS_ABI_O32:
+      return offset + 4000;
+    case MIPS_ABI_N32:
+      return offset + 6000;
+    case MIPS_ABI_N64:
+      return offset + 5000;
+    default:
+      break;
+  }
+  gdb_assert (0);
+  return -1;
+}
+
 /* Initialize one of the GNU/Linux OS ABIs.  */
 
 static void
@@ -1143,6 +2067,170 @@ mips_linux_init_abi (struct gdbarch_info info,
   enum mips_abi abi = mips_abi (gdbarch);
   struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
 
+  set_gdbarch_process_record (gdbarch, mips_record);
+  set_gdbarch_process_record_signal (gdbarch, mips_linux_record_signal);
+
+  /* Initialize the mips_linux_record_tdep.  */
+  /* These values are the size of the type that will be used in a system
+  call.  They are obtained from Linux Kernel source.  */
+  mips_linux_record_tdep.size_pointer
+      = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+  mips_linux_record_tdep.size__old_kernel_stat = 32;
+  mips_linux_record_tdep.size_tms = 16;
+  mips_linux_record_tdep.size_loff_t = 8;
+  mips_linux_record_tdep.size_flock = 16;
+  mips_linux_record_tdep.size_oldold_utsname = 45;
+  mips_linux_record_tdep.size_ustat = 20;
+  mips_linux_record_tdep.size_old_sigaction = 140;
+  mips_linux_record_tdep.size_old_sigset_t = 128;
+  mips_linux_record_tdep.size_rlimit = 8;
+  mips_linux_record_tdep.size_rusage = 72;
+  mips_linux_record_tdep.size_timeval = 8;
+  mips_linux_record_tdep.size_timezone = 8;
+  mips_linux_record_tdep.size_old_gid_t = 2;
+  mips_linux_record_tdep.size_old_uid_t = 2;
+  mips_linux_record_tdep.size_fd_set = 128;
+  mips_linux_record_tdep.size_dirent = 268;
+  mips_linux_record_tdep.size_dirent64 = 276;
+  mips_linux_record_tdep.size_statfs = 64;
+  mips_linux_record_tdep.size_statfs64 = 84;
+  mips_linux_record_tdep.size_sockaddr = 16;
+  mips_linux_record_tdep.size_int
+      = gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT;
+  mips_linux_record_tdep.size_long
+      = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+  mips_linux_record_tdep.size_ulong
+      = gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT;
+  mips_linux_record_tdep.size_msghdr = 28;
+  mips_linux_record_tdep.size_itimerval = 16;
+  mips_linux_record_tdep.size_stat = 88;
+  mips_linux_record_tdep.size_old_utsname = 325;
+  mips_linux_record_tdep.size_sysinfo = 64;
+  mips_linux_record_tdep.size_msqid_ds = 88;
+  mips_linux_record_tdep.size_shmid_ds = 84;
+  mips_linux_record_tdep.size_new_utsname = 390;
+  mips_linux_record_tdep.size_timex = 128;
+  mips_linux_record_tdep.size_mem_dqinfo = 24;
+  mips_linux_record_tdep.size_if_dqblk = 68;
+  mips_linux_record_tdep.size_fs_quota_stat = 68;
+  mips_linux_record_tdep.size_timespec = 8;
+  mips_linux_record_tdep.size_pollfd = 8;
+  mips_linux_record_tdep.size_NFS_FHSIZE = 32;
+  mips_linux_record_tdep.size_knfsd_fh = 132;
+  mips_linux_record_tdep.size_TASK_COMM_LEN = 16;
+  mips_linux_record_tdep.size_sigaction = 140;
+  mips_linux_record_tdep.size_sigset_t = 8;
+  mips_linux_record_tdep.size_siginfo_t = 128;
+  mips_linux_record_tdep.size_cap_user_data_t = 12;
+  mips_linux_record_tdep.size_stack_t = 12;
+  mips_linux_record_tdep.size_off_t = mips_linux_record_tdep.size_long;
+  mips_linux_record_tdep.size_stat64 = 96;
+  mips_linux_record_tdep.size_gid_t = 2;
+  mips_linux_record_tdep.size_uid_t = 2;
+  mips_linux_record_tdep.size_PAGE_SIZE = 4096;
+  mips_linux_record_tdep.size_flock64 = 24;
+  mips_linux_record_tdep.size_user_desc = 16;
+  mips_linux_record_tdep.size_io_event = 32;
+  mips_linux_record_tdep.size_iocb = 64;
+  mips_linux_record_tdep.size_epoll_event = 12;
+  mips_linux_record_tdep.size_itimerspec
+      = mips_linux_record_tdep.size_timespec * 2;
+  mips_linux_record_tdep.size_mq_attr = 32;
+  mips_linux_record_tdep.size_siginfo = 128;
+  mips_linux_record_tdep.size_termios = 36;
+  mips_linux_record_tdep.size_termios2 = 44;
+  mips_linux_record_tdep.size_pid_t = 4;
+  mips_linux_record_tdep.size_winsize = 8;
+  mips_linux_record_tdep.size_serial_struct = 60;
+  mips_linux_record_tdep.size_serial_icounter_struct = 80;
+  mips_linux_record_tdep.size_hayes_esp_config = 12;
+  mips_linux_record_tdep.size_size_t = 4;
+  mips_linux_record_tdep.size_iovec = 8;
+
+  /* These values are the second argument of system call "sys_ioctl".
+  They are obtained from Linux Kernel source.  */
+  mips_linux_record_tdep.ioctl_TCGETS = 0x5401;
+  mips_linux_record_tdep.ioctl_TCSETS = 0x5402;
+  mips_linux_record_tdep.ioctl_TCSETSW = 0x5403;
+  mips_linux_record_tdep.ioctl_TCSETSF = 0x5404;
+  mips_linux_record_tdep.ioctl_TCGETA = 0x5405;
+  mips_linux_record_tdep.ioctl_TCSETA = 0x5406;
+  mips_linux_record_tdep.ioctl_TCSETAW = 0x5407;
+  mips_linux_record_tdep.ioctl_TCSETAF = 0x5408;
+  mips_linux_record_tdep.ioctl_TCSBRK = 0x5409;
+  mips_linux_record_tdep.ioctl_TCXONC = 0x540A;
+  mips_linux_record_tdep.ioctl_TCFLSH = 0x540B;
+  mips_linux_record_tdep.ioctl_TIOCEXCL = 0x540C;
+  mips_linux_record_tdep.ioctl_TIOCNXCL = 0x540D;
+  mips_linux_record_tdep.ioctl_TIOCSCTTY = 0x540E;
+  mips_linux_record_tdep.ioctl_TIOCGPGRP = 0x540F;
+  mips_linux_record_tdep.ioctl_TIOCSPGRP = 0x5410;
+  mips_linux_record_tdep.ioctl_TIOCOUTQ = 0x5411;
+  mips_linux_record_tdep.ioctl_TIOCSTI = 0x5412;
+  mips_linux_record_tdep.ioctl_TIOCGWINSZ = 0x5413;
+  mips_linux_record_tdep.ioctl_TIOCSWINSZ = 0x5414;
+  mips_linux_record_tdep.ioctl_TIOCMGET = 0x5415;
+  mips_linux_record_tdep.ioctl_TIOCMBIS = 0x5416;
+  mips_linux_record_tdep.ioctl_TIOCMBIC = 0x5417;
+  mips_linux_record_tdep.ioctl_TIOCMSET = 0x5418;
+  mips_linux_record_tdep.ioctl_TIOCGSOFTCAR = 0x5419;
+  mips_linux_record_tdep.ioctl_TIOCSSOFTCAR = 0x541A;
+  mips_linux_record_tdep.ioctl_FIONREAD = 0x541B;
+  mips_linux_record_tdep.ioctl_TIOCINQ = mips_linux_record_tdep.ioctl_FIONREAD;
+  mips_linux_record_tdep.ioctl_TIOCLINUX = 0x541C;
+  mips_linux_record_tdep.ioctl_TIOCCONS = 0x541D;
+  mips_linux_record_tdep.ioctl_TIOCGSERIAL = 0x541E;
+  mips_linux_record_tdep.ioctl_TIOCSSERIAL = 0x541F;
+  mips_linux_record_tdep.ioctl_TIOCPKT = 0x5420;
+  mips_linux_record_tdep.ioctl_FIONBIO = 0x5421;
+  mips_linux_record_tdep.ioctl_TIOCNOTTY = 0x5422;
+  mips_linux_record_tdep.ioctl_TIOCSETD = 0x5423;
+  mips_linux_record_tdep.ioctl_TIOCGETD = 0x5424;
+  mips_linux_record_tdep.ioctl_TCSBRKP = 0x5425;
+  mips_linux_record_tdep.ioctl_TIOCTTYGSTRUCT = 0x5426;
+  mips_linux_record_tdep.ioctl_TIOCSBRK = 0x5427;
+  mips_linux_record_tdep.ioctl_TIOCCBRK = 0x5428;
+  mips_linux_record_tdep.ioctl_TIOCGSID = 0x5429;
+  mips_linux_record_tdep.ioctl_TCGETS2 = 0x802c542a;
+  mips_linux_record_tdep.ioctl_TCSETS2 = 0x402c542b;
+  mips_linux_record_tdep.ioctl_TCSETSW2 = 0x402c542c;
+  mips_linux_record_tdep.ioctl_TCSETSF2 = 0x402c542d;
+  mips_linux_record_tdep.ioctl_TIOCGPTN = 0x80045430;
+  mips_linux_record_tdep.ioctl_TIOCSPTLCK = 0x40045431;
+  mips_linux_record_tdep.ioctl_FIONCLEX = 0x5450;
+  mips_linux_record_tdep.ioctl_FIOCLEX = 0x5451;
+  mips_linux_record_tdep.ioctl_FIOASYNC = 0x5452;
+  mips_linux_record_tdep.ioctl_TIOCSERCONFIG = 0x5453;
+  mips_linux_record_tdep.ioctl_TIOCSERGWILD = 0x5454;
+  mips_linux_record_tdep.ioctl_TIOCSERSWILD = 0x5455;
+  mips_linux_record_tdep.ioctl_TIOCGLCKTRMIOS = 0x5456;
+  mips_linux_record_tdep.ioctl_TIOCSLCKTRMIOS = 0x5457;
+  mips_linux_record_tdep.ioctl_TIOCSERGSTRUCT = 0x5458;
+  mips_linux_record_tdep.ioctl_TIOCSERGETLSR = 0x5459;
+  mips_linux_record_tdep.ioctl_TIOCSERGETMULTI = 0x545A;
+  mips_linux_record_tdep.ioctl_TIOCSERSETMULTI = 0x545B;
+  mips_linux_record_tdep.ioctl_TIOCMIWAIT = 0x545C;
+  mips_linux_record_tdep.ioctl_TIOCGICOUNT = 0x545D;
+  mips_linux_record_tdep.ioctl_TIOCGHAYESESP = 0x545E;
+  mips_linux_record_tdep.ioctl_TIOCSHAYESESP = 0x545F;
+  mips_linux_record_tdep.ioctl_FIOQSIZE = 0x5460;
+
+  /* These values are the second argument of system call "sys_fcntl"
+  and "sys_fcntl64".  They are obtained from Linux Kernel source.  */
+  mips_linux_record_tdep.fcntl_F_GETLK = 5;
+  mips_linux_record_tdep.fcntl_F_GETLK64 = 12;
+  mips_linux_record_tdep.fcntl_F_SETLK64 = 13;
+  mips_linux_record_tdep.fcntl_F_SETLKW64 = 14;
+
+  mips_linux_record_tdep.arg1 = MIPS_A0_REGNUM;
+  mips_linux_record_tdep.arg2 = MIPS_A0_REGNUM + 1;
+  mips_linux_record_tdep.arg3 = MIPS_A0_REGNUM + 2;
+  mips_linux_record_tdep.arg4 = MIPS_A0_REGNUM + 3;
+  mips_linux_record_tdep.arg5 = MIPS_UNUSED_REGNUM; /* TODO: */
+  mips_linux_record_tdep.arg6 = MIPS_UNUSED_REGNUM;
+
+  tdep->mips_syscall_record = mips_linux_syscall_record;
+  
   switch (abi)
     {
       case MIPS_ABI_O32:
diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h
old mode 100644
new mode 100755
index 8fcf9c3..00888c7
--- a/gdb/mips-linux-tdep.h
+++ b/gdb/mips-linux-tdep.h
@@ -100,3 +100,689 @@ enum {
 /* Return 1 if MIPS_RESTART_REGNUM is usable.  */
 
 int mips_linux_restart_reg_p (struct gdbarch *gdbarch);
+
+/* Enum that defines the syscall identifiers for mips linux.
+   Used for process record/replay, these will be translated into
+   a gdb-canonical set of syscall ids in linux-record.c.  */
+ 
+enum mips_syscall_offset {
+  mips_sys_O32_syscall = 4000,
+  mips_sys_O32_exit = 4001,
+  mips_sys_O32_fork = 4002,
+  mips_sys_O32_read = 4003,
+  mips_sys_O32_write = 4004,
+  mips_sys_O32_open = 4005,
+  mips_sys_O32_close = 4006,
+  mips_sys_O32_waitpid = 4007,
+  mips_sys_O32_creat = 4008,
+  mips_sys_O32_link = 4009,
+  mips_sys_O32_unlink = 4010,
+  mips_sys_O32_execve = 4011,
+  mips_sys_O32_chdir = 4012,
+  mips_sys_O32_time = 4013,
+  mips_sys_O32_mknod = 4014,
+  mips_sys_O32_chmod = 4015,
+  mips_sys_O32_lchown = 4016,
+  mips_sys_O32_break = 4017,
+  mips_sys_O32_unused18 = 4018,
+  mips_sys_O32_lseek = 4019,
+  mips_sys_O32_getpid = 4020,
+  mips_sys_O32_mount = 4021,
+  mips_sys_O32_umount = 4022,
+  mips_sys_O32_setuid = 4023,
+  mips_sys_O32_getuid = 4024,
+  mips_sys_O32_stime = 4025,
+  mips_sys_O32_ptrace = 4026,
+  mips_sys_O32_alarm = 4027,
+  mips_sys_O32_unused28 = 4028,
+  mips_sys_O32_pause = 4029,
+  mips_sys_O32_utime = 4030,
+  mips_sys_O32_stty = 4031,
+  mips_sys_O32_gtty = 4032,
+  mips_sys_O32_access = 4033,
+  mips_sys_O32_nice = 4034,
+  mips_sys_O32_ftime = 4035,
+  mips_sys_O32_sync = 4036,
+  mips_sys_O32_kill = 4037,
+  mips_sys_O32_rename = 4038,
+  mips_sys_O32_mkdir = 4039,
+  mips_sys_O32_rmdir = 4040,
+  mips_sys_O32_dup = 4041,
+  mips_sys_O32_pipe = 4042,
+  mips_sys_O32_times = 4043,
+  mips_sys_O32_prof = 4044,
+  mips_sys_O32_brk = 4045,
+  mips_sys_O32_setgid = 4046,
+  mips_sys_O32_getgid = 4047,
+  mips_sys_O32_signal = 4048,
+  mips_sys_O32_geteuid = 4049,
+  mips_sys_O32_getegid = 4050,
+  mips_sys_O32_acct = 4051,
+  mips_sys_O32_umount2 = 4052,
+  mips_sys_O32_lock = 4053,
+  mips_sys_O32_ioctl = 4054,
+  mips_sys_O32_fcntl = 4055,
+  mips_sys_O32_mpx = 4056,
+  mips_sys_O32_setpgid = 4057,
+  mips_sys_O32_ulimit = 4058,
+  mips_sys_O32_unused59 = 4059,
+  mips_sys_O32_umask = 4060,
+  mips_sys_O32_chroot = 4061,
+  mips_sys_O32_ustat = 4062,
+  mips_sys_O32_dup2 = 4063,
+  mips_sys_O32_getppid = 4064,
+  mips_sys_O32_getpgrp = 4065,
+  mips_sys_O32_setsid = 4066,
+  mips_sys_O32_sigaction = 4067,
+  mips_sys_O32_sgetmask = 4068,
+  mips_sys_O32_ssetmask = 4069,
+  mips_sys_O32_setreuid = 4070,
+  mips_sys_O32_setregid = 4071,
+  mips_sys_O32_sigsuspend = 4072,
+  mips_sys_O32_sigpending = 4073,
+  mips_sys_O32_sethostname = 4074,
+  mips_sys_O32_setrlimit = 4075,
+  mips_sys_O32_getrlimit = 4076,
+  mips_sys_O32_getrusage = 4077,
+  mips_sys_O32_gettimeofday = 4078,
+  mips_sys_O32_settimeofday = 4079,
+  mips_sys_O32_getgroups = 4080,
+  mips_sys_O32_setgroups = 4081,
+  mips_sys_O32_reserved82 = 4082,
+  mips_sys_O32_symlink = 4083,
+  mips_sys_O32_unused84 = 4084,
+  mips_sys_O32_readlink = 4085,
+  mips_sys_O32_uselib = 4086,
+  mips_sys_O32_swapon = 4087,
+  mips_sys_O32_reboot = 4088,
+  mips_sys_O32_readdir = 4089,
+  mips_sys_O32_mmap = 4090,
+  mips_sys_O32_munmap = 4091,
+  mips_sys_O32_truncate = 4092,
+  mips_sys_O32_ftruncate = 4093,
+  mips_sys_O32_fchmod = 4094,
+  mips_sys_O32_fchown = 4095,
+  mips_sys_O32_getpriority = 4096,
+  mips_sys_O32_setpriority = 4097,
+  mips_sys_O32_profil = 4098,
+  mips_sys_O32_statfs = 4099,
+  mips_sys_O32_fstatfs = 4100,
+  mips_sys_O32_ioperm = 4101,
+  mips_sys_O32_socketcall = 4102,
+  mips_sys_O32_syslog = 4103,
+  mips_sys_O32_setitimer = 4104,
+  mips_sys_O32_getitimer = 4105,
+  mips_sys_O32_stat = 4106,
+  mips_sys_O32_lstat = 4107,
+  mips_sys_O32_fstat = 4108,
+  mips_sys_O32_unused109 = 4109,
+  mips_sys_O32_iopl = 4110,
+  mips_sys_O32_vhangup = 4111,
+  mips_sys_O32_idle = 4112,
+  mips_sys_O32_vm86 = 4113,
+  mips_sys_O32_wait4 = 4114,
+  mips_sys_O32_swapoff = 4115,
+  mips_sys_O32_sysinfo = 4116,
+  mips_sys_O32_ipc = 4117,
+  mips_sys_O32_fsync = 4118,
+  mips_sys_O32_sigreturn = 4119,
+  mips_sys_O32_clone = 4120,
+  mips_sys_O32_setdomainname = 4121,
+  mips_sys_O32_uname = 4122,
+  mips_sys_O32_modify_ldt = 4123,
+  mips_sys_O32_adjtimex = 4124,
+  mips_sys_O32_mprotect = 4125,
+  mips_sys_O32_sigprocmask = 4126,
+  mips_sys_O32_create_module = 4127,
+  mips_sys_O32_init_module = 4128,
+  mips_sys_O32_delete_module = 4129,
+  mips_sys_O32_get_kernel_syms = 4130,
+  mips_sys_O32_quotactl = 4131,
+  mips_sys_O32_getpgid = 4132,
+  mips_sys_O32_fchdir = 4133,
+  mips_sys_O32_bdflush = 4134,
+  mips_sys_O32_sysfs = 4135,
+  mips_sys_O32_personality = 4136,
+  mips_sys_O32_afs_syscall = 4137,
+  mips_sys_O32_setfsuid = 4138,
+  mips_sys_O32_setfsgid = 4139,
+  mips_sys_O32__llseek = 4140,
+  mips_sys_O32_getdents = 4141,
+  mips_sys_O32__newselect = 4142,
+  mips_sys_O32_flock = 4143,
+  mips_sys_O32_msync = 4144,
+  mips_sys_O32_readv = 4145,
+  mips_sys_O32_writev = 4146,
+  mips_sys_O32_cacheflush = 4147,
+  mips_sys_O32_cachectl = 4148,
+  mips_sys_O32_sysmips = 4149,
+  mips_sys_O32_unused150 = 4150,
+  mips_sys_O32_getsid = 4151,
+  mips_sys_O32_fdatasync = 4152,
+  mips_sys_O32__sysctl = 4153,
+  mips_sys_O32_mlock = 4154,
+  mips_sys_O32_munlock = 4155,
+  mips_sys_O32_mlockall = 4156,
+  mips_sys_O32_munlockall = 4157,
+  mips_sys_O32_sched_setparam = 4158,
+  mips_sys_O32_sched_getparam = 4159,
+  mips_sys_O32_sched_setscheduler = 4160,
+  mips_sys_O32_sched_getscheduler = 4161,
+  mips_sys_O32_sched_yield = 4162,
+  mips_sys_O32_sched_get_priority_max = 4163,
+  mips_sys_O32_sched_get_priority_min = 4164,
+  mips_sys_O32_sched_rr_get_interval = 4165,
+  mips_sys_O32_nanosleep = 4166,
+  mips_sys_O32_mremap = 4167,
+  mips_sys_O32_accept = 4168,
+  mips_sys_O32_bind = 4169,
+  mips_sys_O32_connect = 4170,
+  mips_sys_O32_getpeername = 4171,
+  mips_sys_O32_getsockname = 4172,
+  mips_sys_O32_getsockopt = 4173,
+  mips_sys_O32_listen = 4174,
+  mips_sys_O32_recv = 4175,
+  mips_sys_O32_recvfrom = 4176,
+  mips_sys_O32_recvmsg = 4177,
+  mips_sys_O32_send = 4178,
+  mips_sys_O32_sendmsg = 4179,
+  mips_sys_O32_sendto = 4180,
+  mips_sys_O32_setsockopt = 4181,
+  mips_sys_O32_shutdown = 4182,
+  mips_sys_O32_socket = 4183,
+  mips_sys_O32_socketpair = 4184,
+  mips_sys_O32_setresuid = 4185,
+  mips_sys_O32_getresuid = 4186,
+  mips_sys_O32_query_module = 4187,
+  mips_sys_O32_poll = 4188,
+  mips_sys_O32_nfsservctl = 4189,
+  mips_sys_O32_setresgid = 4190,
+  mips_sys_O32_getresgid = 4191,
+  mips_sys_O32_prctl = 4192,
+  mips_sys_O32_rt_sigreturn = 4193,
+  mips_sys_O32_rt_sigaction = 4194,
+  mips_sys_O32_rt_sigprocmask = 4195,
+  mips_sys_O32_rt_sigpending = 4196,
+  mips_sys_O32_rt_sigtimedwait = 4197,
+  mips_sys_O32_rt_sigqueueinfo = 4198,
+  mips_sys_O32_rt_sigsuspend = 4199,
+  mips_sys_O32_pread = 4200,
+  mips_sys_O32_pwrite = 4201,
+  mips_sys_O32_chown = 4202,
+  mips_sys_O32_getcwd = 4203,
+  mips_sys_O32_capget = 4204,
+  mips_sys_O32_capset = 4205,
+  mips_sys_O32_sigaltstack = 4206,
+  mips_sys_O32_sendfile = 4207,
+  mips_sys_O32_getpmsg = 4208,
+  mips_sys_O32_putpmsg = 4209,
+  mips_sys_O32_mmap2 = 4210,
+  mips_sys_O32_truncate64 = 4211,
+  mips_sys_O32_ftruncate64 = 4212,
+  mips_sys_O32_stat64 = 4213,
+  mips_sys_O32_lstat64 = 4214,
+  mips_sys_O32_fstat64 = 4215,
+  mips_sys_O32_root_pivot = 4216,
+  mips_sys_O32_mincore = 4217,
+  mips_sys_O32_madvise = 4218,
+  mips_sys_O32_getdents64 = 4219,
+  mips_sys_O32_fcntl64 = 4220,
+  mips_sys_O32_security = 4221,
+  mips_sys_O32_gettid = 4222,
+  mips_sys_O32_readahead = 4223,
+  mips_sys_O32_setxattr = 4224,
+  mips_sys_O32_lsetxattr = 4225,
+  mips_sys_O32_fsetxattr = 4226,
+  mips_sys_O32_getxattr = 4227,
+  mips_sys_O32_lgetxattr = 4228,
+  mips_sys_O32_fgetxattr = 4229,
+  mips_sys_O32_listxattr = 4230,
+  mips_sys_O32_llistxattr = 4231,
+  mips_sys_O32_flistxattr = 4232,
+  mips_sys_O32_removexattr = 4233,
+  mips_sys_O32_lremovexattr = 4234,
+  mips_sys_O32_fremovexattr = 4235,
+  mips_sys_O32_tkill = 4236,
+  mips_sys_O32_sendfile64 = 4237,
+  mips_sys_O32_futex = 4238,
+  mips_sys_O32_sched_setaffinity = 4239,
+  mips_sys_O32_sched_getaffinity = 4240,
+  mips_sys_rw_performance_counter = 5248,
+  mips_sys_read = 5000,
+  mips_sys_write = 5001,
+  mips_sys_open = 5002,
+  mips_sys_close = 5003,
+  mips_sys_stat = 5004,
+  mips_sys_fstat = 5005,
+  mips_sys_lstat = 5006,
+  mips_sys_poll = 5007,
+  mips_sys_lseek = 5008,
+  mips_sys_mmap = 5009,
+  mips_sys_mprotect = 5010,
+  mips_sys_munmap = 5011,
+  mips_sys_brk = 5012,
+  mips_sys_rt_sigaction = 5013,
+  mips_sys_rt_sigprocmask = 5014,
+  mips_sys_ioctl = 5015,
+  mips_sys_pread = 5016,
+  mips_sys_pwrite = 5017,
+  mips_sys_readv = 5018,
+  mips_sys_writev = 5019,
+  mips_sys_access = 5020,
+  mips_sys_pipe = 5021,
+  mips_sys__newselect = 5022,
+  mips_sys_sched_yield = 5023,
+  mips_sys_mremap = 5024,
+  mips_sys_msync = 5025,
+  mips_sys_mincore = 5026,
+  mips_sys_madvise = 5027,
+  mips_sys_shmget = 5028,
+  mips_sys_shmat = 5029,
+  mips_sys_shmctl = 5030,
+  mips_sys_dup = 5031,
+  mips_sys_dup2 = 5032,
+  mips_sys_pause = 5033,
+  mips_sys_nanosleep = 5034,
+  mips_sys_getitimer = 5035,
+  mips_sys_setitimer = 5036,
+  mips_sys_alarm = 5037,
+  mips_sys_getpid = 5038,
+  mips_sys_sendfile = 5039,
+  mips_sys_socket = 5040,
+  mips_sys_connect = 5041,
+  mips_sys_accept = 5042,
+  mips_sys_sendto = 5043,
+  mips_sys_recvfrom = 5044,
+  mips_sys_sendmsg = 5045,
+  mips_sys_recvmsg = 5046,
+  mips_sys_shutdown = 5047,
+  mips_sys_bind = 5048,
+  mips_sys_listen = 5049,
+  mips_sys_getsockname = 5050,
+  mips_sys_getpeername = 5051,
+  mips_sys_socketpair = 5052,
+  mips_sys_setsockopt = 5053,
+  mips_sys_getsockopt = 5054,
+  mips_sys_clone = 5055,
+  mips_sys_fork = 5056,
+  mips_sys_execve = 5057,
+  mips_sys_exit = 5058,
+  mips_sys_wait4 = 5059,
+  mips_sys_kill = 5060,
+  mips_sys_uname = 5061,
+  mips_sys_semget = 5062,
+  mips_sys_semop = 5063,
+  mips_sys_semctl = 5064,
+  mips_sys_shmdt = 5065,
+  mips_sys_msgget = 5066,
+  mips_sys_msgsnd = 5067,
+  mips_sys_msgrcv = 5068,
+  mips_sys_msgctl = 5069,
+  mips_sys_fcntl = 5070,
+  mips_sys_flock = 5071,
+  mips_sys_fsync = 5072,
+  mips_sys_fdatasync = 5073,
+  mips_sys_truncate = 5074,
+  mips_sys_ftruncate = 5075,
+  mips_sys_getdents = 5076,
+  mips_sys_getcwd = 5077,
+  mips_sys_chdir = 5078,
+  mips_sys_fchdir = 5079,
+  mips_sys_rename = 5080,
+  mips_sys_mkdir = 5081,
+  mips_sys_rmdir = 5082,
+  mips_sys_creat = 5083,
+  mips_sys_link = 5084,
+  mips_sys_unlink = 5085,
+  mips_sys_symlink = 5086,
+  mips_sys_readlink = 5087,
+  mips_sys_chmod = 5088,
+  mips_sys_fchmod = 5089,
+  mips_sys_chown = 5090,
+  mips_sys_fchown = 5091,
+  mips_sys_lchown = 5092,
+  mips_sys_umask = 5093,
+  mips_sys_gettimeofday = 5094,
+  mips_sys_getrlimit = 5095,
+  mips_sys_getrusage = 5096,
+  mips_sys_sysinfo = 5097,
+  mips_sys_times = 5098,
+  mips_sys_ptrace = 5099,
+  mips_sys_getuid = 5100,
+  mips_sys_syslog = 5101,
+  mips_sys_getgid = 5102,
+  mips_sys_setuid = 5103,
+  mips_sys_setgid = 5104,
+  mips_sys_geteuid = 5105,
+  mips_sys_getegid = 5106,
+  mips_sys_setpgid = 5107,
+  mips_sys_getppid = 5108,
+  mips_sys_getpgrp = 5109,
+  mips_sys_setsid = 5110,
+  mips_sys_setreuid = 5111,
+  mips_sys_setregid = 5112,
+  mips_sys_getgroups = 5113,
+  mips_sys_setgroups = 5114,
+  mips_sys_setresuid = 5115,
+  mips_sys_getresuid = 5116,
+  mips_sys_setresgid = 5117,
+  mips_sys_getresgid = 5118,
+  mips_sys_getpgid = 5119,
+  mips_sys_setfsuid = 5120,
+  mips_sys_setfsgid = 5121,
+  mips_sys_getsid = 5122,
+  mips_sys_capget = 5123,
+  mips_sys_capset = 5124,
+  mips_sys_rt_sigpending = 5125,
+  mips_sys_rt_sigtimedwait = 5126,
+  mips_sys_rt_sigqueueinfo = 5127,
+  mips_sys_rt_sigsuspend = 5128,
+  mips_sys_sigaltstack = 5129,
+  mips_sys_utime = 5130,
+  mips_sys_mknod = 5131,
+  mips_sys_personality = 5132,
+  mips_sys_ustat = 5133,
+  mips_sys_statfs = 5134,
+  mips_sys_fstatfs = 5135,
+  mips_sys_sysfs = 5136,
+  mips_sys_getpriority = 5137,
+  mips_sys_setpriority = 5138,
+  mips_sys_sched_setparam = 5139,
+  mips_sys_sched_getparam = 5140,
+  mips_sys_sched_setscheduler = 5141,
+  mips_sys_sched_getscheduler = 5142,
+  mips_sys_sched_get_priority_max = 5143,
+  mips_sys_sched_get_priority_min = 5144,
+  mips_sys_sched_rr_get_interval = 5145,
+  mips_sys_mlock = 5146,
+  mips_sys_munlock = 5147,
+  mips_sys_mlockall = 5148,
+  mips_sys_munlockall = 5149,
+  mips_sys_vhangup = 5150,
+  mips_sys_pivot_root = 5151,
+  mips_sys__sysctl = 5152,
+  mips_sys_prctl = 5153,
+  mips_sys_adjtimex = 5154,
+  mips_sys_setrlimit = 5155,
+  mips_sys_chroot = 5156,
+  mips_sys_sync = 5157,
+  mips_sys_acct = 5158,
+  mips_sys_settimeofday = 5159,
+  mips_sys_mount = 5160,
+  mips_sys_umount2 = 5161,
+  mips_sys_swapon = 5162,
+  mips_sys_swapoff = 5163,
+  mips_sys_reboot = 5164,
+  mips_sys_sethostname = 5165,
+  mips_sys_setdomainname = 5166,
+  mips_sys_create_module = 5167,
+  mips_sys_init_module = 5168,
+  mips_sys_delete_module = 5169,
+  mips_sys_get_kernel_syms = 5170,
+  mips_sys_query_module = 5171,
+  mips_sys_quotactl = 5172,
+  mips_sys_nfsservctl = 5173,
+  mips_sys_getpmsg = 5174,
+  mips_sys_putpmsg = 5175,
+  mips_sys_afs_syscall = 5176,
+  mips_sys_security = 5177,
+  mips_sys_gettid = 5178,
+  mips_sys_readahead = 5179,
+  mips_sys_setxattr = 5180,
+  mips_sys_lsetxattr = 5181,
+  mips_sys_fsetxattr = 5182,
+  mips_sys_getxattr = 5183,
+  mips_sys_lgetxattr = 5184,
+  mips_sys_fgetxattr = 5185,
+  mips_sys_listxattr = 5186,
+  mips_sys_llistxattr = 5187,
+  mips_sys_flistxattr = 5188,
+  mips_sys_removexattr = 5189,
+  mips_sys_lremovexattr = 5190,
+  mips_sys_fremovexattr = 5191,
+  mips_sys_tkill = 5192,
+  mips_sys_unused193 = 5193,
+  mips_sys_futex = 5194,
+  mips_sys_sched_setaffinity = 5195,
+  mips_sys_sched_getaffinity = 5196,
+  mips_sys_cacheflush = 5197,
+  mips_sys_cachectl = 5198,
+  mips_sys_sysmips = 5199,
+  mips_sys_unused200 = 5200,
+  mips_sys_unused201 = 5201,
+  mips_sys_unused202 = 5202,
+  mips_sys_unused203 = 5203,
+  mips_sys_unused204 = 5204,
+  mips_sys_unused205 = 5205,
+  mips_sys_unused206 = 5206,
+  mips_sys_unused207 = 5207,
+  mips_sys_unused208 = 5208,
+  mips_sys_unused209 = 5209,
+  mips_sys_unused210 = 5210,
+  mips_sys_rt_sigreturn = 5211,
+  mips_sys_unused212 = 5212,
+  mips_sys_unused213 = 5213,
+  mips_sys_semtimedop = 5214,
+  mips_sys_N32_read = 6000,
+  mips_sys_N32_write = 6001,
+  mips_sys_N32_open = 6002,
+  mips_sys_N32_close = 6003,
+  mips_sys_N32_stat = 6004,
+  mips_sys_N32_fstat = 6005,
+  mips_sys_N32_lstat = 6006,
+  mips_sys_N32_poll = 6007,
+  mips_sys_N32_lseek = 6008,
+  mips_sys_N32_mmap = 6009,
+  mips_sys_N32_mprotect = 6010,
+  mips_sys_N32_munmap = 6011,
+  mips_sys_N32_brk = 6012,
+  mips_sys_N32_rt_sigaction = 6013,
+  mips_sys_N32_rt_sigprocmask = 6014,
+  mips_sys_N32_ioctl = 6015,
+  mips_sys_N32_pread = 6016,
+  mips_sys_N32_pwrite = 6017,
+  mips_sys_N32_readv = 6018,
+  mips_sys_N32_writev = 6019,
+  mips_sys_N32_access = 6020,
+  mips_sys_N32_pipe = 6021,
+  mips_sys_N32__newselect = 6022,
+  mips_sys_N32_sched_yield = 6023,
+  mips_sys_N32_mremap = 6024,
+  mips_sys_N32_msync = 6025,
+  mips_sys_N32_mincore = 6026,
+  mips_sys_N32_madvise = 6027,
+  mips_sys_N32_shmget = 6028,
+  mips_sys_N32_shmat = 6029,
+  mips_sys_N32_shmctl = 6030,
+  mips_sys_N32_dup = 6031,
+  mips_sys_N32_dup2 = 6032,
+  mips_sys_N32_pause = 6033,
+  mips_sys_N32_nanosleep = 6034,
+  mips_sys_N32_getitimer = 6035,
+  mips_sys_N32_setitimer = 6036,
+  mips_sys_N32_alarm = 6037,
+  mips_sys_N32_getpid = 6038,
+  mips_sys_N32_sendfile = 6039,
+  mips_sys_N32_socket = 6040,
+  mips_sys_N32_connect = 6041,
+  mips_sys_N32_accept = 6042,
+  mips_sys_N32_sendto = 6043,
+  mips_sys_N32_recvfrom = 6044,
+  mips_sys_N32_sendmsg = 6045,
+  mips_sys_N32_recvmsg = 6046,
+  mips_sys_N32_shutdown = 6047,
+  mips_sys_N32_bind = 6048,
+  mips_sys_N32_listen = 6049,
+  mips_sys_N32_getsockname = 6050,
+  mips_sys_N32_getpeername = 6051,
+  mips_sys_N32_socketpair = 6052,
+  mips_sys_N32_setsockopt = 6053,
+  mips_sys_N32_getsockopt = 6054,
+  mips_sys_N32_clone = 6055,
+  mips_sys_N32_fork = 6056,
+  mips_sys_N32_execve = 6057,
+  mips_sys_N32_exit = 6058,
+  mips_sys_N32_wait4 = 6059,
+  mips_sys_N32_kill = 6060,
+  mips_sys_N32_uname = 6061,
+  mips_sys_N32_semget = 6062,
+  mips_sys_N32_semop = 6063,
+  mips_sys_N32_semctl = 6064,
+  mips_sys_N32_shmdt = 6065,
+  mips_sys_N32_msgget = 6066,
+  mips_sys_N32_msgsnd = 6067,
+  mips_sys_N32_msgrcv = 6068,
+  mips_sys_N32_msgctl = 6069,
+  mips_sys_N32_fcntl = 6070,
+  mips_sys_N32_flock = 6071,
+  mips_sys_N32_fsync = 6072,
+  mips_sys_N32_fdatasync = 6073,
+  mips_sys_N32_truncate = 6074,
+  mips_sys_N32_ftruncate = 6075,
+  mips_sys_N32_getdents = 6076,
+  mips_sys_N32_getcwd = 6077,
+  mips_sys_N32_chdir = 6078,
+  mips_sys_N32_fchdir = 6079,
+  mips_sys_N32_rename = 6080,
+  mips_sys_N32_mkdir = 6081,
+  mips_sys_N32_rmdir = 6082,
+  mips_sys_N32_creat = 6083,
+  mips_sys_N32_link = 6084,
+  mips_sys_N32_unlink = 6085,
+  mips_sys_N32_symlink = 6086,
+  mips_sys_N32_readlink = 6087,
+  mips_sys_N32_chmod = 6088,
+  mips_sys_N32_fchmod = 6089,
+  mips_sys_N32_chown = 6090,
+  mips_sys_N32_fchown = 6091,
+  mips_sys_N32_lchown = 6092,
+  mips_sys_N32_umask = 6093,
+  mips_sys_N32_gettimeofday = 6094,
+  mips_sys_N32_getrlimit = 6095,
+  mips_sys_N32_getrusage = 6096,
+  mips_sys_N32_sysinfo = 6097,
+  mips_sys_N32_times = 6098,
+  mips_sys_N32_ptrace = 6099,
+  mips_sys_N32_getuid = 6100,
+  mips_sys_N32_syslog = 6101,
+  mips_sys_N32_getgid = 6102,
+  mips_sys_N32_setuid = 6103,
+  mips_sys_N32_setgid = 6104,
+  mips_sys_N32_geteuid = 6105,
+  mips_sys_N32_getegid = 6106,
+  mips_sys_N32_setpgid = 6107,
+  mips_sys_N32_getppid = 6108,
+  mips_sys_N32_getpgrp = 6109,
+  mips_sys_N32_setsid = 6110,
+  mips_sys_N32_setreuid = 6111,
+  mips_sys_N32_setregid = 6112,
+  mips_sys_N32_getgroups = 6113,
+  mips_sys_N32_setgroups = 6114,
+  mips_sys_N32_setresuid = 6115,
+  mips_sys_N32_getresuid = 6116,
+  mips_sys_N32_setresgid = 6117,
+  mips_sys_N32_getresgid = 6118,
+  mips_sys_N32_getpgid = 6119,
+  mips_sys_N32_setfsuid = 6120,
+  mips_sys_N32_setfsgid = 6121,
+  mips_sys_N32_getsid = 6122,
+  mips_sys_N32_capget = 6123,
+  mips_sys_N32_capset = 6124,
+  mips_sys_N32_rt_sigpending = 6125,
+  mips_sys_N32_rt_sigtimedwait = 6126,
+  mips_sys_N32_rt_sigqueueinfo = 6127,
+  mips_sys_N32_rt_sigsuspend = 6128,
+  mips_sys_N32_sigaltstack = 6129,
+  mips_sys_N32_utime = 6130,
+  mips_sys_N32_mknod = 6131,
+  mips_sys_N32_personality = 6132,
+  mips_sys_N32_ustat = 6133,
+  mips_sys_N32_statfs = 6134,
+  mips_sys_N32_fstatfs = 6135,
+  mips_sys_N32_sysfs = 6136,
+  mips_sys_N32_getpriority = 6137,
+  mips_sys_N32_setpriority = 6138,
+  mips_sys_N32_sched_setparam = 6139,
+  mips_sys_N32_sched_getparam = 6140,
+  mips_sys_N32_sched_setscheduler = 6141,
+  mips_sys_N32_sched_getscheduler = 6142,
+  mips_sys_N32_sched_get_priority_max = 6143,
+  mips_sys_N32_sched_get_priority_min = 6144,
+  mips_sys_N32_sched_rr_get_interval = 6145,
+  mips_sys_N32_mlock = 6146,
+  mips_sys_N32_munlock = 6147,
+  mips_sys_N32_mlockall = 6148,
+  mips_sys_N32_munlockall = 6149,
+  mips_sys_N32_vhangup = 6150,
+  mips_sys_N32_pivot_root = 6151,
+  mips_sys_N32__sysctl = 6152,
+  mips_sys_N32_prctl = 6153,
+  mips_sys_N32_adjtimex = 6154,
+  mips_sys_N32_setrlimit = 6155,
+  mips_sys_N32_chroot = 6156,
+  mips_sys_N32_sync = 6157,
+  mips_sys_N32_acct = 6158,
+  mips_sys_N32_settimeofday = 6159,
+  mips_sys_N32_mount = 6160,
+  mips_sys_N32_umount2 = 6161,
+  mips_sys_N32_swapon = 6162,
+  mips_sys_N32_swapoff = 6163,
+  mips_sys_N32_reboot = 6164,
+  mips_sys_N32_sethostname = 6165,
+  mips_sys_N32_setdomainname = 6166,
+  mips_sys_N32_create_module = 6167,
+  mips_sys_N32_init_module = 6168,
+  mips_sys_N32_delete_module = 6169,
+  mips_sys_N32_get_kernel_syms = 6170,
+  mips_sys_N32_query_module = 6171,
+  mips_sys_N32_quotactl = 6172,
+  mips_sys_N32_nfsservctl = 6173,
+  mips_sys_N32_getpmsg = 6174,
+  mips_sys_N32_putpmsg = 6175,
+  mips_sys_N32_afs_syscall = 6176,
+  mips_sys_N32_security = 6177,
+  mips_sys_N32_gettid = 6178,
+  mips_sys_N32_readahead = 6179,
+  mips_sys_N32_setxattr = 6180,
+  mips_sys_N32_lsetxattr = 6181,
+  mips_sys_N32_fsetxattr = 6182,
+  mips_sys_N32_getxattr = 6183,
+  mips_sys_N32_lgetxattr = 6184,
+  mips_sys_N32_fgetxattr = 6185,
+  mips_sys_N32_listxattr = 6186,
+  mips_sys_N32_llistxattr = 6187,
+  mips_sys_N32_flistxattr = 6188,
+  mips_sys_N32_removexattr = 6189,
+  mips_sys_N32_lremovexattr = 6190,
+  mips_sys_N32_fremovexattr = 6191,
+  mips_sys_N32_tkill = 6192,
+  mips_sys_N32_time = 6193,
+  mips_sys_N32_futex = 6194,
+  mips_sys_N32_sched_setaffinity = 6195,
+  mips_sys_N32_sched_getaffinity = 6196,
+  mips_sys_N32_cacheflush = 6197,
+  mips_sys_N32_cachectl = 6198,
+  mips_sys_N32_sysmips = 6199,
+  mips_sys_N32_unused200 = 6200,
+  mips_sys_N32_unused201 = 6201,
+  mips_sys_N32_unused202 = 6202,
+  mips_sys_N32_unused203 = 6203,
+  mips_sys_N32_unused204 = 6204,
+  mips_sys_N32_unused205 = 6205,
+  mips_sys_N32_unused206 = 6206,
+  mips_sys_N32_unused207 = 6207,
+  mips_sys_N32_unused208 = 6208,
+  mips_sys_N32_unused209 = 6209,
+  mips_sys_N32_unused210 = 6210,
+  mips_sys_N32_rt_sigreturn = 6211,
+  mips_sys_N32_fcntl64 = 6212,
+  mips_sys_N32_unused213 = 6213,
+  mips_sys_N32_unused214 = 6214,
+  mips_sys_N32_semtimedop = 6215,
+  mips_sys_N32_unused216 = 6216,
+  mips_sys_N32_unused217 = 6217,
+  mips_sys_N32_unused218 = 6218,
+  mips_sys_N32_sendfile64 = 6219
+};
+
+int mips_syscall (enum mips_abi abi, enum mips_syscall_offset offset);
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
old mode 100644
new mode 100755
index c4d24ff..6601197
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -59,6 +59,9 @@
 #include "user-regs.h"
 #include "valprint.h"
 
+#include "record.h"
+#include <stdint.h>
+
 static const struct objfile_data *mips_pdr_data;
 
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
@@ -5426,6 +5429,735 @@ value_of_mips_user_reg (struct frame_info *frame, const void *baton)
   return value_of_register (*reg_p, frame);
 }
 
+/* When "record_delay_slot" is true (mean that the prev instruction has delay
+   slot), GDB  need to deal with instrction in the delay slot that address is
+   "mips_delay_slot_addr" and the instruction in target of delay slot
+   instruction that address is "mips_target_addr". */
+static int record_delay_slot;
+static CORE_ADDR mips_delay_slot_addr;
+static CORE_ADDR mips_target_addr;
+
+/* Record the value of the memory that willbe changed in current 32 bits instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+static int
+mips_record_32 (struct gdbarch *gdbarch, struct regcache * record_regcache, CORE_ADDR pc)
+{
+  uint32_t insn = (uint32_t) mips_fetch_instruction (gdbarch, pc);
+  uint32_t opcode;
+  const struct mips_regnum *regnum = mips_regnum (gdbarch);
+  int add_pc = 1;
+  uint32_t tmpu32;
+
+  if (record_debug)
+    {
+      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 (record_regcache, 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 (record_regcache, regnum->hi))
+	    {
+	      return (-1);
+	    }
+	  break;
+	  /* mtlo */
+	case 0x13:
+	  if (record_arch_list_add_reg (record_regcache, 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 (record_regcache, 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 (record_regcache, 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 (record_regcache, 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 (record_regcache, 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 (record_regcache, 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 (record_regcache, regnum->cause))
+		      {
+			return (-1);
+		      }
+		  case 8:
+		    /* badvaddr */
+		    if (record_arch_list_add_reg (record_regcache, 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 (record_regcache, 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 (record_regcache, regnum->pc))
+	    {
+	      return (-1);
+	    }
+	  add_pc = 0;
+	}
+    }
+  if (record_arch_list_add_end ())
+    {
+      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 (record_regcache, rd))
+	  {
+	    return (-1);
+	  }
+      }
+  }
+  goto out;
+
+set_rt:
+  {
+    uint32_t rt = (insn >> 16) & 0x1f;
+    if (rt != 0)
+      {
+	if (record_arch_list_add_reg (record_regcache, 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 (record_regcache, regnum->pc))
+    {
+      return (-1);
+    }
+  add_pc = 0;
+  goto out;
+
+set_hi_lo:
+  if (record_arch_list_add_reg (record_regcache, regnum->hi))
+    {
+      return (-1);
+    }
+  if (record_arch_list_add_reg (record_regcache, regnum->lo))
+    {
+      return (-1);
+    }
+  goto out;
+}
+
+/* Record the value of the memory that willbe changed in current instruction
+   to "record_arch_list".
+   Return -1 if something wrong. */
+int mips_record (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr)
+{
+  CORE_ADDR pc = addr;
+/*
+  if (record_debug)
+    {
+      fprintf_unfiltered (gdb_stdlog, "record: mips_record pc = 0x%p\n",
+			  (void *)(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 (gdbarch, regcache, mips_delay_slot_addr))
+	{
+	  return (-1);
+	}
+      if (mips_record_32 (gdbarch, regcache, mips_target_addr))
+	{
+	  return (-1);
+	}
+      record_delay_slot--;
+    }
+  return (mips_record_32 (gdbarch, regcache, pc));
+}
+#if 0
+static void mips_record_dasm (struct gdbarch *gdbarch)
+{
+  const struct mips_regnum *regnum;
+  ULONGEST pc;
+
+  if (mips_pc_is_mips16 (read_pc ()))
+    {
+      error (_
+	     ("record: record and reverse function don't support mips16.\n"));
+    }
+
+  regnum = mips_regnum (gdbarch);
+  regcache_cooked_read_unsigned (record_regcache, regnum->pc, &pc);
+  if (gdb_is_reverse)
+    {
+      pc -= 4;
+    }
+  else
+    {
+      pc += 4;
+    }
+  regcache_cooked_write_unsigned (record_regcache, regnum->pc, pc);
+}
+#endif
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
old mode 100644
new mode 100755
index d7be66a..ad115d0
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -99,6 +99,9 @@ struct gdbarch_tdep
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+   
+  /* Parse syscall args.  */
+  int (*mips_syscall_record) (struct regcache *regcache);
 };
 
 /* Register numbers of various important registers.  */
@@ -152,4 +155,6 @@ extern unsigned int mips_abi_regsize (struct gdbarch *gdbarch);
 extern struct target_desc *mips_tdesc_gp32;
 extern struct target_desc *mips_tdesc_gp64;
 
+extern int mips_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
 #endif /* MIPS_TDEP_H */
diff --git a/gdb/record.c b/gdb/record.c
old mode 100644
new mode 100755
index 327555d..8006314
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -1002,9 +1002,23 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step,
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
       record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
                                 signal);
+
+       if (gdbarch_software_single_step_p (gdbarch))
+         {
+           if (!single_step_breakpoints_inserted ())
+             gdbarch_software_single_step (gdbarch, get_current_frame ());
+           record_beneath_to_resume (record_beneath_to_resume_ops,
+                                     ptid, step, signal);
+           record_resume_step = 0;
+         }
+       else
+         record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+                                   signal);
     }
 }
 
@@ -1077,6 +1091,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
@@ -1099,6 +1114,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1129,9 +1147,18 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
-		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
-						TARGET_SIGNAL_0);
+                      if (gdbarch_software_single_step_p (gdbarch))
+                        {
+                          gdbarch_software_single_step (gdbarch,
+                                                        get_current_frame ());
+                          record_beneath_to_resume (record_beneath_to_resume_ops,
+                                                    ptid, 0,
+                                                    TARGET_SIGNAL_0);
+                        }
+                      else
+		        record_beneath_to_resume (record_beneath_to_resume_ops,
+						  ptid, 1,
+						  TARGET_SIGNAL_0);
 		      continue;
 		    }
 		}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-23  9:24         ` Hui Zhu
       [not found]           ` <8d62b6fe0912231751p1202294cw83430e8d53af0951@mail.gmail.com>
@ 2009-12-24 17:38           ` Pedro Alves
  2010-01-04 14:23             ` Hui Zhu
  1 sibling, 1 reply; 18+ messages in thread
From: Pedro Alves @ 2009-12-24 17:38 UTC (permalink / raw)
  To: gdb-patches
  Cc: Hui Zhu, Joel Brobecker, Michael Snyder, shuchang zhou,
	paawan oza, Tom Tromey

On Wednesday 23 December 2009 09:23:21, Hui Zhu wrote:
> +      struct gdbarch *gdbarch = target_thread_architecture (ptid);
> +
>        record_message (get_current_regcache (), signal);

>        record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
>                                  signal);

Why is this resume call still present?

> +
> +       if (gdbarch_software_single_step_p (gdbarch))
> +         {
> +           if (!inserted_single_step_breakpoint_p ())

Isn't this naming stale?  I thought you had renamed this.

> +             gdbarch_software_single_step (gdbarch, get_current_frame ());
> +           record_beneath_to_resume (record_beneath_to_resume_ops,
> +                                     ptid, step, signal);
> +           record_resume_step = 0;
> +         }
> +       else
> +         record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
> +                                   signal);
>      }
> 

You've got the predicates a bit mixed up.

 - gdbarch_software_single_step_p purpose is only "is there or
   not a gdbarch_software_single_step callback registered in
   this gdbarch"?  It returning true does not mean that
   software single-step should be used for that single-step.

 - gdbarch_software_single_step can return false, meaning,
   no software single-step needs to be used.

This is how stepping over atomic sequences is handled
currently (grep for deal_with_atomic_sequence):
gdbarch_software_single_step_p returns true, but
gdbarch_software_single_step returns false most
of the times.  See also infrun.c:maybe_software_singlestep.

I think you want this:

       if (!step
           && gdbarch_software_single_step_p (gdbarch)
           && !single_step_breakpoints_inserted ()
           && gdbarch_software_single_step (gdbarch, get_current_frame ()))
         record_resume_step = 0;
       else
         record_resume_step = 1;

       record_beneath_to_resume (record_beneath_to_resume_ops, ptid,
                                 record_resume_step, signal);

If `step' is true when record_resume is called, and so is
gdbarch_software_single_step_p, then it must be that infrun.c
already determined that gdbarch_software_single_step returns
false, otherwise, `step' would be false (maybe_software_singlestep).

If `step' is false (the user is requesting a continue), and
no single-step breakpoints are inserted yet, but,
gdbarch_software_single_step returns false, we have ourselves
an arch/target combo that only wants software single-stepping
for atomic sequences, e.g., MIPS (non-linux), or PPC.  If
so, we should force hardware single-step in the target
beneath (set record_resume_step to 1).

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2009-12-24 17:38           ` Pedro Alves
@ 2010-01-04 14:23             ` Hui Zhu
  2010-01-08 16:24               ` Pedro Alves
  0 siblings, 1 reply; 18+ messages in thread
From: Hui Zhu @ 2010-01-04 14:23 UTC (permalink / raw)
  To: Pedro Alves, shuchang zhou
  Cc: gdb-patches, Joel Brobecker, Michael Snyder, paawan oza, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 4587 bytes --]

Sorry guys, the prev patch is so ugly.

Thanks for teach me clear about the gdbarch_software_single_step, Pedro.
I did some extend with your idea.  Because record_wait need
record_resume_step point out this resume is signal step or continue.

      if (!step)
        {
          /* This is not hard single step.  */
          if (!gdbarch_software_single_step_p (gdbarch))
            {
              /* This is a normal continue.  */
              step = 1;
            }
          else
            {
              /* This arch support soft sigle step.  */
              if (single_step_breakpoints_inserted ())
                {
                  /* This is a soft single step.  */
                  record_resume_step = 1;
                }
              else
                {
                  /* This is a continue.
                     Try to insert a soft single step breakpoint.  */
                  if (!gdbarch_software_single_step (gdbarch,
                                                     get_current_frame ()))
                    {
                      /* This system don't want use soft single step.
                         Use hard sigle step.  */
                      step = 1;
                    }
                }
            }
        }

Shuchuang, please help me try this patch.  Thanks.

Best regards,
Hui


2010-01-04  Hui Zhu  <teawater@gmail.com>

	* breakpoint.c (single_step_breakpoints_inserted): New
	function.
	* breakpoint.h (single_step_breakpoints_inserted): Extern.
	* record.c (record_resume): Add code for software single step.
	(record_wait): Ditto.

On Fri, Dec 25, 2009 at 01:38, Pedro Alves <pedro@codesourcery.com> wrote:
> On Wednesday 23 December 2009 09:23:21, Hui Zhu wrote:
>> +      struct gdbarch *gdbarch = target_thread_architecture (ptid);
>> +
>>        record_message (get_current_regcache (), signal);
>
>>        record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
>>                                  signal);
>
> Why is this resume call still present?
>
>> +
>> +       if (gdbarch_software_single_step_p (gdbarch))
>> +         {
>> +           if (!inserted_single_step_breakpoint_p ())
>
> Isn't this naming stale?  I thought you had renamed this.
>
>> +             gdbarch_software_single_step (gdbarch, get_current_frame ());
>> +           record_beneath_to_resume (record_beneath_to_resume_ops,
>> +                                     ptid, step, signal);
>> +           record_resume_step = 0;
>> +         }
>> +       else
>> +         record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
>> +                                   signal);
>>      }
>>
>
> You've got the predicates a bit mixed up.
>
>  - gdbarch_software_single_step_p purpose is only "is there or
>   not a gdbarch_software_single_step callback registered in
>   this gdbarch"?  It returning true does not mean that
>   software single-step should be used for that single-step.
>
>  - gdbarch_software_single_step can return false, meaning,
>   no software single-step needs to be used.
>
> This is how stepping over atomic sequences is handled
> currently (grep for deal_with_atomic_sequence):
> gdbarch_software_single_step_p returns true, but
> gdbarch_software_single_step returns false most
> of the times.  See also infrun.c:maybe_software_singlestep.
>
> I think you want this:
>
>       if (!step
>           && gdbarch_software_single_step_p (gdbarch)
>           && !single_step_breakpoints_inserted ()
>           && gdbarch_software_single_step (gdbarch, get_current_frame ()))
>         record_resume_step = 0;
>       else
>         record_resume_step = 1;
>
>       record_beneath_to_resume (record_beneath_to_resume_ops, ptid,
>                                 record_resume_step, signal);
>
> If `step' is true when record_resume is called, and so is
> gdbarch_software_single_step_p, then it must be that infrun.c
> already determined that gdbarch_software_single_step returns
> false, otherwise, `step' would be false (maybe_software_singlestep).
>
> If `step' is false (the user is requesting a continue), and
> no single-step breakpoints are inserted yet, but,
> gdbarch_software_single_step returns false, we have ourselves
> an arch/target combo that only wants software single-stepping
> for atomic sequences, e.g., MIPS (non-linux), or PPC.  If
> so, we should force hardware single-step in the target
> beneath (set record_resume_step to 1).
>
> --
> Pedro Alves
>

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 4105 bytes --]

---
 breakpoint.c |   10 ++++++++++
 breakpoint.h |    1 +
 record.c     |   51 ++++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 59 insertions(+), 3 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -9646,6 +9646,16 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -944,6 +944,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -1002,9 +1002,43 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (!step)
+        {
+          /* This is not hard single step.  */
+          if (!gdbarch_software_single_step_p (gdbarch))
+            {
+              /* This is a normal continue.  */
+              step = 1;
+            }
+          else
+            {
+              /* This arch support soft sigle step.  */
+              if (single_step_breakpoints_inserted ())
+                {
+                  /* This is a soft single step.  */
+                  record_resume_step = 1;
+                }
+              else
+                {
+                  /* This is a continue.
+                     Try to insert a soft single step breakpoint.  */
+                  if (!gdbarch_software_single_step (gdbarch,
+                                                     get_current_frame ()))
+                    {
+                      /* This system don't want use soft single step.
+                         Use hard sigle step.  */
+                      step = 1;
+                    }
+                }
+            }
+        }
+
+      record_beneath_to_resume (record_beneath_to_resume_ops,
+                                ptid, step, signal);
     }
 }
 
@@ -1077,6 +1111,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
@@ -1099,6 +1134,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (gdbarch_software_single_step_p (gdbarch))
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1121,6 +1159,8 @@ record_wait (struct target_ops *ops,
 		    {
 		      /* This must be a single-step trap.  Record the
 		         insn and issue another step.  */
+                      int step = 1;
+
 		      if (!record_message_wrapper_safe (regcache,
                                                         TARGET_SIGNAL_0))
   			{
@@ -1129,8 +1169,13 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
+                      if (gdbarch_software_single_step_p (gdbarch)
+                          && gdbarch_software_single_step (gdbarch,
+                                                           get_current_frame ()))
+                        step = 0;
+
 		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
+						ptid, step,
 						TARGET_SIGNAL_0);
 		      continue;
 		    }

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-01-04 14:23             ` Hui Zhu
@ 2010-01-08 16:24               ` Pedro Alves
  2010-05-25  5:14                 ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Pedro Alves @ 2010-01-08 16:24 UTC (permalink / raw)
  To: Hui Zhu
  Cc: shuchang zhou, gdb-patches, Joel Brobecker, Michael Snyder,
	paawan oza, Tom Tromey

On Monday 04 January 2010 14:23:21, Hui Zhu wrote:
> Sorry guys, the prev patch is so ugly.

:-)

> Thanks for teach me clear about the gdbarch_software_single_step, Pedro.
> I did some extend with your idea.  Because record_wait need
> record_resume_step point out this resume is signal step or continue.
> 
>       if (!step)
>         {
>           /* This is not hard single step.  */
>           if (!gdbarch_software_single_step_p (gdbarch))
>             {
>               /* This is a normal continue.  */
>               step = 1;
>             }
>           else
>             {
>               /* This arch support soft sigle step.  */
>               if (single_step_breakpoints_inserted ())
>                 {
>                   /* This is a soft single step.  */
>                   record_resume_step = 1;
>                 }
>               else
>                 {
>                   /* This is a continue.
>                      Try to insert a soft single step breakpoint.  */
>                   if (!gdbarch_software_single_step (gdbarch,
>                                                      get_current_frame ()))
>                     {
>                       /* This system don't want use soft single step.
>                          Use hard sigle step.  */
>                       step = 1;
>                     }
>                 }
>             }
>         }

Cool, this looks pretty clear to me now.  Thanks.



> @@ -1077,6 +1111,7 @@ record_wait (struct target_ops *ops,
>           /* This is not a single step.  */
>           ptid_t ret;
>           CORE_ADDR tmp_pc;
> +          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
>  
>           while (1)
>             {
> @@ -1099,6 +1134,9 @@ record_wait (struct target_ops *ops,
>                   tmp_pc = regcache_read_pc (regcache);
>                   aspace = get_regcache_aspace (regcache);
>  
> +                  if (gdbarch_software_single_step_p (gdbarch))
> +                    remove_single_step_breakpoints ();

This will gdb_assert inside remove_single_step_breakpoints
if SSS bkpts are not inserted, but gdbarch_software_single_step_p
returns true.  This instead is safer:

                  if (single_step_breakpoints_inserted ())
                    remove_single_step_breakpoints ();

But, what if it was infrun that had inserted the single-step
breakpoints, for a "next" or "step", etc.?  Shouldn't you check
for record_resume_step too?

               if (!record_resume_step && single_step_breakpoints_inserted ())
                 remove_single_step_breakpoints ();

Otherwise, the check below for 

		  else if (breakpoint_inserted_here_p (aspace, tmp_pc))
		    {
		      /* There is a breakpoint here.  Let the core
			 handle it.  */
		      if (software_breakpoint_inserted_here_p (aspace, tmp_pc))
			{

would fail, and the finished single-step wouldn't be reported to the
core, right?


Lastly, you may also want to confirm that the SSS bkpt managed by record.d itself explains the SIGTRAP before removing before issueing another
single-step.  If any unexplainable SIGTRAP happens for any reason while
single-stepping, you should report it to infrun instead.  In other words:

With software single-stepping, we can distinguish most random 
SIGTRAPs from SSS SIGTRAPs, so:

		      /* This must be a single-step trap.  Record the
		         insn and issue another step.  */

... the "must" here ends up being a bit too strong.  I'd certainly
understand ignoring this for simplicity or performance reasons though.

Otherwise, looks good to me.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-01-08 16:24               ` Pedro Alves
@ 2010-05-25  5:14                 ` Hui Zhu
  2010-05-27  6:51                   ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Hui Zhu @ 2010-05-25  5:14 UTC (permalink / raw)
  To: Pedro Alves, ping huang, shuchang zhou
  Cc: gdb-patches, Joel Brobecker, Michael Snyder, paawan oza, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 5109 bytes --]

Thanks Pedro.

On Sat, Jan 9, 2010 at 00:24, Pedro Alves <pedro@codesourcery.com> wrote:
> On Monday 04 January 2010 14:23:21, Hui Zhu wrote:
>> Sorry guys, the prev patch is so ugly.
>
> :-)
>
>> Thanks for teach me clear about the gdbarch_software_single_step, Pedro.
>> I did some extend with your idea.  Because record_wait need
>> record_resume_step point out this resume is signal step or continue.
>>
>>       if (!step)
>>         {
>>           /* This is not hard single step.  */
>>           if (!gdbarch_software_single_step_p (gdbarch))
>>             {
>>               /* This is a normal continue.  */
>>               step = 1;
>>             }
>>           else
>>             {
>>               /* This arch support soft sigle step.  */
>>               if (single_step_breakpoints_inserted ())
>>                 {
>>                   /* This is a soft single step.  */
>>                   record_resume_step = 1;
>>                 }
>>               else
>>                 {
>>                   /* This is a continue.
>>                      Try to insert a soft single step breakpoint.  */
>>                   if (!gdbarch_software_single_step (gdbarch,
>>                                                      get_current_frame ()))
>>                     {
>>                       /* This system don't want use soft single step.
>>                          Use hard sigle step.  */
>>                       step = 1;
>>                     }
>>                 }
>>             }
>>         }
>
> Cool, this looks pretty clear to me now.  Thanks.
>
>
>
>> @@ -1077,6 +1111,7 @@ record_wait (struct target_ops *ops,
>>           /* This is not a single step.  */
>>           ptid_t ret;
>>           CORE_ADDR tmp_pc;
>> +          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
>>
>>           while (1)
>>             {
>> @@ -1099,6 +1134,9 @@ record_wait (struct target_ops *ops,
>>                   tmp_pc = regcache_read_pc (regcache);
>>                   aspace = get_regcache_aspace (regcache);
>>
>> +                  if (gdbarch_software_single_step_p (gdbarch))
>> +                    remove_single_step_breakpoints ();
>
> This will gdb_assert inside remove_single_step_breakpoints
> if SSS bkpts are not inserted, but gdbarch_software_single_step_p
> returns true.  This instead is safer:
>
>                  if (single_step_breakpoints_inserted ())
>                    remove_single_step_breakpoints ();

OK.  I will fix it.

>
> But, what if it was infrun that had inserted the single-step
> breakpoints, for a "next" or "step", etc.?  Shouldn't you check
> for record_resume_step too?
>
>               if (!record_resume_step && single_step_breakpoints_inserted ())
>                 remove_single_step_breakpoints ();
>
> Otherwise, the check below for
>
>                  else if (breakpoint_inserted_here_p (aspace, tmp_pc))
>                    {
>                      /* There is a breakpoint here.  Let the core
>                         handle it.  */
>                      if (software_breakpoint_inserted_here_p (aspace, tmp_pc))
>                        {
>
> would fail, and the finished single-step wouldn't be reported to the
> core, right?

I think this single step will be handle by line:
      if (record_resume_step)
	{
	  /* This is a single step.  */
	  return record_beneath_to_wait (record_beneath_to_wait_ops,
					 ptid, status, options);
	}

>
>
> Lastly, you may also want to confirm that the SSS bkpt managed by record.d itself explains the SIGTRAP before removing before issueing another
> single-step.  If any unexplainable SIGTRAP happens for any reason while
> single-stepping, you should report it to infrun instead.  In other words:
>
> With software single-stepping, we can distinguish most random
> SIGTRAPs from SSS SIGTRAPs, so:
>
>                      /* This must be a single-step trap.  Record the
>                         insn and issue another step.  */
>
> ... the "must" here ends up being a bit too strong.  I'd certainly
> understand ignoring this for simplicity or performance reasons though.

Ah.  Looks we didn't have good way to handle it.  I change this comment to:
		      /* This is a single-step trap.  Record the
		         insn and issue another step.
                         FIXME: this part can be a random SIGTRAP too.
                         But GDB cannot handle it.  */


Shuchang,  could you try your code just use command si and
reverse-xxx.  If that part OK.  Please help me try this patch.

Ping, please help me test this patch.  And about hellogcc, you can find us in:
https://groups.google.com/group/hellogcc
https://webchat.freenode.net/ #hellogcc

Thanks,
Hui

2010-05-25  Hui Zhu  <teawater@gmail.com>

	* breakpoint.c (single_step_breakpoints_inserted): New
	function.
	* breakpoint.h (single_step_breakpoints_inserted): Extern.
	* record.c (record_resume): Add code for software single step.
	(record_wait): Ditto.

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 4349 bytes --]

---
 breakpoint.c |   10 ++++++++++
 breakpoint.h |    1 +
 record.c     |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 63 insertions(+), 5 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -10293,6 +10293,16 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -983,6 +983,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/record.c
+++ b/record.c
@@ -1007,9 +1007,43 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (!step)
+        {
+          /* This is not hard single step.  */
+          if (!gdbarch_software_single_step_p (gdbarch))
+            {
+              /* This is a normal continue.  */
+              step = 1;
+            }
+          else
+            {
+              /* This arch support soft sigle step.  */
+              if (single_step_breakpoints_inserted ())
+                {
+                  /* This is a soft single step.  */
+                  record_resume_step = 1;
+                }
+              else
+                {
+                  /* This is a continue.
+                     Try to insert a soft single step breakpoint.  */
+                  if (!gdbarch_software_single_step (gdbarch,
+                                                     get_current_frame ()))
+                    {
+                      /* This system don't want use soft single step.
+                         Use hard sigle step.  */
+                      step = 1;
+                    }
+                }
+            }
+        }
+
+      record_beneath_to_resume (record_beneath_to_resume_ops,
+                                ptid, step, signal);
     }
 }
 
@@ -1082,6 +1116,7 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
@@ -1104,6 +1139,9 @@ record_wait (struct target_ops *ops,
 		  tmp_pc = regcache_read_pc (regcache);
 		  aspace = get_regcache_aspace (regcache);
 
+                  if (single_step_breakpoints_inserted ())
+                    remove_single_step_breakpoints ();
+
 		  if (target_stopped_by_watchpoint ())
 		    {
 		      /* Always interested in watchpoints.  */
@@ -1124,8 +1162,12 @@ record_wait (struct target_ops *ops,
 		    }
 		  else
 		    {
-		      /* This must be a single-step trap.  Record the
-		         insn and issue another step.  */
+		      /* This is a single-step trap.  Record the
+		         insn and issue another step.
+                         FIXME: this part can be a random SIGTRAP too.
+                         But GDB cannot handle it.  */
+                      int step = 1;
+
 		      if (!record_message_wrapper_safe (regcache,
                                                         TARGET_SIGNAL_0))
   			{
@@ -1134,8 +1176,13 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
+                      if (gdbarch_software_single_step_p (gdbarch)
+                          && gdbarch_software_single_step (gdbarch,
+                                                           get_current_frame ()))
+                        step = 0;
+
 		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
+						ptid, step,
 						TARGET_SIGNAL_0);
 		      continue;
 		    }

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-05-25  5:14                 ` Hui Zhu
@ 2010-05-27  6:51                   ` Hui Zhu
  2010-06-11 13:55                     ` Pedro Alves
  0 siblings, 1 reply; 18+ messages in thread
From: Hui Zhu @ 2010-05-27  6:51 UTC (permalink / raw)
  To: Pedro Alves, ping huang, shuchang zhou
  Cc: gdb-patches, Joel Brobecker, Michael Snyder, paawan oza, Tom Tromey

[-- Attachment #1: Type: text/plain, Size: 7361 bytes --]

On Tue, May 25, 2010 at 11:04, Hui Zhu <teawater@gmail.com> wrote:
> Thanks Pedro.
>
> On Sat, Jan 9, 2010 at 00:24, Pedro Alves <pedro@codesourcery.com> wrote:
>> On Monday 04 January 2010 14:23:21, Hui Zhu wrote:
>>> Sorry guys, the prev patch is so ugly.
>>
>> :-)
>>
>>> Thanks for teach me clear about the gdbarch_software_single_step, Pedro.
>>> I did some extend with your idea.  Because record_wait need
>>> record_resume_step point out this resume is signal step or continue.
>>>
>>>       if (!step)
>>>         {
>>>           /* This is not hard single step.  */
>>>           if (!gdbarch_software_single_step_p (gdbarch))
>>>             {
>>>               /* This is a normal continue.  */
>>>               step = 1;
>>>             }
>>>           else
>>>             {
>>>               /* This arch support soft sigle step.  */
>>>               if (single_step_breakpoints_inserted ())
>>>                 {
>>>                   /* This is a soft single step.  */
>>>                   record_resume_step = 1;
>>>                 }
>>>               else
>>>                 {
>>>                   /* This is a continue.
>>>                      Try to insert a soft single step breakpoint.  */
>>>                   if (!gdbarch_software_single_step (gdbarch,
>>>                                                      get_current_frame ()))
>>>                     {
>>>                       /* This system don't want use soft single step.
>>>                          Use hard sigle step.  */
>>>                       step = 1;
>>>                     }
>>>                 }
>>>             }
>>>         }
>>
>> Cool, this looks pretty clear to me now.  Thanks.
>>
>>
>>
>>> @@ -1077,6 +1111,7 @@ record_wait (struct target_ops *ops,
>>>           /* This is not a single step.  */
>>>           ptid_t ret;
>>>           CORE_ADDR tmp_pc;
>>> +          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
>>>
>>>           while (1)
>>>             {
>>> @@ -1099,6 +1134,9 @@ record_wait (struct target_ops *ops,
>>>                   tmp_pc = regcache_read_pc (regcache);
>>>                   aspace = get_regcache_aspace (regcache);
>>>
>>> +                  if (gdbarch_software_single_step_p (gdbarch))
>>> +                    remove_single_step_breakpoints ();
>>
>> This will gdb_assert inside remove_single_step_breakpoints
>> if SSS bkpts are not inserted, but gdbarch_software_single_step_p
>> returns true.  This instead is safer:
>>
>>                  if (single_step_breakpoints_inserted ())
>>                    remove_single_step_breakpoints ();
>
> OK.  I will fix it.
>
>>
>> But, what if it was infrun that had inserted the single-step
>> breakpoints, for a "next" or "step", etc.?  Shouldn't you check
>> for record_resume_step too?
>>
>>               if (!record_resume_step && single_step_breakpoints_inserted ())
>>                 remove_single_step_breakpoints ();
>>
>> Otherwise, the check below for
>>
>>                  else if (breakpoint_inserted_here_p (aspace, tmp_pc))
>>                    {
>>                      /* There is a breakpoint here.  Let the core
>>                         handle it.  */
>>                      if (software_breakpoint_inserted_here_p (aspace, tmp_pc))
>>                        {
>>
>> would fail, and the finished single-step wouldn't be reported to the
>> core, right?
>
> I think this single step will be handle by line:
>      if (record_resume_step)
>        {
>          /* This is a single step.  */
>          return record_beneath_to_wait (record_beneath_to_wait_ops,
>                                         ptid, status, options);
>        }
>
>>
>>
>> Lastly, you may also want to confirm that the SSS bkpt managed by record.d itself explains the SIGTRAP before removing before issueing another
>> single-step.  If any unexplainable SIGTRAP happens for any reason while
>> single-stepping, you should report it to infrun instead.  In other words:
>>
>> With software single-stepping, we can distinguish most random
>> SIGTRAPs from SSS SIGTRAPs, so:
>>
>>                      /* This must be a single-step trap.  Record the
>>                         insn and issue another step.  */
>>
>> ... the "must" here ends up being a bit too strong.  I'd certainly
>> understand ignoring this for simplicity or performance reasons though.
>
> Ah.  Looks we didn't have good way to handle it.  I change this comment to:
>                      /* This is a single-step trap.  Record the
>                         insn and issue another step.
>                         FIXME: this part can be a random SIGTRAP too.
>                         But GDB cannot handle it.  */
>
>
> Shuchang,  could you try your code just use command si and
> reverse-xxx.  If that part OK.  Please help me try this patch.
>
> Ping, please help me test this patch.  And about hellogcc, you can find us in:
> https://groups.google.com/group/hellogcc
> https://webchat.freenode.net/ #hellogcc
>
> Thanks,
> Hui
>
> 2010-05-25  Hui Zhu  <teawater@gmail.com>
>
>        * breakpoint.c (single_step_breakpoints_inserted): New
>        function.
>        * breakpoint.h (single_step_breakpoints_inserted): Extern.
>        * record.c (record_resume): Add code for software single step.
>        (record_wait): Ditto.
>

Hello,

After do some test with Ping, I found some trouble and fixed them.

1.  Add following:
@@ -1134,8 +1176,20 @@ record_wait (struct target_ops *ops,
                            break;
   			}

+                      if (gdbarch_software_single_step_p (gdbarch))
+			{
+			  /* Try to insert the software single step breakpoint.
+			     If insert success, set step to 0.  */
+			  set_executing (inferior_ptid, 0);
+			  reinit_frame_cache ();
+			  if (gdbarch_software_single_step (gdbarch,
+
get_current_frame ()))
+			    step = 0;
+			  set_executing (inferior_ptid, 1);
+			}

This is because in record_wait, we cannot call get_current_frame ()
directly.  And the frame message need refresh each exec cycle.

2.  Ping found that reverse-exec cannot single step in RISC board.
That is because "gdbarch_software_single_step" just can insert the
breakpoint to the next addr.  So I add following:
@@ -1436,7 +1436,8 @@ maybe_software_singlestep (struct gdbarc
 {
   int hw_step = 1;

-  if (gdbarch_software_single_step_p (gdbarch)
+  if (execution_direction == EXEC_FORWARD
+      && gdbarch_software_single_step_p (gdbarch)
       && gdbarch_software_single_step (gdbarch, get_current_frame ()))

If reverse, gdb will not user sss breakpoint to single step.

3.  Ping got some gdb_assert in sometime.  And I am not close to his
board.  So I didn't know what happen.  So I add following:
@@ -1534,7 +1535,8 @@ a command like `return' or `jump' to con
       /* If STEP is set, it's a request to use hardware stepping
 	 facilities.  But in that case, we should never
 	 use singlestep breakpoint.  */
-      gdb_assert (!(singlestep_breakpoints_inserted_p && step));
+      gdb_assert (!(execution_direction == EXEC_FORWARD
+                    && singlestep_breakpoints_inserted_p && step));

The lost one still need be test.

Thanks,
Hui

[-- Attachment #2: prec_software_single_step.txt --]
[-- Type: text/plain, Size: 5450 bytes --]

---
 breakpoint.c |   10 +++++++++
 breakpoint.h |    1 
 infrun.c     |    6 +++--
 record.c     |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 74 insertions(+), 7 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -10293,6 +10293,16 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }
 
+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */
 
 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -983,6 +983,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);
 
 /* Manage manual breakpoints, separate from the normal chain of
--- a/infrun.c
+++ b/infrun.c
@@ -1436,7 +1436,8 @@ maybe_software_singlestep (struct gdbarc
 {
   int hw_step = 1;
 
-  if (gdbarch_software_single_step_p (gdbarch)
+  if (execution_direction == EXEC_FORWARD
+      && gdbarch_software_single_step_p (gdbarch)
       && gdbarch_software_single_step (gdbarch, get_current_frame ()))
     {
       hw_step = 0;
@@ -1534,7 +1535,8 @@ a command like `return' or `jump' to con
       /* If STEP is set, it's a request to use hardware stepping
 	 facilities.  But in that case, we should never
 	 use singlestep breakpoint.  */
-      gdb_assert (!(singlestep_breakpoints_inserted_p && step));
+      gdb_assert (!(execution_direction == EXEC_FORWARD
+                    && singlestep_breakpoints_inserted_p && step));
 
       /* Decide the set of threads to ask the target to resume.  Start
 	 by assuming everything will be resumed, than narrow the set
--- a/record.c
+++ b/record.c
@@ -1007,9 +1007,43 @@ record_resume (struct target_ops *ops, p
 
   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (!step)
+        {
+          /* This is not hard single step.  */
+          if (!gdbarch_software_single_step_p (gdbarch))
+            {
+              /* This is a normal continue.  */
+              step = 1;
+            }
+          else
+            {
+              /* This arch support soft sigle step.  */
+              if (single_step_breakpoints_inserted ())
+                {
+                  /* This is a soft single step.  */
+                  record_resume_step = 1;
+                }
+              else
+                {
+                  /* This is a continue.
+                     Try to insert a soft single step breakpoint.  */
+                  if (!gdbarch_software_single_step (gdbarch,
+                                                     get_current_frame ()))
+                    {
+                      /* This system don't want use soft single step.
+                         Use hard sigle step.  */
+                      step = 1;
+                    }
+                }
+            }
+        }
+
+      record_beneath_to_resume (record_beneath_to_resume_ops,
+                                ptid, step, signal);
     }
 }
 
@@ -1082,12 +1116,16 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+          struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);
 
 	  while (1)
 	    {
 	      ret = record_beneath_to_wait (record_beneath_to_wait_ops,
 					    ptid, status, options);
 
+              if (single_step_breakpoints_inserted ())
+                remove_single_step_breakpoints ();
+
 	      /* Is this a SIGTRAP?  */
 	      if (status->kind == TARGET_WAITKIND_STOPPED
 		  && status->value.sig == TARGET_SIGNAL_TRAP)
@@ -1124,8 +1162,12 @@ record_wait (struct target_ops *ops,
 		    }
 		  else
 		    {
-		      /* This must be a single-step trap.  Record the
-		         insn and issue another step.  */
+		      /* This is a single-step trap.  Record the
+		         insn and issue another step.
+                         FIXME: this part can be a random SIGTRAP too.
+                         But GDB cannot handle it.  */
+                      int step = 1;
+
 		      if (!record_message_wrapper_safe (regcache,
                                                         TARGET_SIGNAL_0))
   			{
@@ -1134,8 +1176,20 @@ record_wait (struct target_ops *ops,
                            break;
   			}
 
+                      if (gdbarch_software_single_step_p (gdbarch))
+			{
+			  /* Try to insert the software single step breakpoint.
+			     If insert success, set step to 0.  */
+			  set_executing (inferior_ptid, 0);
+			  reinit_frame_cache ();
+			  if (gdbarch_software_single_step (gdbarch,
+                                                            get_current_frame ()))
+			    step = 0;
+			  set_executing (inferior_ptid, 1);
+			}
+
 		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
+						ptid, step,
 						TARGET_SIGNAL_0);
 		      continue;
 		    }

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-05-27  6:51                   ` Hui Zhu
@ 2010-06-11 13:55                     ` Pedro Alves
  2010-06-20  7:29                       ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Pedro Alves @ 2010-06-11 13:55 UTC (permalink / raw)
  To: Hui Zhu
  Cc: ping huang, shuchang zhou, gdb-patches, Joel Brobecker,
	Michael Snyder, paawan oza, Tom Tromey

Hi Hui,

> 3.  Ping got some gdb_assert in sometime.  And I am not close to his
> board.  So I didn't know what happen.  So I add following:
> @@ -1534,7 +1535,8 @@ a command like `return' or `jump' to con
>        /* If STEP is set, it's a request to use hardware stepping
>  	 facilities.  But in that case, we should never
>  	 use singlestep breakpoint.  */
> -      gdb_assert (!(singlestep_breakpoints_inserted_p && step));
> +      gdb_assert (!(execution_direction == EXEC_FORWARD
> +                    && singlestep_breakpoints_inserted_p && step));
> 
> The lost one still need be test.

I'm felling a bit dense, and I don't see what is that actually
catching.  If going backwards, the assertion always ends up
evaled as true, nomatter if sofware single-steps are inserted
or not, or whether `step' is set.  Did you mean to assert
that when going backwards, there shouldn't ever be software
single-step breakpoints inserted?

This patch is okay otherwise.  Thanks.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-06-11 13:55                     ` Pedro Alves
@ 2010-06-20  7:29                       ` Hui Zhu
  2010-06-22 10:13                         ` Pedro Alves
  0 siblings, 1 reply; 18+ messages in thread
From: Hui Zhu @ 2010-06-20  7:29 UTC (permalink / raw)
  To: Pedro Alves
  Cc: ping huang, shuchang zhou, gdb-patches, Joel Brobecker,
	Michael Snyder, paawan oza, Tom Tromey

On Fri, Jun 11, 2010 at 21:55, Pedro Alves <pedro@codesourcery.com> wrote:
> Hi Hui,
>
>> 3.  Ping got some gdb_assert in sometime.  And I am not close to his
>> board.  So I didn't know what happen.  So I add following:
>> @@ -1534,7 +1535,8 @@ a command like `return' or `jump' to con
>>        /* If STEP is set, it's a request to use hardware stepping
>>        facilities.  But in that case, we should never
>>        use singlestep breakpoint.  */
>> -      gdb_assert (!(singlestep_breakpoints_inserted_p && step));
>> +      gdb_assert (!(execution_direction == EXEC_FORWARD
>> +                    && singlestep_breakpoints_inserted_p && step));
>>
>> The lost one still need be test.
>
> I'm felling a bit dense, and I don't see what is that actually
> catching.  If going backwards, the assertion always ends up
> evaled as true, nomatter if sofware single-steps are inserted
> or not, or whether `step' is set.  Did you mean to assert
> that when going backwards, there shouldn't ever be software
> single-step breakpoints inserted?
>
> This patch is okay otherwise.  Thanks.
>
> --

Thanks Pedro.
I was also confused by this issue too.  I thought it will never happen
too.  But Ping said he got this issue.  And I didn't have the risc
board to test.  So I gived up and put this patch to him.

So I think this patch is not very hurry to checked in until some one
post a risc prec support patch.  At that time, I will make this issue
clear.

Best regards,
Hui


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-06-20  7:29                       ` Hui Zhu
@ 2010-06-22 10:13                         ` Pedro Alves
  2010-07-19  7:58                           ` Hui Zhu
  0 siblings, 1 reply; 18+ messages in thread
From: Pedro Alves @ 2010-06-22 10:13 UTC (permalink / raw)
  To: Hui Zhu
  Cc: ping huang, shuchang zhou, gdb-patches, Joel Brobecker,
	Michael Snyder, paawan oza, Tom Tromey

Hi Hui,

On Sunday 20 June 2010 08:28:40, Hui Zhu wrote:
> On Fri, Jun 11, 2010 at 21:55, Pedro Alves <pedro@codesourcery.com> wrote:
> > I'm felling a bit dense, and I don't see what is that actually
> > catching.  If going backwards, the assertion always ends up
> > evaled as true, nomatter if sofware single-steps are inserted
> > or not, or whether `step' is set.  Did you mean to assert
> > that when going backwards, there shouldn't ever be software
> > single-step breakpoints inserted?
> >
> > This patch is okay otherwise.  Thanks.
> 
> Thanks Pedro.
> I was also confused by this issue too.  I thought it will never happen
> too.  But Ping said he got this issue.  And I didn't have the risc
> board to test.  So I gived up and put this patch to him.
> 
> So I think this patch is not very hurry to checked in until some one
> post a risc prec support patch.  At that time, I will make this issue
> clear.

I'd be fine with putting the patch in now, but without the change to
that gdb_assert.  It looked like a step in the right direction,
and we can fix any left issues later.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [RFC] Add support of software single step to process record
  2010-06-22 10:13                         ` Pedro Alves
@ 2010-07-19  7:58                           ` Hui Zhu
  0 siblings, 0 replies; 18+ messages in thread
From: Hui Zhu @ 2010-07-19  7:58 UTC (permalink / raw)
  To: Pedro Alves
  Cc: ping huang, shuchang zhou, gdb-patches, Joel Brobecker,
	Michael Snyder, paawan oza, Tom Tromey

On Tue, Jun 22, 2010 at 18:12, Pedro Alves <pedro@codesourcery.com> wrote:
> Hi Hui,
>
> On Sunday 20 June 2010 08:28:40, Hui Zhu wrote:
>> On Fri, Jun 11, 2010 at 21:55, Pedro Alves <pedro@codesourcery.com> wrote:
>> > I'm felling a bit dense, and I don't see what is that actually
>> > catching.  If going backwards, the assertion always ends up
>> > evaled as true, nomatter if sofware single-steps are inserted
>> > or not, or whether `step' is set.  Did you mean to assert
>> > that when going backwards, there shouldn't ever be software
>> > single-step breakpoints inserted?
>> >
>> > This patch is okay otherwise.  Thanks.
>>
>> Thanks Pedro.
>> I was also confused by this issue too.  I thought it will never happen
>> too.  But Ping said he got this issue.  And I didn't have the risc
>> board to test.  So I gived up and put this patch to him.
>>
>> So I think this patch is not very hurry to checked in until some one
>> post a risc prec support patch.  At that time, I will make this issue
>> clear.
>
> I'd be fine with putting the patch in now, but without the change to
> that gdb_assert.  It looked like a step in the right direction,
> and we can fix any left issues later.
>
> --
> Pedro Alves
>

Agree with you.
I delay this patch some days because I want make it check in after 7.2.

Now, following patch checked in.

Thanks,
Hui

2010-07-19  Hui Zhu  <teawater@gmail.com>

	* breakpoint.c (single_step_breakpoints_inserted): New
	function.
	* breakpoint.h (single_step_breakpoints_inserted): Extern.
	* infrun.c (maybe_software_singlestep): Add check code.
	* record.c (record_resume): Add code for software single step.
	(record_wait): Ditto.


---
 breakpoint.c |   10 +++++++++
 breakpoint.h |    1
 infrun.c     |    3 +-
 record.c     |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 72 insertions(+), 6 deletions(-)

--- a/breakpoint.c
+++ b/breakpoint.c
@@ -10468,6 +10468,16 @@ insert_single_step_breakpoint (struct gd
 	     paddress (gdbarch, next_pc));
 }

+/* Check if the breakpoints used for software single stepping
+   were inserted or not.  */
+
+int
+single_step_breakpoints_inserted (void)
+{
+  return (single_step_breakpoints[0] != NULL
+          || single_step_breakpoints[1] != NULL);
+}
+
 /* Remove and delete any breakpoints used for software single step.  */

 void
--- a/breakpoint.h
+++ b/breakpoint.h
@@ -984,6 +984,7 @@ extern int remove_hw_watchpoints (void);
    twice before remove is called.  */
 extern void insert_single_step_breakpoint (struct gdbarch *,
 					   struct address_space *, CORE_ADDR);
+extern int single_step_breakpoints_inserted (void);
 extern void remove_single_step_breakpoints (void);

 /* Manage manual breakpoints, separate from the normal chain of
--- a/infrun.c
+++ b/infrun.c
@@ -1515,7 +1515,8 @@ maybe_software_singlestep (struct gdbarc
 {
   int hw_step = 1;

-  if (gdbarch_software_single_step_p (gdbarch)
+  if (execution_direction == EXEC_FORWARD
+      && gdbarch_software_single_step_p (gdbarch)
       && gdbarch_software_single_step (gdbarch, get_current_frame ()))
     {
       hw_step = 0;
--- a/record.c
+++ b/record.c
@@ -1011,9 +1011,43 @@ record_resume (struct target_ops *ops, p

   if (!RECORD_IS_REPLAY)
     {
+      struct gdbarch *gdbarch = target_thread_architecture (ptid);
+
       record_message (get_current_regcache (), signal);
-      record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
-                                signal);
+
+      if (!step)
+        {
+          /* This is not hard single step.  */
+          if (!gdbarch_software_single_step_p (gdbarch))
+            {
+              /* This is a normal continue.  */
+              step = 1;
+            }
+          else
+            {
+              /* This arch support soft sigle step.  */
+              if (single_step_breakpoints_inserted ())
+                {
+                  /* This is a soft single step.  */
+                  record_resume_step = 1;
+                }
+              else
+                {
+                  /* This is a continue.
+                     Try to insert a soft single step breakpoint.  */
+                  if (!gdbarch_software_single_step (gdbarch,
+                                                     get_current_frame ()))
+                    {
+                      /* This system don't want use soft single step.
+                         Use hard sigle step.  */
+                      step = 1;
+                    }
+                }
+            }
+        }
+
+      record_beneath_to_resume (record_beneath_to_resume_ops,
+                                ptid, step, signal);
     }
 }

@@ -1089,12 +1123,16 @@ record_wait (struct target_ops *ops,
 	  /* This is not a single step.  */
 	  ptid_t ret;
 	  CORE_ADDR tmp_pc;
+	  struct gdbarch *gdbarch = target_thread_architecture (inferior_ptid);

 	  while (1)
 	    {
 	      ret = record_beneath_to_wait (record_beneath_to_wait_ops,
 					    ptid, status, options);

+              if (single_step_breakpoints_inserted ())
+                remove_single_step_breakpoints ();
+
 	      if (record_resume_step)
 	        return ret;

@@ -1134,8 +1172,12 @@ record_wait (struct target_ops *ops,
 		    }
 		  else
 		    {
-		      /* This must be a single-step trap.  Record the
-		         insn and issue another step.  */
+		      /* This is a single-step trap.  Record the
+		         insn and issue another step.
+                         FIXME: this part can be a random SIGTRAP too.
+                         But GDB cannot handle it.  */
+                      int step = 1;
+
 		      if (!record_message_wrapper_safe (regcache,
                                                         TARGET_SIGNAL_0))
   			{
@@ -1144,8 +1186,20 @@ record_wait (struct target_ops *ops,
                            break;
   			}

+                      if (gdbarch_software_single_step_p (gdbarch))
+			{
+			  /* Try to insert the software single step breakpoint.
+			     If insert success, set step to 0.  */
+			  set_executing (inferior_ptid, 0);
+			  reinit_frame_cache ();
+			  if (gdbarch_software_single_step (gdbarch,
+
get_current_frame ()))
+			    step = 0;
+			  set_executing (inferior_ptid, 1);
+			}
+
 		      record_beneath_to_resume (record_beneath_to_resume_ops,
-						ptid, 1,
+						ptid, step,
 						TARGET_SIGNAL_0);
 		      continue;
 		    }


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2010-07-19  7:58 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-18  8:21 [RFC] Add support of software single step to process record Hui Zhu
2009-12-18 19:37 ` Michael Snyder
2009-12-20 13:48   ` Joel Brobecker
2009-12-23  6:38     ` Hui Zhu
2009-12-23  6:52       ` Joel Brobecker
2009-12-23  9:24         ` Hui Zhu
     [not found]           ` <8d62b6fe0912231751p1202294cw83430e8d53af0951@mail.gmail.com>
2009-12-24  1:54             ` Fwd: " shuchang zhou
2009-12-24 17:38           ` Pedro Alves
2010-01-04 14:23             ` Hui Zhu
2010-01-08 16:24               ` Pedro Alves
2010-05-25  5:14                 ` Hui Zhu
2010-05-27  6:51                   ` Hui Zhu
2010-06-11 13:55                     ` Pedro Alves
2010-06-20  7:29                       ` Hui Zhu
2010-06-22 10:13                         ` Pedro Alves
2010-07-19  7:58                           ` Hui Zhu
2009-12-22 18:23 ` Tom Tromey
2009-12-23  3:09   ` Hui Zhu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox