36ea501
2004-12-13  Jeff Johnston  <jjohnstn@redhat.com>
36ea501
9231e41
        * linux-nat.c: (stop_wait_callback, linux-nat-wait): Notify
9231e41
	observers of a sigtrap.
36ea501
	(delete_lwp): Free the saved_trap_data if present.
36ea501
	* linux-nat.h (struct lwp_info): Add saved_trap_data field.
36ea501
	(struct linux_watchpoint): New struct.
9231e41
	* linux-thread-db.c: Add support to always keep lwp info in ptids.
36ea501
	(attach_thread): Notify observers of a linux
36ea501
	new thread.
36ea501
	(thread_db_wait): Call check_event if SIGILL occurs.
9231e41
	* infrun.c: (handle_inferior_event): For platforms that
36ea501
	hit watchpoints prior to the data write, mark the watchpoints
36ea501
	so we know to check them after we step through the write.
36ea501
	* breakpoint.c (bpstat_stop_status): Fix up watchpoint code.
36ea501
	(insert_watchpoints_for_new_thread): New function.
36ea501
	(mark_triggered_watchpoints): Ditto.
36ea501
	* breakpoint.h (insert_watchpoints_for_new_thread): New prototype.
36ea501
	(mark_triggered_watchpoints): Ditto.
36ea501
	* i386-linux-nat.c (i386_linux_dr_get, i386_linux_dr_set): Use
36ea501
	TIDGET to get PTRACE lpw, otherwise fall back to PIDGET.
36ea501
	* amd64-linux-nat.c (amd64_linux_dr_get, amd64_linux_dr_set): Ditto.
36ea501
	* ia64-linux-nat.c: Add support for removing and inserting watchpoints
36ea501
	on all threads.
36ea501
	* s390-nat.c: Ditto.
36ea501
	* Makefile.in: Add observer.h and linux-nat.h to ia64-linux-nat.o
36ea501
	and s390-nat.o.
36ea501
	* doc/observer.texi: Add two new observers for linux_new_thread
36ea501
	and sigtrap.
36ea501
eb9d945
2007-10-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
eb9d945
eb9d945
	Port to GDB-6.7.
eb9d945
eb9d945
Index: gdb-6.7/gdb/doc/observer.texi
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/doc/observer.texi	2007-05-11 21:55:20.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/doc/observer.texi	2007-10-13 04:51:21.000000000 +0200
eb9d945
@@ -129,3 +129,12 @@ Called with @var{objfile} equal to @code
eb9d945
 previously loaded symbol table data has now been invalidated.
36ea501
 @end deftypefun
eb9d945
 
36ea501
+@deftypefun void linux_new_thread (ptid_t @var{ptid})
36ea501
+A new linux thread described by @var{ptid} has been officially attached
36ea501
+to by gdb.
36ea501
+@end deftypefun
36ea501
+
36ea501
+@deftypefun void sigtrap (void * @var{data})
36ea501
+A low-level SIGTRAP has been discovered.  This notification can be used to save
36ea501
+additional state necessary if the trap is deferred for later handling.
36ea501
+@end deftypefun
eb9d945
Index: gdb-6.7/gdb/infrun.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/infrun.c	2007-10-12 22:35:58.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/infrun.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -1784,9 +1784,19 @@ handle_inferior_event (struct execution_
160bca3
      single step over a watchpoint without disabling the watchpoint.  */
160bca3
   if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
160bca3
     {
160bca3
+      CORE_ADDR addr = 0;
160bca3
+
9231e41
       if (debug_infrun)
9231e41
 	fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
9231e41
-      resume (1, 0);
160bca3
+
160bca3
+      target_stopped_data_address (&current_target, &addr);
160bca3
+      mark_triggered_watchpoints (addr);
160bca3
+      registers_changed ();
160bca3
+      target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);	/* Single step */
160bca3
+
160bca3
+      ecs->waiton_ptid = ecs->ptid;
160bca3
+      ecs->wp = &(ecs->ws);
160bca3
+      ecs->infwait_state = infwait_nonstep_watch_state;
160bca3
       prepare_to_wait (ecs);
160bca3
       return;
36ea501
     }
