public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
@ 2010-08-24  6:39 Yao Qi
  2010-08-24 11:28 ` Mark Kettenis
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2010-08-24  6:39 UTC (permalink / raw)
  To: gdb-patches

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

Hi,
This patch is to calculate correct address of 'next pc' of syscall
sigreturn and rt_sigreturn.

Tested on armv7l-unknown-linux-gnueabi, and a diff of test summary is
shown below:

-FAIL: gdb.base/sigstep.exp: step from handler; leave handler(timeout)
+PASS: gdb.base/sigstep.exp: step from handler; leave handler
-FAIL: gdb.base/sigstep.exp: stepi from handleri; leave signal trampoline
+PASS: gdb.base/sigstep.exp: stepi from handleri; leave signal trampoline (in main)
-FAIL: gdb.base/sigstep.exp: next from handler; leave handler (timeout)
+PASS: gdb.base/sigstep.exp: next from handler; leave handler
-FAIL: gdb.base/sigstep.exp: nexti from handleri; leave signal trampoline
+PASS: gdb.base/sigstep.exp: nexti from handleri; leave signal trampoline (in main)

                === gdb Summary ===

-# of expected passes           14664
-# of unexpected failures       314
+# of expected passes           14669
+# of unexpected failures       310

Is that OK?

-- 
Yao Qi
CodeSourcery
yao@codesourcery.com
(650) 331-3385 x739

[-- Attachment #2: nextpc_of_svc.patch --]
[-- Type: text/x-diff, Size: 733 bytes --]

2010-08-24  Yao Qi  <yao@codesourcery.com>

	*arm-tdep.c (arm_get_next_pc_raw): Calculate next pc of sigreturn or
	rt_sigreturn syscall.

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 1ac8817..978bb72 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -3257,7 +3257,18 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
 	case 0xc:
 	case 0xd:
 	case 0xe:		/* coproc ops */
+	  break;
 	case 0xf:		/* SWI */
+	  {
+	    unsigned long svc_number = get_frame_register_unsigned (frame, 7);
+
+	    if (svc_number == 119 || svc_number == 173)
+	      {   
+		if (get_frame_type (frame) == SIGTRAMP_FRAME)
+		  {
+		    nextpc = frame_unwind_caller_pc (frame);
+		  }
+	      }
 	  break;
 
 	default:

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-24  6:39 [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall Yao Qi
@ 2010-08-24 11:28 ` Mark Kettenis
  2010-08-24 14:13   ` Daniel Jacobowitz
  0 siblings, 1 reply; 9+ messages in thread
From: Mark Kettenis @ 2010-08-24 11:28 UTC (permalink / raw)
  To: yao; +Cc: gdb-patches

> Date: Mon, 23 Aug 2010 23:38:54 -0700
> From: Yao Qi <yao@codesourcery.com>
> 
> Hi,
> This patch is to calculate correct address of 'next pc' of syscall
> sigreturn and rt_sigreturn.

You're polluting the genric arm code with Linux-specific stuff.
Please don't do that.  If something like this is needed, it should be
added to code in arm-linux-tdep.c.

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-24 11:28 ` Mark Kettenis
@ 2010-08-24 14:13   ` Daniel Jacobowitz
  2010-08-25  3:06     ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2010-08-24 14:13 UTC (permalink / raw)
  To: Mark Kettenis, Yao Qi; +Cc: gdb-patches

On Tue, Aug 24, 2010 at 01:27:03PM +0200, Mark Kettenis wrote:
> > Date: Mon, 23 Aug 2010 23:38:54 -0700
> > From: Yao Qi <yao@codesourcery.com>
> > 
> > Hi,
> > This patch is to calculate correct address of 'next pc' of syscall
> > sigreturn and rt_sigreturn.
> 
> You're polluting the genric arm code with Linux-specific stuff.
> Please don't do that.  If something like this is needed, it should be
> added to code in arm-linux-tdep.c.

There's a couple of ways to do that; one example is
mips_linux_syscall_next_pc.

-- 
Daniel Jacobowitz
CodeSourcery

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-24 14:13   ` Daniel Jacobowitz
@ 2010-08-25  3:06     ` Yao Qi
  2010-08-25 14:31       ` Daniel Jacobowitz
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2010-08-25  3:06 UTC (permalink / raw)
  To: Mark Kettenis, Daniel Jacobowitz; +Cc: gdb-patches

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

