This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC]: x86 threaded watchpoint support [2/3]


This is the 2nd part of getting x86 threaded watchpoints to work. It involves some fixes to breakpoint.c.

The most major change is that a check has been added for a hardware_watchpoint to ensure that the stopped data address matches the watchpoint address. I do not know if there are platforms that have hardware_watchpoints but cannot tell what the data address is. If this problem exists, I can easily add a flag to determine if the stopped address can be used or not. Alternatively, the default stopped_data_address for such a platform could return a special value that the comparison check could treat as "don't know".

Comments? Ok?

-- Jeff J.

2004-06-11 Jeff Johnston <jjohnstn@redhat.com>

        * breakpoint.c (print_it_typical): Do not issue a warning message
        if we find a bp_thread_event and there are other items on the
        stop list.
        (bpstat_stop_status): When dealing with a hardware_watchpoint,
        check if the stopped data address matches the watched address
        for the current breakpoint in the list.  When dealing with a
        read or access watchpoint, if the address does not match, remember
        to turn off the print for the newly added bpstat.

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.174
diff -u -p -r1.174 breakpoint.c
--- breakpoint.c	7 Jun 2004 17:58:32 -0000	1.174
+++ breakpoint.c	11 Jun 2004 21:22:42 -0000
@@ -2120,8 +2120,13 @@ print_it_typical (bpstat bs)
       break;
 
     case bp_thread_event:
-      /* Not sure how we will get here. 
-	 GDB should not stop for these breakpoints.  */
+      /* We can only get here legitimately if something further on the bs 
+	 list has caused the stop status to be noisy.  A valid example
+	 of this is a new thread event and a software watchpoint have
+	 both occurred.  */
+      if (bs->next)
+        return PRINT_UNKNOWN;
+	          
       printf_filtered ("Thread Event Breakpoint: gdb should not stop!\n");
       return PRINT_NOTHING;
       break;
@@ -2683,45 +2688,100 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
     if (b->type == bp_watchpoint ||
 	b->type == bp_hardware_watchpoint)
       {
-	char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
+	CORE_ADDR addr;
+	struct value *v;
+	int found = 0;
+
+	/* If we have a hardware watchpoint, ensure that the address
+	   being watched caused the trap event.  */
+	if (b->type == bp_hardware_watchpoint)
+	  {
+	    addr = target_stopped_data_address ();
+	    if (addr == 0)
+	      {
+	        /* Don't stop.  */
+	        bs->print_it = print_it_noop;
+	        bs->stop = 0;
+	        continue;
+	      }
+	    for (v = b->val_chain; v; v = v->next)
+	      {
+	        if (VALUE_LVAL (v) == lval_memory
+	            && ! VALUE_LAZY (v))
+	          {
+		    struct type *vtype = check_typedef (VALUE_TYPE (v));
+
+		    if (v == b->val_chain
+		        || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+			&& TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+		      {
+		        CORE_ADDR vaddr;
+
+		        vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
+		        /* Exact match not required.  Within range is
+                           sufficient.  */
+		        if (addr >= vaddr &&
+			    addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
+		          found = 1;
+		      }
+	          }
+	      }
+	  }
+	else /* For a non-hardware watchpoint we need to test values.  */
+	  found = 1;
+	
+	if (found)
+	  {
+	    char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
 				    b->number);
-	struct cleanup *cleanups = make_cleanup (xfree, message);
-	int e = catch_errors (watchpoint_check, bs, message, 
-			      RETURN_MASK_ALL);
-	do_cleanups (cleanups);
-	switch (e)
+	    struct cleanup *cleanups = make_cleanup (xfree, message);
+	    int e = catch_errors (watchpoint_check, bs, message, 
+				  RETURN_MASK_ALL);
+	    do_cleanups (cleanups);
+	    switch (e)
+	      {
+	      case WP_DELETED:
+		/* We've already printed what needs to be printed.  */
+		/* Actually this is superfluous, because by the time we
+		   call print_it_typical() the wp will be already deleted,
+		   and the function will return immediately. */
+		bs->print_it = print_it_done;
+		/* Stop.  */
+		break;
+	      case WP_VALUE_CHANGED:
+		/* Stop.  */
+		++(b->hit_count);
+		break;
+	      case WP_VALUE_NOT_CHANGED:
+		/* Don't stop.  */
+		bs->print_it = print_it_noop;
+		bs->stop = 0;
+		continue;
+	      default:
+		/* Can't happen.  */
+		/* FALLTHROUGH */
+	      case 0:
+		/* Error from catch_errors.  */
+		printf_filtered ("Watchpoint %d deleted.\n", b->number);
+		if (b->related_breakpoint)
+		  b->related_breakpoint->disposition = disp_del_at_next_stop;
+		b->disposition = disp_del_at_next_stop;
+		/* We've already printed what needs to be printed.  */
+		bs->print_it = print_it_done;
+		
+		/* Stop.  */
+		break;
+	      }
+	  }
+	else	/* found == 0 */
 	  {
-	  case WP_DELETED:
-	    /* We've already printed what needs to be printed.  */
-	    /* Actually this is superfluous, because by the time we
-               call print_it_typical() the wp will be already deleted,
-               and the function will return immediately. */
-	    bs->print_it = print_it_done;
-	    /* Stop.  */
-	    break;
-	  case WP_VALUE_CHANGED:
-	    /* Stop.  */
-	    ++(b->hit_count);
-	    break;
-	  case WP_VALUE_NOT_CHANGED:
-	    /* Don't stop.  */
+	    /* This is a case where some watchpoint(s) triggered,
+	       but not at the address of this watchpoint (FOUND
+	       was left zero).  So don't print anything for this
+	       watchpoint.  */
 	    bs->print_it = print_it_noop;
 	    bs->stop = 0;
-	    continue;
-	  default:
-	    /* Can't happen.  */
-	    /* FALLTHROUGH */
-	  case 0:
-	    /* Error from catch_errors.  */
-	    printf_filtered ("Watchpoint %d deleted.\n", b->number);
-	    if (b->related_breakpoint)
-	      b->related_breakpoint->disposition = disp_del_at_next_stop;
-	    b->disposition = disp_del_at_next_stop;
-	    /* We've already printed what needs to be printed.  */
-	    bs->print_it = print_it_done;
-
-	    /* Stop.  */
-	    break;
+            continue;
 	  }
       }
     else if (b->type == bp_read_watchpoint || 
@@ -2733,7 +2793,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
 
 	addr = target_stopped_data_address ();
 	if (addr == 0)
-	  continue;
+	  {
+	    /* Don't stop.  */
+	    bs->print_it = print_it_noop;
+	    bs->stop = 0;
+	    continue;
+	  }
 	for (v = b->val_chain; v; v = v->next)
 	  {
 	    if (VALUE_LVAL (v) == lval_memory

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]