eb9d945
@@ -1797,6 +1807,8 @@ handle_inferior_event (struct execution_
eb9d945
   if (gdbarch_have_nonsteppable_watchpoint (current_gdbarch)
eb9d945
       && STOPPED_BY_WATCHPOINT (ecs->ws))
160bca3
     {
160bca3
+      CORE_ADDR addr = 0;
36ea501
+
160bca3
       /* At this point, we are stopped at an instruction which has
160bca3
          attempted to write to a piece of memory under control of
160bca3
          a watchpoint.  The instruction hasn't actually executed
eb9d945
@@ -1804,15 +1816,12 @@ handle_inferior_event (struct execution_
160bca3
          now, we would get the old value, and therefore no change
160bca3
          would seem to have occurred.
36ea501
 
160bca3
-         In order to make watchpoints work `right', we really need
160bca3
-         to complete the memory write, and then evaluate the
160bca3
-         watchpoint expression.  The following code does that by
160bca3
-         removing the watchpoint (actually, all watchpoints and
160bca3
-         breakpoints), single-stepping the target, re-inserting
160bca3
-         watchpoints, and then falling through to let normal
160bca3
-         single-step processing handle proceed.  Since this
160bca3
-         includes evaluating watchpoints, things will come to a
160bca3
-         stop in the correct manner.  */
160bca3
+         In order to make watchpoints work `right', we mark the
160bca3
+	 triggered watchpoints so that after we single step,
160bca3
+	 we will check for a value change.  */
36ea501
+
160bca3
+      target_stopped_data_address (&current_target, &addr);
160bca3
+      mark_triggered_watchpoints (addr);
36ea501
 
9231e41
       if (debug_infrun)
9231e41
 	fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
eb9d945
@@ -1883,6 +1892,41 @@ handle_inferior_event (struct execution_
9231e41
 	}
9231e41
     }
36ea501
 
160bca3
+  if (stop_signal == TARGET_SIGNAL_TRAP
160bca3
+      && trap_expected
160bca3
+      && gdbarch_single_step_through_delay_p (current_gdbarch)
160bca3
+      && currently_stepping (ecs))
160bca3
+    {
160bca3
+      /* We're trying to step of a breakpoint.  Turns out that we're
160bca3
+	 also on an instruction that needs to be stepped multiple
160bca3
+	 times before it's been fully executing. E.g., architectures
160bca3
+	 with a delay slot.  It needs to be stepped twice, once for
160bca3
+	 the instruction and once for the delay slot.  */
160bca3
+      int step_through_delay
160bca3
+	= gdbarch_single_step_through_delay (current_gdbarch,
160bca3
+					     get_current_frame ());
160bca3
+      if (debug_infrun && step_through_delay)
9231e41
+	fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
160bca3
+      if (step_range_end == 0 && step_through_delay)
160bca3
+	{
160bca3
+	  /* The user issued a continue when stopped at a breakpoint.
160bca3
+	     Set up for another trap and get out of here.  */
160bca3
+         ecs->another_trap = 1;
160bca3
+         keep_going (ecs);
160bca3
+         return;
160bca3
+	}
160bca3
+      else if (step_through_delay)
160bca3
+	{
160bca3
+	  /* The user issued a step when stopped at a breakpoint.
160bca3
+	     Maybe we should stop, maybe we should not - the delay
160bca3
+	     slot *might* correspond to a line of source.  In any
160bca3
+	     case, don't decide that here, just set ecs->another_trap,
160bca3
+	     making sure we single-step again before breakpoints are
160bca3
+	     re-inserted.  */
160bca3
+	  ecs->another_trap = 1;
160bca3
+	}
160bca3
+    }
160bca3
+
160bca3
   /* Look at the cause of the stop, and decide what to do.
160bca3
      The alternatives are:
160bca3
      1) break; to really stop and return to the debugger,
eb9d945
@@ -1935,6 +1979,8 @@ handle_inferior_event (struct execution_
9231e41
          See more comments in inferior.h.  */
9231e41
       if (stop_soon == STOP_QUIETLY_NO_SIGSTOP)
160bca3
 	{
160bca3
+          if (debug_infrun)
9231e41
+	    fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
160bca3
 	  stop_stepping (ecs);
9231e41
 	  if (stop_signal == TARGET_SIGNAL_STOP)
9231e41
 	    stop_signal = TARGET_SIGNAL_0;
eb9d945
Index: gdb-6.7/gdb/breakpoint.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/breakpoint.c	2007-08-30 00:07:47.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/breakpoint.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -806,6 +806,90 @@ insert_catchpoint (struct ui_out *uo, vo
160bca3
     }
160bca3
 }
160bca3
 
160bca3
+/* External function to insert all existing watchpoints on a newly
160bca3
+   attached thread.  IWPFN is a callback function to perform
160bca3
+   the target insert watchpoint.  This function is used to support
160bca3
+   platforms where a watchpoint must be inserted/removed on each
160bca3
+   individual thread (e.g. ia64-linux and s390-linux).  For
160bca3
+   ia64 and s390 linux, this function is called via a new thread
160bca3
+   observer.  */
160bca3
+int
160bca3
+insert_watchpoints_for_new_thread (ptid_t new_thread, 
160bca3
+				   insert_watchpoint_ftype *iwpfn)
160bca3
+{
160bca3
+  struct bp_location *b;
160bca3
+  int val = 0;
160bca3
+  int return_val = 0;
160bca3
+  struct ui_file *tmp_error_stream = mem_fileopen ();
160bca3
+  make_cleanup_ui_file_delete (tmp_error_stream);
160bca3
+
160bca3
+  /* Explicitly mark the warning -- this will only be printed if
160bca3
+     there was an error.  */
160bca3
+  fprintf_unfiltered (tmp_error_stream, "Warning:\n");
160bca3
+
160bca3
+  ALL_BP_LOCATIONS (b)
160bca3
+    {
160bca3
+      /* Skip disabled breakpoints.  */
160bca3
+      if (!breakpoint_enabled (b->owner))
160bca3
+	continue;
160bca3
+
160bca3
+      /* For every active watchpoint, we need to insert the watchpoint on 
160bca3
+         the new thread.  */
160bca3
+      if (b->loc_type == bp_loc_hardware_watchpoint)
160bca3
+	{
160bca3
+	  struct value *v = b->owner->val_chain;
160bca3
+
160bca3
+	  /* Look at each value on the value chain.  */
160bca3
+	  for (; v; v = v->next)
160bca3
+	    {
160bca3
+	      /* If it's a memory location, and GDB actually needed
160bca3
+		 its contents to evaluate the expression, then we
160bca3
+		 must watch it.  */
160bca3
+	      if (VALUE_LVAL (v) == lval_memory
160bca3
+		  && ! VALUE_LAZY (v))
160bca3
+		{
160bca3
+		  struct type *vtype = check_typedef (VALUE_TYPE (v));
160bca3
+		  
160bca3
+		  /* We only watch structs and arrays if user asked
160bca3
+		     for it explicitly, never if they just happen to
160bca3
+		     appear in the middle of some value chain.  */
160bca3
+		  if (v == b->owner->val_chain
160bca3
+		      || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
160bca3
+			  && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
160bca3
+		    {
160bca3
+		      CORE_ADDR addr;
160bca3
+		      int len, type;
160bca3
+		      
160bca3
+		      addr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
160bca3
+		      len = TYPE_LENGTH (VALUE_TYPE (v));
160bca3
+		      type = hw_write;
160bca3
+		      if (b->owner->type == bp_read_watchpoint)
160bca3
+			type = hw_read;
160bca3
+		      else if (b->owner->type == bp_access_watchpoint)
160bca3
+			type = hw_access;
160bca3
+		      val = (*iwpfn) (new_thread, addr, len, type); 
160bca3
+		    }
160bca3
+		}
160bca3
+	    }
160bca3
+	}
160bca3
+
160bca3
+      if (val)
160bca3
+	return_val = val;
160bca3
+    }
160bca3
+
160bca3
+  /* Failure to insert a watchpoint on any memory value in the
160bca3
+     value chain brings us here.  */
160bca3
+  if (return_val)
160bca3
+    {
160bca3
+      fprintf_unfiltered (tmp_error_stream,
160bca3
+			  "%s\n",
160bca3
+			  "Could not insert hardware watchpoints on new thread."); 
160bca3
+      target_terminal_ours_for_output ();
160bca3
+      error_stream (tmp_error_stream);
160bca3
+    }
160bca3
+  return return_val;
160bca3
+}
160bca3
+
160bca3
 /* Helper routine: free the value chain for a breakpoint (watchpoint).  */
160bca3
 
eb9d945
 static void
eb9d945
@@ -1294,6 +1378,7 @@ remove_breakpoints (void)
160bca3
 {
160bca3
   struct bp_location *b;
160bca3
   int val;
160bca3
+  int return_val = 0;
160bca3
 
160bca3
   ALL_BP_LOCATIONS (b)
160bca3
   {
eb9d945
@@ -1301,10 +1386,10 @@ remove_breakpoints (void)
160bca3
       {
160bca3
 	val = remove_breakpoint (b, mark_uninserted);
160bca3
 	if (val != 0)
160bca3
-	  return val;
160bca3
+	  return_val = val;
160bca3
       }
160bca3
   }
160bca3
-  return 0;
160bca3
+  return return_val;
160bca3
 }
160bca3
 
160bca3
 int
eb9d945
@@ -2187,8 +2272,13 @@ print_it_typical (bpstat bs)
160bca3
       break;
160bca3
 
160bca3
     case bp_thread_event:
160bca3
-      /* Not sure how we will get here. 
160bca3
-	 GDB should not stop for these breakpoints.  */
160bca3
+      /* We can only get here legitimately if something further on the bs 
160bca3
+	 list has caused the stop status to be noisy.  A valid example
160bca3
+	 of this is a new thread event and a software watchpoint have
160bca3
+	 both occurred.  */
160bca3
+      if (bs->next)
160bca3
+        return PRINT_UNKNOWN;
160bca3
+
9231e41
       printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
160bca3
       return PRINT_NOTHING;
160bca3
       break;
eb9d945
@@ -2636,6 +2726,54 @@ which its expression is valid.\n");     
160bca3
     }
160bca3
 }
160bca3
 
160bca3
+/* Check watchpoints for a match with a stopped data address.
160bca3
+  
160bca3
+   STOPPED_DATA_ADDRESS is the address of a triggered watchpoint.
160bca3
+   A match with an existing watchpoint will cause that watchpoint
160bca3
+   to be marked as triggered.
160bca3
+
160bca3
+   This function is only used for platforms where a watchpoint
160bca3
+   triggers prior to the data being accessed.  */
160bca3
+
160bca3
+void
160bca3
+mark_triggered_watchpoints (CORE_ADDR stopped_data_address)
160bca3
+{
160bca3
+  struct breakpoint *b, *temp;
160bca3
+  CORE_ADDR addr = stopped_data_address;
160bca3
+  struct value *v;
160bca3
+  
160bca3
+  ALL_BREAKPOINTS_SAFE (b, temp)
160bca3
+  {
160bca3
+    if (b->type == bp_hardware_watchpoint
160bca3
+	|| b->type == bp_read_watchpoint
160bca3
+	|| b->type == bp_access_watchpoint)
160bca3
+      {
160bca3
+	for (v = b->val_chain; v; v = v->next)
160bca3
+	  {
160bca3
+	    if (VALUE_LVAL (v) == lval_memory
160bca3
+	        && ! VALUE_LAZY (v))
160bca3
+	      {
160bca3
+	        struct type *vtype = check_typedef (VALUE_TYPE (v));
160bca3
+		    
160bca3
+		if (v == b->val_chain
160bca3
+		    || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
160bca3
+		    && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
160bca3
+		  {
160bca3
+		    CORE_ADDR vaddr;
160bca3
+			
160bca3
+		    vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
160bca3
+		    /* Exact match not required.  Within range is
160bca3
+		       sufficient.  */
160bca3
+		    if (addr >= vaddr &&
160bca3
+		        addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
160bca3
+		      b->watchpoint_triggered = 1;
160bca3
+		  }
160bca3
+	      }
160bca3
+	  }
160bca3
+      }
160bca3
+  }
160bca3
+}
160bca3
+
160bca3
 /* Get a bpstat associated with having just stopped at address
160bca3
    BP_ADDR in thread PTID.  STOPPED_BY_WATCHPOINT is 1 if the
160bca3
    target thinks we stopped due to a hardware watchpoint, 0 if we
eb9d945
@@ -2766,82 +2904,61 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
160bca3
     bs->stop = 1;
160bca3
     bs->print = 1;
160bca3
 
160bca3
-    if (b->type == bp_watchpoint ||
160bca3
-	b->type == bp_hardware_watchpoint)
160bca3
-      {
160bca3
-	char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
160bca3
-				    b->number);
160bca3
-	struct cleanup *cleanups = make_cleanup (xfree, message);
160bca3
-	int e = catch_errors (watchpoint_check, bs, message, 
160bca3
-			      RETURN_MASK_ALL);
160bca3
-	do_cleanups (cleanups);
160bca3
-	switch (e)
160bca3
-	  {
160bca3
-	  case WP_DELETED:
160bca3
-	    /* We've already printed what needs to be printed.  */
160bca3
-	    /* Actually this is superfluous, because by the time we
160bca3
-               call print_it_typical() the wp will be already deleted,
160bca3
-               and the function will return immediately. */
160bca3
-	    bs->print_it = print_it_done;
160bca3
-	    /* Stop.  */
160bca3
-	    break;
160bca3
-	  case WP_VALUE_CHANGED:
160bca3
-	    /* Stop.  */
160bca3
-	    ++(b->hit_count);
160bca3
-	    break;
160bca3
-	  case WP_VALUE_NOT_CHANGED:
160bca3
-	    /* Don't stop.  */
160bca3
-	    bs->print_it = print_it_noop;
160bca3
-	    bs->stop = 0;
160bca3
-	    continue;
160bca3
-	  default:
160bca3
-	    /* Can't happen.  */
160bca3
-	    /* FALLTHROUGH */
160bca3
-	  case 0:
160bca3
-	    /* Error from catch_errors.  */
9231e41
-	    printf_filtered (_("Watchpoint %d deleted.\n"), b->number);
160bca3
-	    if (b->related_breakpoint)
160bca3
-	      b->related_breakpoint->disposition = disp_del_at_next_stop;
160bca3
-	    b->disposition = disp_del_at_next_stop;
160bca3
-	    /* We've already printed what needs to be printed.  */
160bca3
-	    bs->print_it = print_it_done;
160bca3
-
160bca3
-	    /* Stop.  */
160bca3
-	    break;
160bca3
-	  }
160bca3
-      }
160bca3
-    else if (b->type == bp_read_watchpoint || 
160bca3
-	     b->type == bp_access_watchpoint)
160bca3
+    if (b->type == bp_watchpoint
160bca3
+	     || b->type == bp_read_watchpoint 
160bca3
+	     || b->type == bp_access_watchpoint
160bca3
+	     || b->type == bp_hardware_watchpoint)
160bca3
       {
160bca3
 	CORE_ADDR addr;
160bca3
 	struct value *v;
160bca3
-	int found = 0;
160bca3
+	int must_check_value = 0;
160bca3
 
160bca3
-	if (!target_stopped_data_address (&current_target, &addr))
160bca3
-	  continue;
9231e41
-	for (v = b->val_chain; v; v = value_next (v))
9231e41
+ 	if (b->type == bp_watchpoint
160bca3
+	    || b->watchpoint_triggered
160bca3
+	    || (b->type == bp_hardware_watchpoint
160bca3
+		&& !target_stopped_data_address_p (&current_target)))
160bca3
 	  {
160bca3
-	    if (VALUE_LVAL (v) == lval_memory
9231e41
-		&& ! value_lazy (v))
160bca3
+	    /* We either have a software watchpoint, a triggered watchpoint 
160bca3
+	       which we have stepped over, or we cannot ascertain what data 
160bca3
+	       address causes a write watchpoint.  In all these
160bca3
+	       cases, we must check the watchpoint value.  */
160bca3
+	    b->watchpoint_triggered = 0;
160bca3
+	    must_check_value = 1;
160bca3
+	  }
160bca3
+	else
160bca3
+	  {
160bca3
+	    /* At this point, we know target_stopped_data_address () works or 
160bca3
+	       we have a read or access watchpoint and have no alternatives.  */
160bca3
+	    if (!target_stopped_data_address (&current_target, &addr))
160bca3
 	      {
9231e41
-		struct type *vtype = check_typedef (value_type (v));
160bca3
-
160bca3
-		if (v == b->val_chain
160bca3
-		    || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
160bca3
-			&& TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
160bca3
+		bs->print_it = print_it_noop;
160bca3
+		bs->stop = 0;
160bca3
+		continue;
160bca3
+	      }
160bca3
+	    for (v = b->val_chain; v; v = v->next)
160bca3
+	      {
160bca3
+		if (VALUE_LVAL (v) == lval_memory
160bca3
+		    && ! VALUE_LAZY (v))
160bca3
 		  {
160bca3
-		    CORE_ADDR vaddr;
160bca3
-
9231e41
-		    vaddr = VALUE_ADDRESS (v) + value_offset (v);
160bca3
-		    /* Exact match not required.  Within range is
160bca3
-                       sufficient.  */
160bca3
-		    if (addr >= vaddr &&
9231e41
-			addr < vaddr + TYPE_LENGTH (value_type (v)))
160bca3
-		      found = 1;
160bca3
+		    struct type *vtype = check_typedef (VALUE_TYPE (v));
160bca3
+		    
160bca3
+		    if (v == b->val_chain
160bca3
+			|| (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
160bca3
+			    && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
160bca3
+		      {
160bca3
+			CORE_ADDR vaddr;
160bca3
+			
160bca3
+			vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v);
160bca3
+			/* Exact match not required.  Within range is
160bca3
+			   sufficient.  */
160bca3
+			if (addr >= vaddr &&
160bca3
+			    addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v)))
160bca3
+			  must_check_value = 1;
160bca3
+		      }
160bca3
 		  }
160bca3
 	      }
160bca3
 	  }
160bca3
-	if (found)
9231e41
+ 	if (must_check_value)
160bca3
 	  {
160bca3
 	    char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
160bca3
 					b->number);
eb9d945
@@ -2870,6 +2987,15 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
160bca3
 		break;
160bca3
 	      case WP_VALUE_NOT_CHANGED:
160bca3
 		/* Stop.  */
160bca3
+		if (b->type == bp_hardware_watchpoint
160bca3
+		    || b->type == bp_watchpoint)
160bca3
+		  {
160bca3
+		    /* Don't stop: write watchpoints shouldn't fire if
160bca3
+		       the value hasn't changed.  */
160bca3
+		    bs->print_it = print_it_noop;
160bca3
+		    bs->stop = 0;
160bca3
+		    continue;
160bca3
+		  }
160bca3
 		++(b->hit_count);
160bca3
 		break;
160bca3
 	      default:
eb9d945
@@ -2885,7 +3011,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
160bca3
 		break;
160bca3
 	      }
160bca3
 	  }
160bca3
-	else	/* found == 0 */
160bca3
+	else	/* must_check_value == 0 */
160bca3
 	  {
160bca3
 	    /* This is a case where some watchpoint(s) triggered,
160bca3
 	       but not at the address of this watchpoint (FOUND
eb9d945
@@ -4186,6 +4312,7 @@ set_raw_breakpoint (struct symtab_and_li
160bca3
   b->exec_pathname = NULL;
160bca3
   b->ops = NULL;
160bca3
   b->pending = 0;
160bca3
+  b->watchpoint_triggered = 0;
160bca3
 
160bca3
   /* Add this breakpoint to the end of the chain
160bca3
      so that a list of breakpoints will come out in order
eb9d945
Index: gdb-6.7/gdb/breakpoint.h
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/breakpoint.h	2007-08-23 20:08:26.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/breakpoint.h	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -420,6 +420,11 @@ struct breakpoint
36ea501
 
a51648d
     /* Is breakpoint pending on shlib loads?  */
a51648d
     int pending;
a51648d
+
a51648d
+    /* Has a watchpoint been triggered?  This is only used for 
a51648d
+       non-continuable watchpoints which trigger prior to the data
a51648d
+       being modified.  */
a51648d
+    int watchpoint_triggered;
a51648d
   };
a51648d
 
a51648d
 /* The following stuff is an abstract data type "bpstat" ("breakpoint
eb9d945
@@ -688,6 +693,14 @@ extern void tbreak_command (char *, int)
a51648d
 
a51648d
 extern int insert_breakpoints (void);
a51648d
 
a51648d
+/* The following provides a callback mechanism to insert watchpoints
a51648d
+   for a new thread.  This is needed, for example, on ia64 linux.  */
a51648d
+typedef int (insert_watchpoint_ftype) (ptid_t, CORE_ADDR, int, int);
a51648d
+extern int insert_watchpoints_for_new_thread (ptid_t ptid,
a51648d
+					      insert_watchpoint_ftype *fn);
a51648d
+
a51648d
+extern void mark_triggered_watchpoints (CORE_ADDR);
a51648d
+
a51648d
 extern int remove_breakpoints (void);
a51648d
 
a51648d
 /* This function can be used to physically insert eventpoints from the
eb9d945
Index: gdb-6.7/gdb/linux-nat.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/linux-nat.c	2007-10-12 22:35:58.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/linux-nat.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -34,6 +34,7 @@
a51648d
 #include "gdbthread.h"
a51648d
 #include "gdbcmd.h"
a51648d
 #include "regcache.h"
a51648d
+#include "observer.h"
9231e41
 #include "regset.h"
9231e41
 #include "inf-ptrace.h"
9231e41
 #include "auxv.h"
eb9d945
@@ -704,6 +705,9 @@ delete_lwp (ptid_t ptid)
a51648d
   else
a51648d
     lwp_list = lp->next;
a51648d
 
a51648d
+  if (lp->saved_trap_data)
a51648d
+    xfree (lp->saved_trap_data);
a51648d
+
a51648d
   xfree (lp);
a51648d
 }
a51648d
 
eb9d945
@@ -1501,6 +1505,13 @@ stop_wait_callback (struct lwp_info *lp,
a51648d
 	         user will delete or disable the breakpoint, but the
a51648d
 	         thread will have already tripped on it.  */
a51648d
 
a51648d
+              /* Notify any observers that we have a SIGTRAP.
a51648d
+                 This is needed on platforms that must save more state
a51648d
+                 than just the trap.  For example, ia64 linux uses
a51648d
+                 siginfo to determine if a watchpoint has occurred and
a51648d
+                 this information gets trashed by a SIGSTOP.  */
a51648d
+              observer_notify_sigtrap (lp);
a51648d
+
a51648d
 	      /* Now resume this LWP and get the SIGSTOP event. */
a51648d
 	      errno = 0;
a51648d
 	      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
eb9d945
@@ -2061,6 +2072,14 @@ retry:
9231e41
 				 target_pid_to_str (lp->ptid));
a51648d
 	    }
a51648d
 
a51648d
+          /* For platforms such as ia64, a hardware watchpoint is
a51648d
+             determined by looking at special information available
a51648d
+	     at the time time of the trap (siginfo).  This information
a51648d
+	     is not preserved if we choose to take an event on another
a51648d
+	     thread and later come back to this event, thus we must
a51648d
+	     notify an observer so the information can be stored.  */
a51648d
+          observer_notify_sigtrap (lp);   
a51648d
+
a51648d
 	  /* Handle GNU/Linux's extended waitstatus for trace events.  */
a51648d
 	  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
a51648d
 	    {
eb9d945
Index: gdb-6.7/gdb/linux-nat.h
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/linux-nat.h	2007-10-12 22:35:58.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/linux-nat.h	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -61,6 +61,18 @@ struct lwp_info
a51648d
 
a51648d
   /* Next LWP in list.  */
a51648d
   struct lwp_info *next;
a51648d
+
a51648d
+  /* Optional saved trap state for when a trap gets pushed back
a51648d
+     due to multiple events occurring at the same time.  */
a51648d
+  void *saved_trap_data;
a51648d
+};
a51648d
+
a51648d
+/* Watchpoint description.  */
a51648d
+struct linux_watchpoint
a51648d
+{
a51648d
+  CORE_ADDR addr;
a51648d
+  int len;
a51648d
+  int type;
a51648d
 };
a51648d
 
9231e41
 /* Attempt to initialize libthread_db.  */
eb9d945
Index: gdb-6.7/gdb/Makefile.in
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/Makefile.in	2007-09-05 02:14:02.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/Makefile.in	2007-10-13 04:50:53.000000000 +0200
eb9d945
@@ -2160,7 +2160,7 @@ i387-tdep.o: i387-tdep.c $(defs_h) $(dou
9231e41
 	$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h)
a51648d
 ia64-linux-nat.o: ia64-linux-nat.c $(defs_h) $(gdb_string_h) $(inferior_h) \
9231e41
 	$(target_h) $(gdbcore_h) $(regcache_h) $(ia64_tdep_h) $(gdb_wait_h) \
9231e41
-	$(gregset_h) $(linux_nat_h)
9231e41
+	$(gregset_h) $(observer_h) $(linux_nat_h)
a51648d
 ia64-linux-tdep.o: ia64-linux-tdep.c $(defs_h) $(ia64_tdep_h) \
eb9d945
 	$(arch_utils_h) $(gdbcore_h) $(regcache_h) $(osabi_h) $(solib_svr4_h) \
eb9d945
 	$(symtab_h)
eb9d945
@@ -2541,7 +2541,7 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_h) $
eb9d945
 rs6000-aix-tdep.o: rs6000-aix-tdep.c $(defs_h) $(gdb_string_h) $(osabi_h) \
eb9d945
 	$(regcache_h) $(regset_h) $(rs6000_tdep_h) $(ppc_tdep_h)
eb9d945
 s390-nat.o: s390-nat.c $(defs_h) $(regcache_h) $(inferior_h) \
9231e41
-	$(s390_tdep_h) $(target_h) $(linux_nat_h)
eb9d945
+	$(s390_tdep_h) $(target_h) $(linux_nat_h) $(observer_h)
a51648d
 s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
a51648d
 	$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \
9231e41
 	$(floatformat_h) $(regcache_h) $(trad_frame_h) $(frame_base_h) \
eb9d945
Index: gdb-6.7/gdb/linux-thread-db.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/linux-thread-db.c	2007-08-23 20:08:35.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/linux-thread-db.c	2007-10-13 04:53:59.000000000 +0200
eb9d945
@@ -34,6 +34,7 @@
a51648d
 #include "target.h"
a51648d
 #include "regcache.h"
a51648d
 #include "solib-svr4.h"
a51648d
+#include "observer.h"
9231e41
 #include "gdbcore.h"
eb9d945
 #include "observer.h"
9231e41
 #include "linux-nat.h"
eb9d945
@@ -673,6 +674,7 @@ attach_thread (ptid_t ptid, const td_thr
a51648d
 {
a51648d
   struct thread_info *tp;
a51648d
   td_err_e err;
a51648d
+  ptid_t new_ptid;
a51648d
 
a51648d
   /* If we're being called after a TD_CREATE event, we may already
a51648d
      know about this thread.  There are two ways this can happen.  We
eb9d945
@@ -700,8 +702,10 @@ attach_thread (ptid_t ptid, const td_thr
a51648d
   if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
a51648d
     return;			/* A zombie thread -- do not attach.  */
a51648d
 
a51648d
+  new_ptid = BUILD_LWP (ti_p->ti_lid, GET_PID (ptid));
a51648d
+
a51648d
   /* Under GNU/Linux, we have to attach to each and every thread.  */
eb9d945
-  if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0) < 0)
eb9d945
+  if (lin_lwp_attach_lwp (new_ptid, 0) < 0)
eb9d945
     return;
eb9d945
 
eb9d945
   /* Add the thread to GDB's thread list.  */
eb9d945
@@ -712,6 +716,11 @@ attach_thread (ptid_t ptid, const td_thr
eb9d945
   if (verbose)
eb9d945
     printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
a51648d
 
a51648d
+  /* Notify any observers of a new linux thread.  This
a51648d
+     would include any linux platforms that have to insert hardware
a51648d
+     watchpoints on every thread.  */
a51648d
+  observer_notify_linux_new_thread (new_ptid);
a51648d
+
a51648d
   /* Enable thread event reporting for this thread.  */
a51648d
   err = td_thr_event_enable_p (th_p, 1);
a51648d
   if (err != TD_OK)
eb9d945
@@ -891,7 +900,8 @@ thread_db_wait (ptid_t ptid, struct targ
eb9d945
     thread_db_find_new_threads ();
a51648d
 
a51648d
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
a51648d
-      && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
a51648d
+      && (ourstatus->value.sig == TARGET_SIGNAL_TRAP
a51648d
+          || ourstatus->value.sig == TARGET_SIGNAL_ILL))
a51648d
     /* Check for a thread event.  */
a51648d
     check_event (ptid);
a51648d
 
eb9d945
Index: gdb-6.7/gdb/i386-linux-nat.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/i386-linux-nat.c	2007-08-23 20:08:34.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/i386-linux-nat.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -585,10 +585,9 @@ i386_linux_dr_get (int regnum)
a51648d
   int tid;
a51648d
   unsigned long value;
a51648d
 
a51648d
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
a51648d
-     multi-threaded processes here.  For now, pretend there is just
a51648d
-     one thread.  */
a51648d
-  tid = PIDGET (inferior_ptid);
a51648d
+  tid = TIDGET (inferior_ptid);
a51648d
+  if (tid == 0)
a51648d
+    tid = PIDGET (inferior_ptid);
36ea501
 
a51648d
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
a51648d
      ptrace call fails breaks debugging remote targets.  The correct
eb9d945
@@ -613,10 +612,9 @@ i386_linux_dr_set (int regnum, unsigned 
a51648d
 {
a51648d
   int tid;
36ea501
 
a51648d
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
a51648d
-     multi-threaded processes here.  For now, pretend there is just
a51648d
-     one thread.  */
a51648d
-  tid = PIDGET (inferior_ptid);
a51648d
+  tid = TIDGET (inferior_ptid);
a51648d
+  if (tid == 0)
a51648d
+    tid = PIDGET (inferior_ptid);
36ea501
 
a51648d
   errno = 0;
a51648d
   ptrace (PTRACE_POKEUSER, tid,
eb9d945
Index: gdb-6.7/gdb/ia64-linux-nat.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/ia64-linux-nat.c	2007-08-23 20:08:35.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/ia64-linux-nat.c	2007-10-13 05:07:58.000000000 +0200
eb9d945
@@ -27,6 +27,7 @@
c59c374
 #include "regcache.h"
c59c374
 #include "ia64-tdep.h"
c59c374
 #include "linux-nat.h"
160bca3
+#include "observer.h"
36ea501
 
c59c374
 #include <signal.h>
c59c374
 #include <sys/ptrace.h>
eb9d945
@@ -550,10 +551,10 @@ is_power_of_2 (int val)
160bca3
   return onecount <= 1;
160bca3
 }
36ea501
 
160bca3
+/* Internal routine to insert one watchpoint for a specified thread.  */
eb9d945
 static int
eb9d945
-ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
160bca3
+ia64_linux_insert_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
160bca3
 {
eb9d945
-  ptid_t ptid = inferior_ptid;
160bca3
   int idx;
160bca3
   long dbr_addr, dbr_mask;
eb9d945
   int max_watchpoints = 4;
eb9d945
@@ -598,10 +599,39 @@ ia64_linux_insert_watchpoint (CORE_ADDR 
160bca3
   return 0;
160bca3
 }
36ea501
 
160bca3
+/* Internal callback routine which can be used via iterate_over_lwps
160bca3
+   to insert a specific watchpoint from all active threads.  */
eb9d945
 static int
eb9d945
-ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
160bca3
+ia64_linux_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
160bca3
+{
160bca3
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
36ea501
+
160bca3
+  return ia64_linux_insert_one_watchpoint (lwp->ptid, args->addr,
160bca3
+		 		     	   args->len, args->type);
160bca3
+}
160bca3
+
160bca3
+/* Insert a watchpoint for all threads.  */
eb9d945
+static int
eb9d945
+ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
160bca3
+{
160bca3
+  struct linux_watchpoint args;
160bca3
+
160bca3
+  args.addr = addr;
160bca3
+  args.len = len;
160bca3
+  args.type = rw;
160bca3
+
160bca3
+  /* For ia64, watchpoints must be inserted/removed on each thread so
160bca3
+     we iterate over the lwp list.  */
160bca3
+  if (iterate_over_lwps (&ia64_linux_insert_watchpoint_callback, &args))
160bca3
+    return -1;
160bca3
+
160bca3
+  return 0;
160bca3
+}
160bca3
+
160bca3
+/* Internal routine to remove one watchpoint for a specified thread.  */
160bca3
+static int
eb9d945
+ia64_linux_remove_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int type)
160bca3
 {
eb9d945
-  ptid_t ptid = inferior_ptid;
160bca3
   int idx;
160bca3
   long dbr_addr, dbr_mask;
eb9d945
   int max_watchpoints = 4;
eb9d945
@@ -623,13 +653,55 @@ ia64_linux_remove_watchpoint (CORE_ADDR 
160bca3
   return -1;
160bca3
 }
36ea501
 
160bca3
+/* Internal callback routine which can be used via iterate_over_lwps
160bca3
+   to remove a specific watchpoint from all active threads.  */
160bca3
+static int
160bca3
+ia64_linux_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
160bca3
+{
160bca3
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
160bca3
+
160bca3
+  return ia64_linux_remove_one_watchpoint (lwp->ptid, args->addr,
160bca3
+		 		     	   args->len);
160bca3
+}
160bca3
+
160bca3
+/* Remove a watchpoint for all threads.  */
eb9d945
+static int
eb9d945
+ia64_linux_remove_watchpoint (CORE_ADDR addr, int len)
160bca3
+{
160bca3
+  struct linux_watchpoint args;
160bca3
+
160bca3
+  args.addr = addr;
160bca3
+  args.len = len;
160bca3
+
160bca3
+  /* For ia64, watchpoints must be inserted/removed on each thread so
160bca3
+     we iterate over the lwp list.  */
160bca3
+  if (iterate_over_lwps (&ia64_linux_remove_watchpoint_callback, &args))
160bca3
+    return -1;
160bca3
+
160bca3
+  return 0;
160bca3
+}
160bca3
+
160bca3
+/* Callback to find lwp_info struct for a given lwp.  */
160bca3
+static int
160bca3
+find_lwp_info (struct lwp_info *lp, void *data)
160bca3
+{ 
160bca3
+  int lwp = *(int *)data;
160bca3
+    
160bca3
+  if (lwp == TIDGET (lp->ptid))
160bca3
+    return 1;
36ea501
+
160bca3
+  return 0;
160bca3
+}
36ea501
+
eb9d945
 static int
eb9d945
 ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
160bca3
 {
160bca3
   CORE_ADDR psr;
160bca3
   int tid;
160bca3
   struct siginfo siginfo;
160bca3
+  struct siginfo *siginfo_p;
160bca3
   ptid_t ptid = inferior_ptid;
160bca3
+  struct lwp_info *lp;
eb9d945
   struct regcache *regcache = get_current_regcache ();
36ea501
 
160bca3
   tid = TIDGET(ptid);
eb9d945
@@ -637,10 +709,19 @@ ia64_linux_stopped_data_address (struct 
160bca3
     tid = PIDGET (ptid);
160bca3
   
160bca3
   errno = 0;
160bca3
-  ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
160bca3
+  /* Check to see if we have already cached the siginfo for this
160bca3
+     event.  */
160bca3
+  lp = iterate_over_lwps (find_lwp_info, &tid;;
160bca3
+  if (lp && lp->saved_trap_data != NULL)
160bca3
+    siginfo_p = (struct siginfo *)lp->saved_trap_data;
160bca3
+  else
160bca3
+    {
160bca3
+      siginfo_p = &siginfo;
160bca3
+      ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, siginfo_p);
160bca3
+    }
160bca3
 
160bca3
-  if (errno != 0 || siginfo.si_signo != SIGTRAP || 
160bca3
-      (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
160bca3
+  if (errno != 0 || siginfo_p->si_signo != SIGTRAP || 
160bca3
+      (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
160bca3
     return 0;
160bca3
 
eb9d945
   regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr;;
eb9d945
@@ -648,7 +729,7 @@ ia64_linux_stopped_data_address (struct 
160bca3
                            for the next instruction */
eb9d945
   regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
160bca3
 
160bca3
-  *addr_p = (CORE_ADDR)siginfo.si_addr;
160bca3
+  *addr_p = (CORE_ADDR)siginfo_p->si_addr;
160bca3
   return 1;
36ea501
 }
36ea501
 
eb9d945
@@ -796,6 +877,31 @@ ia64_linux_xfer_partial (struct target_o
c59c374
 			     offset, len);
36ea501
 }
c59c374
 
160bca3
+/* Observer function for a new thread attach.  We need to insert
160bca3
+   existing watchpoints on the new thread.  */
160bca3
+static void
160bca3
+ia64_linux_new_thread (ptid_t ptid)
160bca3
+{
160bca3
+  insert_watchpoints_for_new_thread (ptid, 
160bca3
+		  		     &ia64_linux_insert_one_watchpoint);
160bca3
+}
36ea501
+
160bca3
+/* For ia64 linux, we must save the siginfo data as part of the state
160bca3
+   of a queued SIGTRAP.  This is because siginfo is used to determine
160bca3
+   if a watchpoint has occurred and the information will be lost if
160bca3
+   a SIGSTOP is issued to the thread.  */
160bca3
+void
160bca3
+ia64_linux_save_sigtrap_info (void *queue_data)
160bca3
+{
160bca3
+  struct lwp_info *lp = (struct lwp_info *)queue_data;
36ea501
+
160bca3
+  if (lp->saved_trap_data == NULL)
160bca3
+    lp->saved_trap_data = xmalloc (sizeof(struct siginfo));
160bca3
+
160bca3
+  ptrace (PTRACE_GETSIGINFO, ptid_get_lwp (lp->ptid), (PTRACE_ARG3_TYPE) 0,
160bca3
+          lp->saved_trap_data);
160bca3
+}
160bca3
+
c59c374
 void _initialize_ia64_linux_nat (void);
c59c374
 
c59c374
 void
eb9d945
@@ -834,4 +940,7 @@ _initialize_ia64_linux_nat (void)
c59c374
 
c59c374
   /* Register the target.  */
c59c374
   linux_nat_add_target (t);
c59c374
+
160bca3
+  observer_attach_linux_new_thread (ia64_linux_new_thread);
160bca3
+  observer_attach_sigtrap (ia64_linux_save_sigtrap_info);
c59c374
 }
eb9d945
Index: gdb-6.7/gdb/amd64-linux-nat.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/amd64-linux-nat.c	2007-08-23 20:08:26.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/amd64-linux-nat.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -240,10 +240,9 @@ amd64_linux_dr_get (int regnum)
a51648d
   int tid;
a51648d
   unsigned long value;
a51648d
 
a51648d
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
a51648d
-     multi-threaded processes here.  For now, pretend there is just
a51648d
-     one thread.  */
a51648d
-  tid = PIDGET (inferior_ptid);
a51648d
+  tid = TIDGET (inferior_ptid);
a51648d
+  if (tid == 0)
a51648d
+    tid = PIDGET (inferior_ptid);
a51648d
 
a51648d
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
a51648d
      ptrace call fails breaks debugging remote targets.  The correct
eb9d945
@@ -268,10 +267,9 @@ amd64_linux_dr_set (int regnum, unsigned
a51648d
 {
a51648d
   int tid;
a51648d
 
a51648d
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
a51648d
-     multi-threaded processes here.  For now, pretend there is just
a51648d
-     one thread.  */
a51648d
-  tid = PIDGET (inferior_ptid);
a51648d
+  tid = TIDGET (inferior_ptid);
a51648d
+  if (tid == 0)
a51648d
+    tid = PIDGET (inferior_ptid);
a51648d
 
a51648d
   errno = 0;
a51648d
   ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
eb9d945
Index: gdb-6.7/gdb/s390-nat.c
9231e41
===================================================================
eb9d945
--- gdb-6.7.orig/gdb/s390-nat.c	2007-08-23 20:08:37.000000000 +0200
eb9d945
+++ gdb-6.7/gdb/s390-nat.c	2007-10-13 04:50:11.000000000 +0200
eb9d945
@@ -27,6 +27,7 @@
9231e41
 #include "linux-nat.h"
36ea501
 
160bca3
 #include "s390-tdep.h"
36ea501
+#include "observer.h"
36ea501
 
160bca3
 #include <asm/ptrace.h>
160bca3
 #include <sys/ptrace.h>
eb9d945
@@ -111,14 +112,14 @@ fill_fpregset (const struct regcache *re
eb9d945
 			      (char *)regp + regmap_fpregset[i]);
160bca3
 }
36ea501
 
160bca3
-/* Find the TID for the current inferior thread to use with ptrace.  */
160bca3
+/* Find the TID for use with ptrace.  */
160bca3
 static int
160bca3
-s390_inferior_tid (void)
160bca3
+s390_tid (ptid_t ptid)
160bca3
 {
160bca3
   /* GNU/Linux LWP ID's are process ID's.  */
160bca3
-  int tid = TIDGET (inferior_ptid);
160bca3
+  int tid = TIDGET (ptid);
160bca3
   if (tid == 0)
160bca3
-    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
160bca3
+    tid = PIDGET (ptid); /* Not a threaded program.  */
36ea501
 
160bca3
   return tid;
160bca3
 }
eb9d945
@@ -202,7 +203,7 @@ store_fpregs (const struct regcache *reg
9231e41
 static void
eb9d945
 s390_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
160bca3
 {
160bca3
-  int tid = s390_inferior_tid ();
160bca3
+  int tid = s390_tid (inferior_ptid);
36ea501
 
160bca3
   if (regnum == -1 
160bca3
       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
eb9d945
@@ -218,7 +219,7 @@ s390_linux_fetch_inferior_registers (str
9231e41
 static void
eb9d945
 s390_linux_store_inferior_registers (struct regcache *regcache, int regnum)
160bca3
 {
160bca3
-  int tid = s390_inferior_tid ();
160bca3
+  int tid = s390_tid (inferior_ptid);
36ea501
 
160bca3
   if (regnum == -1 
160bca3
       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
eb9d945
@@ -260,7 +261,7 @@ s390_stopped_by_watchpoint (void)
160bca3
   parea.len = sizeof (per_lowcore);
160bca3
   parea.process_addr = (addr_t) & per_lowcore;
160bca3
   parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
160bca3
-  if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
160bca3
+  if (ptrace (PTRACE_PEEKUSR_AREA, s390_tid (inferior_ptid), &parea) < 0)
9231e41
     perror_with_name (_("Couldn't retrieve watchpoint status"));
36ea501
 
160bca3
   return per_lowcore.perc_storage_alteration == 1
eb9d945
@@ -268,9 +269,9 @@ s390_stopped_by_watchpoint (void)
36ea501
 }
36ea501
 
160bca3
 static void
160bca3
-s390_fix_watch_points (void)
160bca3
+s390_fix_watch_points (ptid_t ptid)
36ea501
 {
160bca3
-  int tid = s390_inferior_tid ();
160bca3
+  int tid = s390_tid (ptid);
160bca3
 
160bca3
   per_struct per_info;
160bca3
   ptrace_area parea;
eb9d945
@@ -307,6 +308,16 @@ s390_fix_watch_points (void)
9231e41
     perror_with_name (_("Couldn't modify watchpoint status"));
36ea501
 }
36ea501
 
160bca3
+/* Callback routine to use with iterate_over_lwps to insert a specified
160bca3
+   watchpoint on all threads.  */
160bca3
+static int
160bca3
+s390_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
160bca3
+{
160bca3
+  s390_fix_watch_points (lwp->ptid);
160bca3
+  return 0;
160bca3
+}
160bca3
+
160bca3
+/* Insert a specified watchpoint on all threads.  */
9231e41
 static int
9231e41
 s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
36ea501
 {
eb9d945
@@ -320,10 +331,24 @@ s390_insert_watchpoint (CORE_ADDR addr, 
160bca3
   area->next = watch_base;
160bca3
   watch_base = area;
36ea501
 
160bca3
-  s390_fix_watch_points ();
160bca3
+  /* For the S390, a watchpoint must be inserted/removed for each
160bca3
+     thread so we iterate over the list of existing lwps.  */
160bca3
+  if (iterate_over_lwps (&s390_insert_watchpoint_callback, NULL))
160bca3
+    return -1;
36ea501
+
21721b8
   return 0;
21721b8
 }
21721b8
 
160bca3
+/* Callback routine to use with iterate_over_lwps to remove a specified
160bca3
+   watchpoint from all threads.  */
160bca3
+static int
160bca3
+s390_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
160bca3
+{
160bca3
+  s390_fix_watch_points (lwp->ptid);
21721b8
+  return 0;
21721b8
+}
21721b8
+
160bca3
+/* Remove a specified watchpoint from all threads.  */
9231e41
 static int
9231e41
 s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
160bca3
 {
eb9d945
@@ -345,7 +370,11 @@ s390_remove_watchpoint (CORE_ADDR addr, 
160bca3
   *parea = area->next;
160bca3
   xfree (area);
36ea501
 
160bca3
-  s390_fix_watch_points ();
160bca3
+  /* For the S390, a watchpoint must be inserted/removed for each
160bca3
+     thread so we iterate over the list of existing lwps.  */
160bca3
+  if (iterate_over_lwps (&s390_remove_watchpoint_callback, NULL))
160bca3
+    return -1;
160bca3
+
160bca3
   return 0;
160bca3
 }
36ea501
 
eb9d945
@@ -361,6 +390,15 @@ s390_region_ok_for_hw_watchpoint (CORE_A
9231e41
   return 1;
160bca3
 }
36ea501
 
160bca3
+/* New thread observer that inserts all existing watchpoints on the
160bca3
+   new thread.  */
160bca3
+static void
160bca3
+s390_linux_new_thread (ptid_t ptid)
160bca3
+{
160bca3
+  /* Add existing watchpoints to new thread.  */
160bca3
+  s390_fix_watch_points (ptid);
160bca3
+}
160bca3
+
9231e41
 
9231e41
 void _initialize_s390_nat (void);
9231e41
 
eb9d945
@@ -386,4 +424,6 @@ _initialize_s390_nat (void)
9231e41
 
9231e41
   /* Register the target.  */
9231e41
   linux_nat_add_target (t);
9231e41
+
160bca3
+  observer_attach_linux_new_thread (s390_linux_new_thread);
9231e41
 }