On Tue, Aug 24, 2010 at 10:12:57AM -0400, Daniel Jacobowitz wrote:
> On Tue, Aug 24, 2010 at 01:27:03PM +0200, Mark Kettenis wrote:
> > > Date: Mon, 23 Aug 2010 23:38:54 -0700
> > > From: Yao Qi <yao@codesourcery.com>
> > > 
> > > Hi,
> > > This patch is to calculate correct address of 'next pc' of syscall
> > > sigreturn and rt_sigreturn.
> > 
> > You're polluting the genric arm code with Linux-specific stuff.
> > Please don't do that.  If something like this is needed, it should be
> > added to code in arm-linux-tdep.c.
> 
> There's a couple of ways to do that; one example is
> mips_linux_syscall_next_pc.

Here is the updated patch, in which:
  1.  Add arm_linux_syscall_next_pc, similar to
mips_linux_syscall_next_pc.  Compute the return address of SWI in both
ARM mode and Thumb mode.
  2.  Extract some common code from arm_linux_copy_svc.

Tested on armv7l-unknown-linux-gnueabi again.  Result is the same as
my previous post.

-- 
Yao Qi
CodeSourcery
yao@codesourcery.com
(650) 331-3385 x739

[-- Attachment #2: return_addr_sigreturn.patch --]
[-- Type: text/x-diff, Size: 6256 bytes --]

2010-08-25  Yao Qi  <yao@codesourcery.com>

	* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
	(arm_linux_syscall_next_pc): New.
	(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. 
	(arm_linux_init_abi): Initialize syscall_next_pc.
	* arm-tdep.c (thumb_get_next_pc_raw):  Get next pc of SWI in Thumb mode.
	(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
	* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. 
	Declare arm_frame_is_thumb.


diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 682054c..106cd85 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -630,6 +630,53 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
   return NULL;
 }
 
+/* Get the value of next pc of sigreturn and rt_sigrturn.  Return 0 if it is 
+   not a rt_sigreturn/sigreturn syscall.  */
+static int
+arm_linux_sigreturn_return_addr(struct frame_info *frame,
+				unsigned long svc_number)
+{
+  /* Is this a sigreturn or rt_sigreturn syscall?  Note: these are only useful
+     for EABI.  */
+  if (svc_number == 119 || svc_number == 173)
+    {
+      if (get_frame_type (frame) == SIGTRAMP_FRAME)
+	{
+	  return frame_unwind_caller_pc (frame);
+	}
+    }
+  return 0;
+}
+
+/* When FRAME is at a syscall instruction, return the PC of the next
+   instruction to be executed.  */
+
+static CORE_ADDR
+arm_linux_syscall_next_pc (struct frame_info *frame)
+{
+  CORE_ADDR pc = get_frame_pc (frame);
+  CORE_ADDR return_addr = 0;
+  return_addr = arm_linux_sigreturn_return_addr(frame,
+						get_frame_register_unsigned (frame, 7));
+
+  if (return_addr)
+    return return_addr;
+  
+  if (arm_frame_is_thumb (frame))
+    {
+      return_addr = pc + 2;
+      /* Addresses for calling Thumb functions have the bit 0 set.  */
+      return_addr |= 1;
+    }
+  else
+    {
+      return_addr = pc + 4;
+    }
+
+  return return_addr;
+}
+
+
 /* Insert a single step breakpoint at the next executed instruction.  */
 
 static int
@@ -688,6 +735,8 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 		    struct regcache *regs, struct displaced_step_closure *dsc)
 {
   CORE_ADDR from = dsc->insn_addr;
+  CORE_ADDR return_to = 0;
+
   struct frame_info *frame;
   unsigned int svc_number = displaced_read_reg (regs, from, 7);
 
@@ -697,13 +746,9 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 
   frame = get_current_frame ();
 
-  /* Is this a sigreturn or rt_sigreturn syscall?  Note: these are only useful
-     for EABI.  */
-  if (svc_number == 119 || svc_number == 173)
-    {
-      if (get_frame_type (frame) == SIGTRAMP_FRAME)
+  return_to = arm_linux_sigreturn_return_addr(frame, svc_number);
+  if (return_to)
 	{
-	  CORE_ADDR return_to;
 	  struct symtab_and_line sal;
 
 	  if (debug_displaced)
@@ -711,7 +756,6 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 	      "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n",
 	      (unsigned long) get_frame_pc (frame));
 
-	  return_to = frame_unwind_caller_pc (frame);
 	  if (debug_displaced)
 	    fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. "
 	      "Setting momentary breakpoint.\n", (unsigned long) return_to);
@@ -743,7 +787,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
       else if (debug_displaced)
 	fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn "
 			    "SVC call not in signal trampoline frame\n");
-    }
+    
 
   /* Preparation: If we detect sigreturn, set momentary breakpoint at resume
 		  location, else nothing.
@@ -946,6 +990,9 @@ arm_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_displaced_step_free_closure (gdbarch,
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+
+
+  tdep->syscall_next_pc = arm_linux_syscall_next_pc;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 1ac8817..518e4e8 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -257,7 +257,7 @@ int arm_apcs_32 = 1;
 
 /* Determine if FRAME is executing in Thumb mode.  */
 
