Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1.
@ 2011-07-05 20:29 Thiago Jung Bauermann
  2011-07-06 15:03 ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Thiago Jung Bauermann @ 2011-07-05 20:29 UTC (permalink / raw)
  To: gdb-patches ml

Hi,

target_{insert,remove}_{hw_breakpoint,watchpoint,mask_watchpoint} are
supposed to return 0, 1 and -1 for success, unsupported and error,
respectively. This patch makes ppc-linux-nat.c comply.

No regressions on ppc-linux and ppc64-linux. Ok?
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


2011-07-05  Thiago Jung Bauermann  <bauerman@br.ibm.com>

	Make insert/remove breakpoint and watchpoint functions return -1.
	* ppc-linux-nat.c (ppc_linux_remove_watchpoint): Add prototype.
	(booke_insert_point): Return 0 on success and -1 on error.
	(booke_remove_point): Likewise.
	(ppc_linux_insert_hw_breakpoint): Return 0 on success, -1 on error
	and 1 if hardware breakpoints are not supported.  Also, remove the
	breakpoint from all threads if it couldn't be installed in one
	of them.
	(ppc_linux_remove_hw_breakpoint): Likewise.
	(ppc_linux_insert_mask_watchpoint): Likewise.  Also, remove the
	watchpoint from all threads if it couldn't be installed in one
	of them.
	(ppc_linux_remove_mask_watchpoint): Likewise.
	(ppc_linux_insert_watchpoint): Likewise.  Also, remove the
	watchpoint from all threads if it couldn't be installed in one
	of them.
	(ppc_linux_remove_watchpoint): Likewise.

diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 275de78..410755f 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -336,6 +336,9 @@ PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
 PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
 /* *INDENT_ON * */
 
+static int ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
+					struct expression *cond);
+
 static int
 ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
 {
@@ -1566,8 +1569,10 @@ booke_find_thread_points_by_tid (int tid, int alloc_new)
 
 /* This function is a generic wrapper that is responsible for inserting a
    *point (i.e., calling `ptrace' in order to issue the request to the
-   kernel) and registering it internally in GDB.  */
-static void
+   kernel) and registering it internally in GDB.  Returns 0 for success
+   or -1 for failure.  */
+
+static int
 booke_insert_point (struct ppc_hw_breakpoint *b, int tid)
 {
   int i;
@@ -1580,10 +1585,13 @@ booke_insert_point (struct ppc_hw_breakpoint *b, int tid)
 
   memcpy (p, b, sizeof (struct ppc_hw_breakpoint));
 
-  errno = 0;
   slot = ptrace (PPC_PTRACE_SETHWDEBUG, tid, 0, p);
   if (slot < 0)
-    perror_with_name (_("Unexpected error setting breakpoint or watchpoint"));
+    {
+      do_cleanups (c);
+
+      return -1;
+    }
 
   /* Everything went fine, so we have to register this *point.  */
   t = booke_find_thread_points_by_tid (tid, 1);
@@ -1602,15 +1610,19 @@ booke_insert_point (struct ppc_hw_breakpoint *b, int tid)
   gdb_assert (i != max_slots_number);
 
   discard_cleanups (c);
+
+  return 0;
 }
 
 /* This function is a generic wrapper that is responsible for removing a
    *point (i.e., calling `ptrace' in order to issue the request to the
-   kernel), and unregistering it internally at GDB.  */
-static void
+   kernel), and unregistering it internally at GDB.  Returns 0 for
+   success or -1 for failure.  */
+
+static int
 booke_remove_point (struct ppc_hw_breakpoint *b, int tid)
 {
-  int i;
+  int i, ret = 0;
   struct hw_break_tuple *hw_breaks;
   struct thread_points *t;
 
@@ -1622,7 +1634,9 @@ booke_remove_point (struct ppc_hw_breakpoint *b, int tid)
     if (hw_breaks[i].hw_break && booke_cmp_hw_point (hw_breaks[i].hw_break, b))
       break;
 
-  gdb_assert (i != max_slots_number);
+  /* There's no such breakpoint/watchpoint for this thread.  */
+  if (i == max_slots_number)
+    return -1;
 
   /* We have to ignore ENOENT errors because the kernel implements hardware
      breakpoints/watchpoints as "one-shot", that is, they are automatically
@@ -1630,11 +1644,12 @@ booke_remove_point (struct ppc_hw_breakpoint *b, int tid)
   errno = 0;
   if (ptrace (PPC_PTRACE_DELHWDEBUG, tid, 0, hw_breaks[i].slot) < 0)
     if (errno != ENOENT)
-      perror_with_name (_("Unexpected error deleting "
-			  "breakpoint or watchpoint"));
+      ret = -1;
 
   xfree (hw_breaks[i].hw_break);
   hw_breaks[i].hw_break = NULL;
+
+  return ret;
 }
 
 /* Return the number of registers needed for a ranged breakpoint.  */
@@ -1652,14 +1667,15 @@ ppc_linux_ranged_break_num_registers (struct target_ops *target)
 
 static int
 ppc_linux_insert_hw_breakpoint (struct gdbarch *gdbarch,
-				  struct bp_target_info *bp_tgt)
+				struct bp_target_info *bp_tgt)
 {
+  int ret;
   ptid_t ptid;
   struct lwp_info *lp;
   struct ppc_hw_breakpoint p;
 
   if (!have_ptrace_booke_interface ())
-    return -1;
+    return 1;
 
   p.version = PPC_DEBUG_CURRENT_VERSION;
   p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
@@ -1682,21 +1698,36 @@ ppc_linux_insert_hw_breakpoint (struct gdbarch *gdbarch,
     }
 
   ALL_LWPS (lp, ptid)
-    booke_insert_point (&p, TIDGET (ptid));
+    {
+      ret = booke_insert_point (&p, TIDGET (ptid));
+      if (ret)
+	break;
+    }
 
-  return 0;
+  /* If an error occurred, remove the breakpoint from all threads, to
+     keep consistency (all threads must have the same breakpoints and
+     watchpoints intalled.)  */
+  if (ret)
+    ALL_LWPS (lp, ptid)
+      booke_remove_point (&p, TIDGET (ptid));
+
+  return ret;
 }
 