-static int
+int
 arm_frame_is_thumb (struct frame_info *frame)
 {
   CORE_ADDR cpsr;
@@ -2808,7 +2808,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
   else if ((inst1 & 0xf000) == 0xd000)	/* conditional branch */
     {
       unsigned long cond = bits (inst1, 8, 11);
-      if (cond != 0x0f && condition_true (cond, status))    /* 0x0f = SWI */
+      if (cond == 0x0f)  /* 0x0f = SWI */
+	{
+	  struct gdbarch_tdep *tdep;
+	  tdep = gdbarch_tdep (get_frame_arch (frame));
+
+	  if (tdep->syscall_next_pc != NULL)
+	    nextpc = tdep->syscall_next_pc (frame);
+
+	}
+      else if (cond != 0x0f && condition_true (cond, status))
 	nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
     }
   else if ((inst1 & 0xf800) == 0xe000)	/* unconditional branch */
@@ -3257,7 +3266,16 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
 	case 0xc:
 	case 0xd:
 	case 0xe:		/* coproc ops */
+	  break;
 	case 0xf:		/* SWI */
+	  {
+	    struct gdbarch_tdep *tdep;
+	    tdep = gdbarch_tdep (get_frame_arch (frame));
+
+	    if (tdep->syscall_next_pc != NULL)
+	      nextpc = tdep->syscall_next_pc (frame);
+
+	  }
 	  break;
 
 	default:
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index b6283ef..2f4e99b 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -193,6 +193,10 @@ struct gdbarch_tdep
   struct type *arm_ext_type;
   struct type *neon_double_type;
   struct type *neon_quad_type;
+
+  /* Return the expected next PC if FRAME is stopped at a syscall
+     instruction.  */
+  CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
 };
 
 /* Structures used for displaced stepping.  */
@@ -294,6 +298,7 @@ extern void
 CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
 CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
 int arm_software_single_step (struct frame_info *);
+int arm_frame_is_thumb (struct frame_info *frame);
 
 extern struct displaced_step_closure *
   arm_displaced_step_copy_insn (struct gdbarch *, CORE_ADDR, CORE_ADDR,

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-25  3:06     ` Yao Qi
@ 2010-08-25 14:31       ` Daniel Jacobowitz
  2010-08-26  8:51         ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2010-08-25 14:31 UTC (permalink / raw)
  To: Yao Qi; +Cc: Mark Kettenis, gdb-patches

Generally looks OK.

On Tue, Aug 24, 2010 at 08:05:55PM -0700, Yao Qi wrote:
> Here is the updated patch, in which:
>   1.  Add arm_linux_syscall_next_pc, similar to
> mips_linux_syscall_next_pc.  Compute the return address of SWI in both
> ARM mode and Thumb mode.
>   2.  Extract some common code from arm_linux_copy_svc.

A valid return address won't be zero, but it's still confusing.
Please do this the way that e.g. mips_linux_get_longjmp_target does;
return 0 or 1, and have a CORE_ADDR * parameter.

> +static int
> +arm_linux_sigreturn_return_addr(struct frame_info *frame,
> +				unsigned long svc_number)

Space before "(".  Same problem in other places, too.

> +/* When FRAME is at a syscall instruction, return the PC of the next
> +   instruction to be executed.  */
> +
> +static CORE_ADDR
> +arm_linux_syscall_next_pc (struct frame_info *frame)
> +{
> +  CORE_ADDR pc = get_frame_pc (frame);
> +  CORE_ADDR return_addr = 0;
> +  return_addr = arm_linux_sigreturn_return_addr(frame,
> +						get_frame_register_unsigned (frame, 7));

Line too long; move the read of r7 to another temporary.

What about non-EABI?  We shouldn't wire this up for non-EABI binaries,
because the syscall number won't be in r7.

> @@ -2808,7 +2808,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
>    else if ((inst1 & 0xf000) == 0xd000)	/* conditional branch */
>      {
>        unsigned long cond = bits (inst1, 8, 11);
> -      if (cond != 0x0f && condition_true (cond, status))    /* 0x0f = SWI */
> +      if (cond == 0x0f)  /* 0x0f = SWI */

Why did you remove the condition_true check?

> +	{
> +	  struct gdbarch_tdep *tdep;
> +	  tdep = gdbarch_tdep (get_frame_arch (frame));

You can just use gdbarch_tdep (gdbarch).

-- 
Daniel Jacobowitz
CodeSourcery

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-25 14:31       ` Daniel Jacobowitz
@ 2010-08-26  8:51         ` Yao Qi
  2010-08-30 13:00           ` Daniel Jacobowitz
  0 siblings, 1 reply; 9+ messages in thread
From: Yao Qi @ 2010-08-26  8:51 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Mark Kettenis, gdb-patches

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

Daniel Jacobowitz wrote:
> Generally looks OK.
> 
> On Tue, Aug 24, 2010 at 08:05:55PM -0700, Yao Qi wrote:
>> Here is the updated patch, in which:
>>   1.  Add arm_linux_syscall_next_pc, similar to
>> mips_linux_syscall_next_pc.  Compute the return address of SWI in both
>> ARM mode and Thumb mode.
>>   2.  Extract some common code from arm_linux_copy_svc.
> 
> A valid return address won't be zero, but it's still confusing.
> Please do this the way that e.g. mips_linux_get_longjmp_target does;
> return 0 or 1, and have a CORE_ADDR * parameter.
> 
OK, done as you suggested.

>> +static int
>> +arm_linux_sigreturn_return_addr(struct frame_info *frame,
>> +				unsigned long svc_number)
> 
> Space before "(".  Same problem in other places, too.
> 

Done.

>> +/* When FRAME is at a syscall instruction, return the PC of the next
>> +   instruction to be executed.  */
>> +
>> +static CORE_ADDR
>> +arm_linux_syscall_next_pc (struct frame_info *frame)
>> +{
>> +  CORE_ADDR pc = get_frame_pc (frame);
>> +  CORE_ADDR return_addr = 0;
>> +  return_addr = arm_linux_sigreturn_return_addr(frame,
>> +						get_frame_register_unsigned (frame, 7));
> 
> Line too long; move the read of r7 to another temporary.
> 

Done.

> What about non-EABI?  We shouldn't wire this up for non-EABI binaries,
> because the syscall number won't be in r7.

I've added code for non-EABI to decode SWI instruction for syscall
number.  See details in my patch.

> 
>> @@ -2808,7 +2808,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
>>    else if ((inst1 & 0xf000) == 0xd000)	/* conditional branch */
>>      {
>>        unsigned long cond = bits (inst1, 8, 11);
>> -      if (cond != 0x0f && condition_true (cond, status))    /* 0x0f = SWI */
>> +      if (cond == 0x0f)  /* 0x0f = SWI */
> 
> Why did you remove the condition_true check?

Because I noticed that condition_true always returns true if cond is 0xf
(INST_NV).

>> +	{
>> +	  struct gdbarch_tdep *tdep;
>> +	  tdep = gdbarch_tdep (get_frame_arch (frame));
> 
> You can just use gdbarch_tdep (gdbarch).

OK, done in my patch.

-- 
Yao Qi
CodeSourcery
yao@codesourcery.com
(650) 331-3385 x739

[-- Attachment #2: return_addr_sigreturn.patch --]
[-- Type: text/x-patch, Size: 7073 bytes --]

2010-08-26  Yao Qi  <yao@codesourcery.com>

	* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
	(arm_linux_syscall_next_pc): New.
	(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. 
	(arm_linux_init_abi): Initialize syscall_next_pc.
	* arm-tdep.c (thumb_get_next_pc_raw):  Get next pc of SWI in Thumb mode.
	(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
	* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. 
	Declare arm_frame_is_thumb.

diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 682054c..f0e1dfa 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -630,6 +630,82 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
   return NULL;
 }
 
+/* Copy the value of next pc of sigreturn and rt_sigrturn into PC,
+   and return 1.  Return 0 if it is not a rt_sigreturn/sigreturn
+   syscall.  */
+static int
+arm_linux_sigreturn_return_addr (struct frame_info *frame,
+				 unsigned long svc_number,
+				 CORE_ADDR *pc)
+{
+  /* Is this a sigreturn or rt_sigreturn syscall?  */
+  if (svc_number == 119 || svc_number == 173)
+    {
+      if (get_frame_type (frame) == SIGTRAMP_FRAME)
+	{
+	  *pc = frame_unwind_caller_pc (frame);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+/* When FRAME is at a syscall instruction, return the PC of the next
+   instruction to be executed.  */
+
+static CORE_ADDR
+arm_linux_syscall_next_pc (struct frame_info *frame)
+{
+  CORE_ADDR pc = get_frame_pc (frame);
+  CORE_ADDR return_addr = 0;
+  int is_thumb = arm_frame_is_thumb (frame);
+  ULONGEST svc_number = 0;
+  int is_sigreturn = 0;
+
+  if (is_thumb)
+    {
+      svc_number = get_frame_register_unsigned (frame, 7);
+    }
+  else
+    {
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+      enum bfd_endian byte_order_for_code = 
+	gdbarch_byte_order_for_code (gdbarch);
+      unsigned long this_instr = 
+	read_memory_unsigned_integer (pc, 4, byte_order_for_code);
+
+      unsigned long svc_operand = (0x00ffffff & this_instr);
+      if (svc_operand)  /* OABI.  */
+	{
+	  svc_number = svc_operand - 0x900000;
+	}
+      else /* EABI.  */
+	{
+	  svc_number = get_frame_register_unsigned (frame, 7);
+	}
+    }
+
+  is_sigreturn = arm_linux_sigreturn_return_addr (frame, svc_number, 
+						  &return_addr);
+
+  if (is_sigreturn)
+    return return_addr;
+  
+  if (is_thumb)
+    {
+      return_addr = pc + 2;
+      /* Addresses for calling Thumb functions have the bit 0 set.  */
+      return_addr |= 1;
+    }
+  else
+    {
+      return_addr = pc + 4;
+    }
+
+  return return_addr;
+}
+
+
 /* Insert a single step breakpoint at the next executed instruction.  */
 
 static int
@@ -688,8 +764,11 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 		    struct regcache *regs, struct displaced_step_closure *dsc)
 {
   CORE_ADDR from = dsc->insn_addr;
+  CORE_ADDR return_to = 0;
+
   struct frame_info *frame;
   unsigned int svc_number = displaced_read_reg (regs, from, 7);
+  int is_sigreturn = 0;
 
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n",
@@ -697,13 +776,10 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 
   frame = get_current_frame ();
 
-  /* Is this a sigreturn or rt_sigreturn syscall?  Note: these are only useful
-     for EABI.  */
-  if (svc_number == 119 || svc_number == 173)
+  is_sigreturn = arm_linux_sigreturn_return_addr(frame, svc_number,
+						 &return_to);
+  if (is_sigreturn)
     {
-      if (get_frame_type (frame) == SIGTRAMP_FRAME)
-	{
-	  CORE_ADDR return_to;
 	  struct symtab_and_line sal;
 
 	  if (debug_displaced)
@@ -711,7 +787,6 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
 	      "sigreturn/rt_sigreturn SVC call. PC in frame = %lx\n",
 	      (unsigned long) get_frame_pc (frame));
 
-	  return_to = frame_unwind_caller_pc (frame);
 	  if (debug_displaced)
 	    fprintf_unfiltered (gdb_stdlog, "displaced: unwind pc = %lx. "
 	      "Setting momentary breakpoint.\n", (unsigned long) return_to);
@@ -743,7 +818,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
       else if (debug_displaced)
 	fprintf_unfiltered (gdb_stdlog, "displaced: sigreturn/rt_sigreturn "
 			    "SVC call not in signal trampoline frame\n");
-    }
+    
 
   /* Preparation: If we detect sigreturn, set momentary breakpoint at resume
 		  location, else nothing.
@@ -946,6 +1021,9 @@ arm_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_displaced_step_free_closure (gdbarch,
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+
+
+  tdep->syscall_next_pc = arm_linux_syscall_next_pc;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 1ac8817..36b46b5 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -257,7 +257,7 @@ int arm_apcs_32 = 1;
 
 /* Determine if FRAME is executing in Thumb mode.  */
 
-static int
+int
 arm_frame_is_thumb (struct frame_info *frame)
 {
   CORE_ADDR cpsr;
@@ -2808,7 +2808,16 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
   else if ((inst1 & 0xf000) == 0xd000)	/* conditional branch */
     {
       unsigned long cond = bits (inst1, 8, 11);
-      if (cond != 0x0f && condition_true (cond, status))    /* 0x0f = SWI */
+      if (cond == 0x0f)  /* 0x0f = SWI */
+	{
+	  struct gdbarch_tdep *tdep;
+	  tdep = gdbarch_tdep (gdbarch);
+
+	  if (tdep->syscall_next_pc != NULL)
+	    nextpc = tdep->syscall_next_pc (frame);
+
+	}
+      else if (cond != 0x0f && condition_true (cond, status))
 	nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
     }
   else if ((inst1 & 0xf800) == 0xe000)	/* unconditional branch */
@@ -3257,7 +3266,16 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc, int insert_bkpt)
 	case 0xc:
 	case 0xd:
 	case 0xe:		/* coproc ops */
+	  break;
 	case 0xf:		/* SWI */
+	  {
+	    struct gdbarch_tdep *tdep;
+	    tdep = gdbarch_tdep (gdbarch);
+
+	    if (tdep->syscall_next_pc != NULL)
+	      nextpc = tdep->syscall_next_pc (frame);
+
+	  }
 	  break;
 
 	default:
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index b6283ef..2f4e99b 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -193,6 +193,10 @@ struct gdbarch_tdep
   struct type *arm_ext_type;
   struct type *neon_double_type;
   struct type *neon_quad_type;
+
+  /* Return the expected next PC if FRAME is stopped at a syscall
+     instruction.  */
+  CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
 };
 
 /* Structures used for displaced stepping.  */
@@ -294,6 +298,7 @@ extern void
 CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
 CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
 int arm_software_single_step (struct frame_info *);
+int arm_frame_is_thumb (struct frame_info *frame);
 
 extern struct displaced_step_closure *
   arm_displaced_step_copy_insn (struct gdbarch *, CORE_ADDR, CORE_ADDR,

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-26  8:51         ` Yao Qi
@ 2010-08-30 13:00           ` Daniel Jacobowitz
  2010-08-30 13:08             ` Mark Kettenis
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2010-08-30 13:00 UTC (permalink / raw)
  To: Yao Qi; +Cc: Mark Kettenis, gdb-patches

On Thu, Aug 26, 2010 at 04:50:48PM +0800, Yao Qi wrote:
> > Why did you remove the condition_true check?
> 
> Because I noticed that condition_true always returns true if cond is 0xf
> (INST_NV).

Sorry, you're right - I completely misread this.

> 2010-08-26  Yao Qi  <yao@codesourcery.com>
> 
> 	* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
> 	(arm_linux_syscall_next_pc): New.
> 	(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. 
> 	(arm_linux_init_abi): Initialize syscall_next_pc.
> 	* arm-tdep.c (thumb_get_next_pc_raw):  Get next pc of SWI in Thumb mode.
> 	(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
> 	* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. 
> 	Declare arm_frame_is_thumb.

This is OK.  Thanks!

-- 
Daniel Jacobowitz
CodeSourcery

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-30 13:00           ` Daniel Jacobowitz
@ 2010-08-30 13:08             ` Mark Kettenis
  2010-08-30 15:35               ` Yao Qi
  0 siblings, 1 reply; 9+ messages in thread
From: Mark Kettenis @ 2010-08-30 13:08 UTC (permalink / raw)
  To: dan; +Cc: yao, mark.kettenis, gdb-patches

> Date: Mon, 30 Aug 2010 08:59:58 -0400
> From: Daniel Jacobowitz <dan@codesourcery.com>
> 
> On Thu, Aug 26, 2010 at 04:50:48PM +0800, Yao Qi wrote:
> > > Why did you remove the condition_true check?
> > 
> > Because I noticed that condition_true always returns true if cond is 0xf
> > (INST_NV).
> 
> Sorry, you're right - I completely misread this.
> 
> > 2010-08-26  Yao Qi  <yao@codesourcery.com>
> > 
> > 	* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
> > 	(arm_linux_syscall_next_pc): New.
> > 	(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. 
> > 	(arm_linux_init_abi): Initialize syscall_next_pc.
> > 	* arm-tdep.c (thumb_get_next_pc_raw):  Get next pc of SWI in Thumb mode.
> > 	(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
> > 	* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. 
> > 	Declare arm_frame_is_thumb.
> 
> This is OK.  Thanks!

If Daniel is happy with this, I'm as well.

Thanks,

Mark

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

* Re: [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall
  2010-08-30 13:08             ` Mark Kettenis
@ 2010-08-30 15:35               ` Yao Qi
  0 siblings, 0 replies; 9+ messages in thread
From: Yao Qi @ 2010-08-30 15:35 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: dan, gdb-patches

On Mon, Aug 30, 2010 at 03:07:16PM +0200, Mark Kettenis wrote:
> > Date: Mon, 30 Aug 2010 08:59:58 -0400
> > From: Daniel Jacobowitz <dan@codesourcery.com>
> > 
> > On Thu, Aug 26, 2010 at 04:50:48PM +0800, Yao Qi wrote:
> > > > Why did you remove the condition_true check?
> > > 
> > > Because I noticed that condition_true always returns true if cond is 0xf
> > > (INST_NV).
> > 
> > Sorry, you're right - I completely misread this.
> > 
> > > 2010-08-26  Yao Qi  <yao@codesourcery.com>
> > > 
> > > 	* arm-linux-tdep.c (arm_linux_sigreturn_return_addr): New.
> > > 	(arm_linux_syscall_next_pc): New.
> > > 	(arm_linux_copy_svc): Use arm_linux_sigreturn_return_addr instead. 
> > > 	(arm_linux_init_abi): Initialize syscall_next_pc.
> > > 	* arm-tdep.c (thumb_get_next_pc_raw):  Get next pc of SWI in Thumb mode.
> > > 	(arm_get_next_pc_raw): Get next pc of SWI in ARM mode.
> > > 	* arm-tdep.h (struct gdbarch_tdep): Add a function pointer syscall_next_pc. 
> > > 	Declare arm_frame_is_thumb.
> > 
> > This is OK.  Thanks!
> 
> If Daniel is happy with this, I'm as well.

Committed in both GDB mainline and GDB 7.2 branch.
http://www.cygwin.org/ml/gdb-cvs/2010-08/msg00190.html
http://www.cygwin.org/ml/gdb-cvs/2010-08/msg00191.html

-- 
Yao Qi
CodeSourcery
yao@codesourcery.com
(650) 331-3385 x739

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

end of thread, other threads:[~2010-08-30 15:35 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-24  6:39 [Patch,ARM] Next pc of sigreturn/rt_sigreturn syscall Yao Qi
2010-08-24 11:28 ` Mark Kettenis
2010-08-24 14:13   ` Daniel Jacobowitz
2010-08-25  3:06     ` Yao Qi
2010-08-25 14:31       ` Daniel Jacobowitz
2010-08-26  8:51         ` Yao Qi
2010-08-30 13:00           ` Daniel Jacobowitz
2010-08-30 13:08             ` Mark Kettenis
2010-08-30 15:35               ` Yao Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).