+/* Remove the hardware breakpoint described by BP_TGT.  Returns 0 for
+   success, 1 if hardware breakpoints are not supported or -1 for failure.  */
+
 static int
 ppc_linux_remove_hw_breakpoint (struct gdbarch *gdbarch,
-				  struct bp_target_info *bp_tgt)
+				struct bp_target_info *bp_tgt)
 {
+  int ret = 0;
   ptid_t ptid;
   struct lwp_info *lp;
   struct ppc_hw_breakpoint p;
 
   if (!have_ptrace_booke_interface ())
-    return -1;
+    return 1;
 
   p.version = PPC_DEBUG_CURRENT_VERSION;
   p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
@@ -1719,9 +1750,9 @@ ppc_linux_remove_hw_breakpoint (struct gdbarch *gdbarch,
     }
 
   ALL_LWPS (lp, ptid)
-    booke_remove_point (&p, TIDGET (ptid));
+    ret |= booke_remove_point (&p, TIDGET (ptid));
 
-  return 0;
+  return ret;
 }
 
 static int
@@ -1741,13 +1772,14 @@ get_trigger_type (int rw)
 
 /* Insert a new masked watchpoint at ADDR using the mask MASK.
    RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
-   or hw_access for an access watchpoint.  Returns 0 on success and throws
-   an error on failure.  */
+   or hw_access for an access watchpoint.  Returns 0 for success, 1 if
+   masked watchpoints are not supported or -1 for failure.  */
 
 static int
 ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
 				  CORE_ADDR mask, int rw)
 {
+  int ret;
   ptid_t ptid;
   struct lwp_info *lp;
   struct ppc_hw_breakpoint p;
@@ -1763,20 +1795,32 @@ ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
   p.condition_value = 0;
 
   ALL_LWPS (lp, ptid)
-    booke_insert_point (&p, TIDGET (ptid));
+    {
+      ret = booke_insert_point (&p, TIDGET (ptid));
+      if (ret)
+	break;
+    }
 
-  return 0;
+  /* If an error occurred, remove the breakpoint from all threads, to
+     keep consistency (all threads must have the same breakpoints and
+     watchpoints intalled.)  */
+  if (ret)
+    ALL_LWPS (lp, ptid)
+      booke_remove_point (&p, TIDGET (ptid));
+
+  return ret;
 }
 
 /* Remove a masked watchpoint at ADDR with the mask MASK.
    RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
-   or hw_access for an access watchpoint.  Returns 0 on success and throws
-   an error on failure.  */
+   or hw_access for an access watchpoint.  Returns 0 for success, 1 if
+   masked watchpoints are not supported or -1 for failure.  */
 
 static int
 ppc_linux_remove_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
 				  CORE_ADDR mask, int rw)
 {
+  int ret = 0;
   ptid_t ptid;
   struct lwp_info *lp;
   struct ppc_hw_breakpoint p;
@@ -1792,9 +1836,9 @@ ppc_linux_remove_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
   p.condition_value = 0;
 
   ALL_LWPS (lp, ptid)
-    booke_remove_point (&p, TIDGET (ptid));
+    ret |= booke_remove_point (&p, TIDGET (ptid));
 
-  return 0;
+  return ret;
 }
 
 /* Check whether we have at least one free DVC register.  */
@@ -2054,13 +2098,18 @@ create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr,
   p->addr = (uint64_t) addr;
 }
 
+/* Insert a hardware watchpoint at address ADDR, spanning LEN bytes.
+   RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
+   or hw_access for an access watchpoint.  Returns 0 for success, 1 if
+   hardware watchpoints are not supported or -1 for failure.  */
+
 static int
 ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
 			     struct expression *cond)
 {
   struct lwp_info *lp;
   ptid_t ptid;
-  int ret = -1;
+  int ret;
 
   if (have_ptrace_booke_interface ())
     {
@@ -2069,9 +2118,18 @@ ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
       create_watchpoint_request (&p, addr, len, rw, cond, 1);
 
       ALL_LWPS (lp, ptid)
-	booke_insert_point (&p, TIDGET (ptid));
+	{
+	  ret = booke_insert_point (&p, TIDGET (ptid));
+	  if (ret)
+	    break;
+	}
 
-      ret = 0;
+      /* If an error occurred, remove the breakpoint from all threads, to
+	 keep consistency (all threads must have the same breakpoints and
+	 watchpoints intalled.)  */
+      if (ret)
+	ALL_LWPS (lp, ptid)
+	  booke_remove_point (&p, TIDGET (ptid));
     }
   else
     {
@@ -2111,25 +2169,38 @@ ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
 	}
 
       saved_dabr_value = dabr_value;
+      ret = 0;
 
       ALL_LWPS (lp, ptid)
 	if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0,
 		    saved_dabr_value) < 0)
-	  return -1;
+	  {
+	    ret = -1;
+	    break;
+	  }
 
-      ret = 0;
+      /* If an error occurred, remove the breakpoint from all threads, to
+	 keep consistency (all threads must have the same breakpoints and
+	 watchpoints intalled.)  */
+      if (ret)
+	ppc_linux_remove_watchpoint (addr, len, rw, cond);
     }
 
   return ret;
 }
 
+/* Remove a hardware watchpoint at address ADDR, spanning LEN bytes.
+   RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
+   or hw_access for an access watchpoint.  Returns 0 for success, 1 if
+   hardware watchpoints are not supported or -1 for failure.  */
+
 static int
 ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
 			     struct expression *cond)
 {
   struct lwp_info *lp;
   ptid_t ptid;
-  int ret = -1;
+  int ret = 0;
 
   if (have_ptrace_booke_interface ())
     {
@@ -2138,19 +2209,16 @@ ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
       create_watchpoint_request (&p, addr, len, rw, cond, 0);
 
       ALL_LWPS (lp, ptid)
-	booke_remove_point (&p, TIDGET (ptid));
-
-      ret = 0;
+	ret |= booke_remove_point (&p, TIDGET (ptid));
     }
   else
     {
       saved_dabr_value = 0;
+
       ALL_LWPS (lp, ptid)
 	if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0,
 		    saved_dabr_value) < 0)
-	  return -1;
-
-      ret = 0;
+	  ret = -1;
     }
 
   return ret;



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

* Re: [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1.
  2011-07-05 20:29 [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1 Thiago Jung Bauermann
@ 2011-07-06 15:03 ` Tom Tromey
  2011-07-06 16:12   ` Joel Brobecker
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2011-07-06 15:03 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches ml

>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:

Thiago> target_{insert,remove}_{hw_breakpoint,watchpoint,mask_watchpoint} are
Thiago> supposed to return 0, 1 and -1 for success, unsupported and error,
Thiago> respectively.

I looked around for anything saying this, and couldn't find it.
Well -- I found it for target_insert_mask_watchpoint, but not other
cases.

And, at least in breakpoint.c:insert_bp_location, it seems to me that
the return value is expected to be an errno in one case -- search for
safe_strerror.

Maybe this code is in error?  I really couldn't say; but it seems
inconsistent at best.  Perhaps only parts of your patch could go in
as-is, what do you think?

Tom


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

* Re: [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1.
  2011-07-06 15:03 ` Tom Tromey
@ 2011-07-06 16:12   ` Joel Brobecker
  2011-07-06 16:36     ` Joel Brobecker
  0 siblings, 1 reply; 5+ messages in thread
From: Joel Brobecker @ 2011-07-06 16:12 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches ml

> >>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:
> 
> Thiago> target_{insert,remove}_{hw_breakpoint,watchpoint,mask_watchpoint} are
> Thiago> supposed to return 0, 1 and -1 for success, unsupported and error,
> Thiago> respectively.
> 
> I looked around for anything saying this, and couldn't find it.
> Well -- I found it for target_insert_mask_watchpoint, but not other
> cases.
> 
> And, at least in breakpoint.c:insert_bp_location, it seems to me that
> the return value is expected to be an errno in one case -- search for
> safe_strerror.
> 
> Maybe this code is in error?  I really couldn't say; but it seems
> inconsistent at best.  Perhaps only parts of your patch could go in
> as-is, what do you think?

Looking at target.h:

| /* Insert a breakpoint at address BP_TGT->placed_address in the target
|    machine.  Result is 0 for success, or an errno value.  */
| 
| extern int target_insert_breakpoint (struct gdbarch *gdbarch,
|                                      struct bp_target_info *bp_tgt);

It's a little bit confusing because some methods are implemented
inside the target_ops vector, while some others are documented
via the target_... function. That being said, it's ultra important
IMO in that case that we add the documentation wherever missing,
because these are used by all ports. And I remember scratching
my head quite a bit a while ago when I was working on watchpoint
support for VxWorks.

In any case, all this rambling to say that breakpoint.c is correct
in this case.

-- 
Joel


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

* Re: [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1.
  2011-07-06 16:12   ` Joel Brobecker
@ 2011-07-06 16:36     ` Joel Brobecker
  2011-07-06 19:38       ` Thiago Jung Bauermann
  0 siblings, 1 reply; 5+ messages in thread
From: Joel Brobecker @ 2011-07-06 16:36 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, gdb-patches ml

> Looking at target.h:
> 
> | /* Insert a breakpoint at address BP_TGT->placed_address in the target
> |    machine.  Result is 0 for success, or an errno value.  */
> | 
> | extern int target_insert_breakpoint (struct gdbarch *gdbarch,
> |                                      struct bp_target_info *bp_tgt);
> 

Sorry, scrap that part - I was looking at the wrong method
(I should have been looking at the `hw' one....).

> That being said, it's ultra important IMO in that case that we add the
> documentation wherever missing, because these are used by all ports.

Makes that comment all the more relevant :).

So I guess we'll have to infer the expected behavior from the core
code that calls it. I am hoping that it's the same as with the non
hw versions! :)

-- 
Joel


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

* Re: [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1.
  2011-07-06 16:36     ` Joel Brobecker
@ 2011-07-06 19:38       ` Thiago Jung Bauermann
  0 siblings, 0 replies; 5+ messages in thread
From: Thiago Jung Bauermann @ 2011-07-06 19:38 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches ml

On Wed, 2011-07-06 at 09:35 -0700, Joel Brobecker wrote:
> > Looking at target.h:
> > 
> > | /* Insert a breakpoint at address BP_TGT->placed_address in the target
> > |    machine.  Result is 0 for success, or an errno value.  */
> > | 
> > | extern int target_insert_breakpoint (struct gdbarch *gdbarch,
> > |                                      struct bp_target_info *bp_tgt);
> > 
> 
> Sorry, scrap that part - I was looking at the wrong method
> (I should have been looking at the `hw' one....).
> 
> > That being said, it's ultra important IMO in that case that we add the
> > documentation wherever missing, because these are used by all ports.
> 
> Makes that comment all the more relevant :).
> 
> So I guess we'll have to infer the expected behavior from the core
> code that calls it. I am hoping that it's the same as with the non
> hw versions! :)

My ppc476 patches touched a lot of this code and I made everything that
uses the breakpoint_ops methods follow that convention. Things were
indeed confusing and even contradictory before my patches, and I thought
I fixed all that. It seems I missed some parts then. I'll have a look
and post fixes. This patch can wait for now. Thanks for bringing this
up.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


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

end of thread, other threads:[~2011-07-06 18:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05 20:29 [RFA] Make ppc-linux-nat insert/remove breakpoint and watchpoint functions return -1 Thiago Jung Bauermann
2011-07-06 15:03 ` Tom Tromey
2011-07-06 16:12   ` Joel Brobecker
2011-07-06 16:36     ` Joel Brobecker
2011-07-06 19:38       ` Thiago Jung Bauermann

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