This is the mail archive of the gdb-patches@sourceware.org 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]

[patch 0/1] Threaded Watchpoints


Folks,

I took the freedom of refreshing Jeff Johnston's patch for threaded
watchpoints for HEAD in order to keep this feature moving, and
eventually include it for GDB 6.7.

I remember from previous threads that there was some discussion about
the observer implemented by Jeff. Based on comments and suggestions i'll
re-work the patch.

I'm also working on the ppc side of this patch and will submit soon.

Best regards,

-- 
Luis Machado
IBM Linux Technology Center
e-mail: luisgpm@vnet.linux.ibm.com
2007-08-13  Jeff Johnston  <jjohnstn@redhat.com>

    * linux-nat.c: (stop_wait_callback, linux-nat-wait): Notify
	observers of a sigtrap.
	(delete_lwp): Free the saved_trap_data if present.
	* linux-nat.h (struct lwp_info): Add saved_trap_data field.
	(struct linux_watchpoint): New struct.
	* linux-thread-db.c: Add support to always keep lwp info in ptids.
	(attach_thread): Notify observers of a linux
	new thread.
	(thread_db_wait): Call check_event if SIGILL occurs.
	* infrun.c: (handle_inferior_event): For platforms that
	hit watchpoints prior to the data write, mark the watchpoints
	so we know to check them after we step through the write.
	* breakpoint.c (bpstat_stop_status): Fix up watchpoint code.
	(insert_watchpoints_for_new_thread): New function.
	(mark_triggered_watchpoints): Ditto.
	* breakpoint.h (insert_watchpoints_for_new_thread): New prototype.
	(mark_triggered_watchpoints): Ditto.
	* i386-linux-nat.c (i386_linux_dr_get, i386_linux_dr_set): Use
	TIDGET to get PTRACE lpw, otherwise fall back to PIDGET.
	* amd64-linux-nat.c (amd64_linux_dr_get, amd64_linux_dr_set): Ditto.
	* ia64-linux-nat.c: Add support for removing and inserting watchpoints
	on all threads.
	* s390-nat.c: Ditto.
	* Makefile.in: Add observer.h and linux-nat.h to ia64-linux-nat.o
	and s390-nat.o.
	* doc/observer.texi: Add two new observers for linux_new_thread
	and sigtrap.

Index: gdb/doc/observer.texi
===================================================================
--- gdb.orig/doc/observer.texi	2007-08-10 14:32:29.000000000 -0700
+++ gdb/doc/observer.texi	2007-08-13 06:21:29.000000000 -0700
@@ -123,6 +123,16 @@
 The shared library specified by @var{solib} has been unloaded.
 @end deftypefun
 
+@deftypefun void linux_new_thread (ptid_t @var{ptid})
+A new linux thread described by @var{ptid} has been officially attached
+to by gdb.
+@end deftypefun
+
+@deftypefun void sigtrap (void * @var{data})
+A low-level SIGTRAP has been discovered.  This notification can be used to save
+additional state necessary if the trap is deferred for later handling.
+@end deftypefun
+
 @deftypefun void new_objfile (struct objfile *@var{objfile})
 The symbol file specified by @var{objfile} has been loaded.
 Called with @var{objfile} equal to @code{NULL} to indicate
Index: gdb/infrun.c
===================================================================
--- gdb.orig/infrun.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/infrun.c	2007-08-13 06:21:29.000000000 -0700
@@ -1777,9 +1777,19 @@
      single step over a watchpoint without disabling the watchpoint.  */
   if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
     {
+      CORE_ADDR addr = 0;
+
       if (debug_infrun)
 	fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
-      resume (1, 0);
+
+      target_stopped_data_address (&current_target, &addr);
+      mark_triggered_watchpoints (addr);
+      registers_changed ();
+      target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);	/* Single step */
+
+      ecs->waiton_ptid = ecs->ptid;
+      ecs->wp = &(ecs->ws);
+      ecs->infwait_state = infwait_nonstep_watch_state;
       prepare_to_wait (ecs);
       return;
     }
@@ -1790,6 +1800,8 @@
   if (gdbarch_have_nonsteppable_watchpoint (current_gdbarch)
       && STOPPED_BY_WATCHPOINT (ecs->ws))
     {
+      CORE_ADDR addr = 0;
+
       /* At this point, we are stopped at an instruction which has
          attempted to write to a piece of memory under control of
          a watchpoint.  The instruction hasn't actually executed
@@ -1797,15 +1809,12 @@
          now, we would get the old value, and therefore no change
          would seem to have occurred.
 
-         In order to make watchpoints work `right', we really need
-         to complete the memory write, and then evaluate the
-         watchpoint expression.  The following code does that by
-         removing the watchpoint (actually, all watchpoints and
-         breakpoints), single-stepping the target, re-inserting
-         watchpoints, and then falling through to let normal
-         single-step processing handle proceed.  Since this
-         includes evaluating watchpoints, things will come to a
-         stop in the correct manner.  */
+         In order to make watchpoints work `right', we mark the
+	 triggered watchpoints so that after we single step,
+	 we will check for a value change.  */
+
+      target_stopped_data_address (&current_target, &addr);
+      mark_triggered_watchpoints (addr);
 
       if (debug_infrun)
 	fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
@@ -1876,6 +1885,41 @@
 	}
     }
 
+  if (stop_signal == TARGET_SIGNAL_TRAP
+      && trap_expected
+      && gdbarch_single_step_through_delay_p (current_gdbarch)
+      && currently_stepping (ecs))
+    {
+      /* We're trying to step of a breakpoint.  Turns out that we're
+	 also on an instruction that needs to be stepped multiple
+	 times before it's been fully executing. E.g., architectures
+	 with a delay slot.  It needs to be stepped twice, once for
+	 the instruction and once for the delay slot.  */
+      int step_through_delay
+	= gdbarch_single_step_through_delay (current_gdbarch,
+					     get_current_frame ());
+      if (debug_infrun && step_through_delay)
+	fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
+      if (step_range_end == 0 && step_through_delay)
+	{
+	  /* The user issued a continue when stopped at a breakpoint.
+	     Set up for another trap and get out of here.  */
+         ecs->another_trap = 1;
+         keep_going (ecs);
+         return;
+	}
+      else if (step_through_delay)
+	{
+	  /* The user issued a step when stopped at a breakpoint.
+	     Maybe we should stop, maybe we should not - the delay
+	     slot *might* correspond to a line of source.  In any
+	     case, don't decide that here, just set ecs->another_trap,
+	     making sure we single-step again before breakpoints are
+	     re-inserted.  */
+	  ecs->another_trap = 1;
+	}
+    }
+
   /* Look at the cause of the stop, and decide what to do.
      The alternatives are:
      1) break; to really stop and return to the debugger,
@@ -1928,6 +1972,8 @@
          See more comments in inferior.h.  */
       if (stop_soon == STOP_QUIETLY_NO_SIGSTOP)
 	{
+          if (debug_infrun)
+	    fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
 	  stop_stepping (ecs);
 	  if (stop_signal == TARGET_SIGNAL_STOP)
 	    stop_signal = TARGET_SIGNAL_0;
Index: gdb/breakpoint.c
===================================================================
--- gdb.orig/breakpoint.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/breakpoint.c	2007-08-13 06:21:29.000000000 -0700
@@ -808,6 +808,90 @@
     }
 }
 
+/* External function to insert all existing watchpoints on a newly
+   attached thread.  IWPFN is a callback function to perform
+   the target insert watchpoint.  This function is used to support
+   platforms where a watchpoint must be inserted/removed on each
+   individual thread (e.g. ia64-linux and s390-linux).  For
+   ia64 and s390 linux, this function is called via a new thread
+   observer.  */
+int
+insert_watchpoints_for_new_thread (ptid_t new_thread,
+				   insert_watchpoint_ftype *iwpfn)
+{
+  struct bp_location *b;
+  int val = 0;
+  int return_val = 0;
+  struct ui_file *tmp_error_stream = mem_fileopen ();
+  make_cleanup_ui_file_delete (tmp_error_stream);
+
+  /* Explicitly mark the warning -- this will only be printed if
+     there was an error.  */
+  fprintf_unfiltered (tmp_error_stream, "Warning:\n");
+
+  ALL_BP_LOCATIONS (b)
+    {
+      /* Skip disabled breakpoints.  */
+      if (!breakpoint_enabled (b->owner))
+	continue;
+
+      /* For every active watchpoint, we need to insert the watchpoint on
+         the new thread.  */
+      if (b->loc_type == bp_loc_hardware_watchpoint)
+	{
+	  struct value *v = b->owner->val_chain;
+
+	  /* Look at each value on the value chain.  */
+	  for (; v; v = value_next(v))
+	    {
+	      /* If it's a memory location, and GDB actually needed
+		 its contents to evaluate the expression, then we
+		 must watch it.  */
+	      if (VALUE_LVAL (v) == lval_memory
+		  && ! value_lazy (v))
+		{
+		  struct type *vtype = check_typedef (value_type (v));
+
+		  /* We only watch structs and arrays if user asked
+		     for it explicitly, never if they just happen to
+		     appear in the middle of some value chain.  */
+		  if (v == b->owner->val_chain
+		      || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT
+			  && TYPE_CODE (vtype) != TYPE_CODE_ARRAY))
+		    {
+		      CORE_ADDR addr;
+		      int len, type;
+
+		      addr = VALUE_ADDRESS (v) + value_offset (v);
+		      len = TYPE_LENGTH (value_type (v));
+		      type = hw_write;
+		      if (b->owner->type == bp_read_watchpoint)
+			type = hw_read;
+		      else if (b->owner->type == bp_access_watchpoint)
+			type = hw_access;
+		      val = (*iwpfn) (new_thread, addr, len, type);
+		    }
+		}
+	    }
+	}
+
+      if (val)
+	return_val = val;
+    }
+
+  /* Failure to insert a watchpoint on any memory value in the
+     value chain brings us here.  */
+  if (return_val)
+    {
+      fprintf_unfiltered (tmp_error_stream,
+			  "%s\n",
+			  "Could not insert hardware watchpoints on new thread.");
+      target_terminal_ours_for_output ();
+      error_stream (tmp_error_stream);
+    }
+  return return_val;
+}
+
 /* Helper routine: free the value chain for a breakpoint (watchpoint).  */
 
 static void
@@ -1296,6 +1380,7 @@
 {
   struct bp_location *b;
   int val;
+  int return_val = 0;
 
   ALL_BP_LOCATIONS (b)
   {
@@ -1303,10 +1388,10 @@
       {
 	val = remove_breakpoint (b, mark_uninserted);
 	if (val != 0)
-	  return val;
+	  return_val = val;
       }
   }
-  return 0;
+  return return_val;
 }
 
 int
@@ -2209,8 +2294,13 @@
       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;
@@ -2658,6 +2748,54 @@
     }
 }
 
+/* Check watchpoints for a match with a stopped data address.
+
+   STOPPED_DATA_ADDRESS is the address of a triggered watchpoint.
+   A match with an existing watchpoint will cause that watchpoint
+   to be marked as triggered.
+
+   This function is only used for platforms where a watchpoint
+   triggers prior to the data being accessed.  */
+
+void
+mark_triggered_watchpoints (CORE_ADDR stopped_data_address)
+{
+  struct breakpoint *b, *temp;
+  CORE_ADDR addr = stopped_data_address;
+  struct value *v;
+
+  ALL_BREAKPOINTS_SAFE (b, temp)
+  {
+    if (b->type == bp_hardware_watchpoint
+	|| b->type == bp_read_watchpoint
+	|| b->type == bp_access_watchpoint)
+      {
+	for (v = b->val_chain; v; v = value_next(v))
+	  {
+	    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)))
+		      b->watchpoint_triggered = 1;
+		  }
+	      }
+	  }
+      }
+  }
+}
+
 /* Get a bpstat associated with having just stopped at address
    BP_ADDR in thread PTID.  STOPPED_BY_WATCHPOINT is 1 if the
    target thinks we stopped due to a hardware watchpoint, 0 if we
@@ -2788,82 +2926,61 @@
     bs->stop = 1;
     bs->print = 1;
 
-    if (b->type == bp_watchpoint ||
-	b->type == bp_hardware_watchpoint)
-      {
-	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)
-	  {
-	  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 if (b->type == bp_read_watchpoint || 
-	     b->type == bp_access_watchpoint)
+    if (b->type == bp_watchpoint
+	     || b->type == bp_read_watchpoint
+	     || b->type == bp_access_watchpoint
+	     || b->type == bp_hardware_watchpoint)
       {
 	CORE_ADDR addr;
 	struct value *v;
-	int found = 0;
+	int must_check_value = 0;
 
-	if (!target_stopped_data_address (&current_target, &addr))
-	  continue;
-	for (v = b->val_chain; v; v = value_next (v))
+ 	if (b->type == bp_watchpoint
+	    || b->watchpoint_triggered
+	    || (b->type == bp_hardware_watchpoint
+		&& !target_stopped_data_address_p (&current_target)))
 	  {
-	    if (VALUE_LVAL (v) == lval_memory
-		&& ! value_lazy (v))
+	    /* We either have a software watchpoint, a triggered watchpoint
+	       which we have stepped over, or we cannot ascertain what data
+	       address causes a write watchpoint.  In all these
+	       cases, we must check the watchpoint value.  */
+	    b->watchpoint_triggered = 0;
+	    must_check_value = 1;
+	  }
+	else
+	  {
+	    /* At this point, we know target_stopped_data_address () works or
+	       we have a read or access watchpoint and have no alternatives.  */
+	    if (!target_stopped_data_address (&current_target, &addr))
 	      {
-		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))
+		bs->print_it = print_it_noop;
+		bs->stop = 0;
+		continue;
+	      }
+	    for (v = b->val_chain; v; v = value_next(v))
+	      {
+		if (VALUE_LVAL (v) == lval_memory
+		    && ! value_lazy (v))
 		  {
-		    CORE_ADDR vaddr;
+		    struct type *vtype = check_typedef (value_type (v));
 
-		    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;
+		    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)))
+			  must_check_value = 1;
+		      }
 		  }
 	      }
 	  }
-	if (found)
+ 	if (must_check_value)
 	  {
 	    char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n",
 					b->number);
@@ -2892,6 +3009,15 @@
 		break;
 	      case WP_VALUE_NOT_CHANGED:
 		/* Stop.  */
+		if (b->type == bp_hardware_watchpoint
+		    || b->type == bp_watchpoint)
+		  {
+		    /* Don't stop: write watchpoints shouldn't fire if
+		       the value hasn't changed.  */
+		    bs->print_it = print_it_noop;
+		    bs->stop = 0;
+		    continue;
+		  }
 		++(b->hit_count);
 		break;
 	      default:
@@ -2907,7 +3033,7 @@
 		break;
 	      }
 	  }
-	else	/* found == 0 */
+	else	/* must_check_value == 0 */
 	  {
 	    /* This is a case where some watchpoint(s) triggered,
 	       but not at the address of this watchpoint (FOUND
@@ -4208,6 +4334,7 @@
   b->exec_pathname = NULL;
   b->ops = NULL;
   b->pending = 0;
+  b->watchpoint_triggered = 0;
 
   /* Add this breakpoint to the end of the chain
      so that a list of breakpoints will come out in order
Index: gdb/breakpoint.h
===================================================================
--- gdb.orig/breakpoint.h	2007-08-10 14:32:29.000000000 -0700
+++ gdb/breakpoint.h	2007-08-13 06:21:29.000000000 -0700
@@ -422,6 +422,11 @@
 
     /* Is breakpoint pending on shlib loads?  */
     int pending;
+
+    /* Has a watchpoint been triggered?  This is only used for
+       non-continuable watchpoints which trigger prior to the data
+       being modified.  */
+    int watchpoint_triggered;
   };
 
 /* The following stuff is an abstract data type "bpstat" ("breakpoint
@@ -687,6 +692,14 @@
 
 extern int insert_breakpoints (void);
 
+/* The following provides a callback mechanism to insert watchpoints
+   for a new thread.  This is needed, for example, on ia64 linux.  */
+typedef int (insert_watchpoint_ftype) (ptid_t, CORE_ADDR, int, int);
+extern int insert_watchpoints_for_new_thread (ptid_t ptid,
+					      insert_watchpoint_ftype *iwpfn);
+
+extern void mark_triggered_watchpoints (CORE_ADDR);
+
 extern int remove_breakpoints (void);
 
 /* This function can be used to physically insert eventpoints from the
Index: gdb/linux-nat.c
===================================================================
--- gdb.orig/linux-nat.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-nat.c	2007-08-13 06:21:29.000000000 -0700
@@ -36,6 +36,7 @@
 #include "gdbthread.h"
 #include "gdbcmd.h"
 #include "regcache.h"
+#include "observer.h"
 #include "regset.h"
 #include "inf-ptrace.h"
 #include "auxv.h"
@@ -706,6 +707,9 @@
   else
     lwp_list = lp->next;
 
+  if (lp->saved_trap_data)
+    xfree (lp->saved_trap_data);
+
   xfree (lp);
 }
 
@@ -1503,6 +1507,13 @@
 	         user will delete or disable the breakpoint, but the
 	         thread will have already tripped on it.  */
 
+              /* Notify any observers that we have a SIGTRAP.
+                 This is needed on platforms that must save more state
+                 than just the trap.  For example, ia64 linux uses
+                 siginfo to determine if a watchpoint has occurred and
+                 this information gets trashed by a SIGSTOP.  */
+              observer_notify_sigtrap (lp);
+
 	      /* Now resume this LWP and get the SIGSTOP event. */
 	      errno = 0;
 	      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
@@ -2060,6 +2071,14 @@
 				 target_pid_to_str (lp->ptid));
 	    }
 
+          /* For platforms such as ia64, a hardware watchpoint is
+             determined by looking at special information available
+	     at the time time of the trap (siginfo).  This information
+	     is not preserved if we choose to take an event on another
+	     thread and later come back to this event, thus we must
+	     notify an observer so the information can be stored.  */
+          observer_notify_sigtrap (lp);
+
 	  /* Handle GNU/Linux's extended waitstatus for trace events.  */
 	  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
 	    {
Index: gdb/linux-nat.h
===================================================================
--- gdb.orig/linux-nat.h	2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-nat.h	2007-08-13 06:21:29.000000000 -0700
@@ -63,6 +63,18 @@
 
   /* Next LWP in list.  */
   struct lwp_info *next;
+
+  /* Optional saved trap state for when a trap gets pushed back
+     due to multiple events occurring at the same time.  */
+  void *saved_trap_data;
+};
+
+/* Watchpoint description.  */
+struct linux_watchpoint
+{
+  CORE_ADDR addr;
+  int len;
+  int type;
 };
 
 /* Attempt to initialize libthread_db.  */
Index: gdb/Makefile.in
===================================================================
--- gdb.orig/Makefile.in	2007-08-10 14:32:29.000000000 -0700
+++ gdb/Makefile.in	2007-08-13 06:21:33.000000000 -0700
@@ -555,6 +555,7 @@
 	p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
 	prologue-value.c \
 	regcache.c reggroups.c remote.c remote-fileio.c \
+	scm-exp.c scm-lang.c scm-valprint.c \
 	sentinel-frame.c \
 	serial.c ser-base.c ser-unix.c \
 	solib.c solib-null.c source.c \
@@ -787,6 +788,8 @@
 remote_h = remote.h
 rs6000_tdep_h = rs6000-tdep.h $(defs_h)
 s390_tdep_h = s390-tdep.h
+scm_lang_h = scm-lang.h $(scm_tags_h)
+scm_tags_h = scm-tags.h
 score_tdep_h = score-tdep.h
 sentinel_frame_h = sentinel-frame.h
 serial_h = serial.h
@@ -810,7 +813,7 @@
 srec_h = srec.h
 stabsread_h = stabsread.h
 stack_h = stack.h
-symfile_h = symfile.h
+symfile_h = symfile.h $(symtab_h)
 symtab_h = symtab.h
 target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h)
 target_descriptions_h = target-descriptions.h
@@ -833,6 +836,7 @@
 wrapper_h = wrapper.h $(gdb_h)
 xcoffsolib_h = xcoffsolib.h
 xml_support_h = xml-support.h $(gdb_obstack_h) $(vec_h)
+xml_tdesc_h = xml-tdesc.h
 xtensa_tdep_h = xtensa-tdep.h 
 
 #
@@ -958,6 +962,7 @@
 	varobj.o vec.o wrapper.o \
 	jv-lang.o jv-valprint.o jv-typeprint.o \
 	m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
+	scm-exp.o scm-lang.o scm-valprint.o \
 	sentinel-frame.o \
 	complaints.o typeprint.o \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
@@ -1702,7 +1707,7 @@
 	$(gdbcore_h) $(hashtab_h) $(gdb_obstack_h) $(ada_lang_h) \
 	$(completer_h) $(gdb_stat_h) $(ui_out_h) $(block_h) $(infcall_h) \
 	$(dictionary_h) $(exceptions_h) $(annotate_h) $(valprint_h) \
-	$(source_h)
+	$(source_h) $(observer_h)
 ada-typeprint.o: ada-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) \
 	$(symtab_h) $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) \
 	$(target_h) $(command_h) $(gdbcmd_h) $(language_h) $(demangle_h) \
@@ -1758,7 +1763,7 @@
 amd64-linux-nat.o: amd64-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
 	$(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) \
 	$(gdb_proc_service_h) $(gregset_h) $(amd64_tdep_h) \
-	$(i386_linux_tdep_h) $(amd64_nat_h) $(target_h) $(amd64_linux_tdep_h)
+	$(i386_linux_tdep_h) $(amd64_nat_h) $(amd64_linux_tdep_h)
 amd64-linux-tdep.o: amd64-linux-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \
 	$(regcache_h) $(osabi_h) $(symtab_h) $(gdb_string_h) $(amd64_tdep_h) \
 	$(solib_svr4_h) $(gdbtypes_h) $(reggroups_h) $(amd64_linux_tdep_h)
@@ -1817,6 +1822,8 @@
 	$(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) $(objfiles_h) \
 	$(dwarf2_frame_h) $(gdbtypes_h) $(prologue_value_h) \
 	$(target_descriptions_h) $(user_regs_h)
+arm-wince-tdep.o: arm-wince-tdep.c $(defs_h) $(osabi_h) $(solib_svr4_h) \
+	$(target_h) $(gdb_string_h) $(arm_tdep_h)
 auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \
 	$(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \
 	$(elf_common_h)
@@ -1845,8 +1852,8 @@
 	$(gdb_string_h) $(demangle_h) $(annotate_h) $(symfile_h) \
 	$(objfiles_h) $(source_h) $(linespec_h) $(completer_h) $(gdb_h) \
 	$(ui_out_h) $(cli_script_h) $(gdb_assert_h) $(block_h) $(solib_h) \
-	$(solist_h) $(observer_h) $(exceptions_h) $(gdb_events_h) $(mi_common_h) \
-	$(memattr_h) $(ada_lang_h)
+	$(solist_h) $(observer_h) $(exceptions_h) $(gdb_events_h) \
+	$(mi_common_h) $(memattr_h) $(ada_lang_h) $(top_h)
 bsd-kvm.o: bsd-kvm.c $(defs_h) $(cli_cmds_h) $(command_h) $(frame_h) \
 	$(regcache_h) $(target_h) $(value_h) $(gdbcore_h) $(gdb_assert_h) \
 	$(readline_h) $(bsd_kvm_h)
@@ -1975,7 +1982,8 @@
 	$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
 event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
 	$(terminal_h) $(event_loop_h) $(event_top_h) $(interps_h) \
-	$(exceptions_h) $(gdbcmd_h) $(readline_h) $(readline_history_h)
+	$(exceptions_h) $(cli_script_h) $(gdbcmd_h) $(readline_h) \
+	$(readline_history_h)
 exceptions.o: exceptions.c $(defs_h) $(exceptions_h) $(breakpoint_h) \
 	$(target_h) $(inferior_h) $(annotate_h) $(ui_out_h) $(gdb_assert_h) \
 	$(gdb_string_h) $(serial_h)
@@ -2071,7 +2079,7 @@
 	$(osabi_h) $(frame_h) $(frame_unwind_h) $(trad_frame_h) $(symtab_h) \
 	$(objfiles_h) $(inferior_h) $(infcall_h) $(observer_h) \
 	$(hppa_tdep_h) $(solib_som_h) $(solib_pa64_h) $(regset_h) \
-	$(regcache_h) $(exceptions_h) $(gdb_string_h)
+	$(regcache_h) $(exceptions_h) $(gdb_string_h) $(hppa_tdep_h)
 hppa-linux-nat.o: hppa-linux-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
 	$(gdb_string_h) $(inferior_h) $(hppa_tdep_h) $(gregset_h) \
 	$(target_h) $(linux_nat_h)
@@ -2114,7 +2122,8 @@
 	$(i386_linux_tdep_h) $(glibc_tdep_h) $(solib_svr4_h) $(symtab_h)
 i386-nat.o: i386-nat.c $(defs_h) $(breakpoint_h) $(command_h) $(gdbcmd_h)
 i386nbsd-nat.o: i386nbsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \
-	$(target_h) $(i386_tdep_h) $(i386bsd_nat_h) $(bsd_kvm_h)
+	$(target_h) $(i386_tdep_h) $(i386bsd_nat_h) $(nbsd_nat_h) \
+	$(bsd_kvm_h)
 i386nbsd-tdep.o: i386nbsd-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) \
 	$(gdbcore_h) $(regcache_h) $(regset_h) $(osabi_h) $(symtab_h) \
 	$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h) \
@@ -2148,7 +2157,7 @@
 	$(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h)
 ia64-linux-nat.o: ia64-linux-nat.c $(defs_h) $(gdb_string_h) $(inferior_h) \
 	$(target_h) $(gdbcore_h) $(regcache_h) $(ia64_tdep_h) $(gdb_wait_h) \
-	$(gregset_h) $(linux_nat_h)
+	$(gregset_h) $(observer_h) $(linux_nat_h)
 ia64-linux-tdep.o: ia64-linux-tdep.c $(defs_h) $(ia64_tdep_h) \
 	$(arch_utils_h) $(gdbcore_h) $(regcache_h) $(osabi_h) $(solib_svr4_h) \
 	$(symtab_h)
@@ -2203,7 +2212,8 @@
 jv-lang.o: jv-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
 	$(parser_defs_h) $(language_h) $(gdbtypes_h) $(symtab_h) \
 	$(symfile_h) $(objfiles_h) $(gdb_string_h) $(value_h) $(c_lang_h) \
-	$(jv_lang_h) $(gdbcore_h) $(block_h) $(demangle_h) $(dictionary_h)
+	$(jv_lang_h) $(gdbcore_h) $(block_h) $(demangle_h) $(dictionary_h) \
+	$(gdb_assert_h)
 jv-typeprint.o: jv-typeprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
 	$(value_h) $(demangle_h) $(jv_lang_h) $(gdb_string_h) $(typeprint_h) \
 	$(c_lang_h) $(cp_abi_h)
@@ -2220,7 +2230,7 @@
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
 	$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
-	$(objc_lang_h) $(linespec_h) $(exceptions_h)
+	$(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h)
 linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \
 	$(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \
 	$(linux_nat_h)
@@ -2239,10 +2249,13 @@
 m2-lang.o: m2-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
 	$(parser_defs_h) $(language_h) $(m2_lang_h) $(c_lang_h) \
 	$(valprint_h)
-m2-typeprint.o: m2-typeprint.c $(defs_h) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
-	$(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h)
+m2-typeprint.o: m2-typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) \
+	$(symtab_h) $(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) \
+	$(m2_lang_h) $(target_h) $(language_h) $(demangle_h) $(c_lang_h) \
+	$(typeprint_h) $(cp_abi_h) $(gdb_string_h)
 m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
-	$(m2_lang_h) $(c_lang_h)
+	$(expression_h) $(value_h) $(valprint_h) $(language_h) \
+	$(typeprint_h) $(c_lang_h) $(m2_lang_h) $(target_h)
 m32c-tdep.o: m32c-tdep.c $(defs_h) $(gdb_assert_h) $(elf_bfd_h)		\
 	$(elf_m32c_h) $(gdb_sim_m32c_h) $(dis_asm_h) $(gdbtypes_h)	\
 	$(regcache_h) $(arch_utils_h) $(frame_h) $(frame_unwind_h)	\
@@ -2384,7 +2397,7 @@
 monitor.o: monitor.c $(defs_h) $(gdbcore_h) $(target_h) $(exceptions_h) \
 	$(gdb_string_h) $(command_h) $(serial_h) $(monitor_h) $(gdbcmd_h) \
 	$(inferior_h) $(gdb_regex_h) $(srec_h) $(regcache_h)
-ms1-tdep.o: ms1-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \
+mt-tdep.o: mt-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) $(frame_base_h) \
 	$(symtab_h) $(dis_asm_h) $(arch_utils_h) $(gdbtypes_h) \
 	$(gdb_string_h) $(regcache_h) $(reggroups_h) $(gdbcore_h) \
 	$(trad_frame_h) $(inferior_h) $(dwarf2_frame_h) $(infcall_h) \
@@ -2498,8 +2511,6 @@
 remote-fileio.o: remote-fileio.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) \
 	$(remote_h) $(gdb_fileio_h) $(gdb_wait_h) $(gdb_stat_h) \
 	$(exceptions_h) $(remote_fileio_h)
-remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
-	$(serial_h) $(regcache_h)
 remote-m32r-sdi.o: remote-m32r-sdi.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
 	$(inferior_h) $(target_h) $(regcache_h) $(gdb_string_h) $(serial_h)
 remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \
@@ -2527,13 +2538,22 @@
 rs6000-aix-tdep.o: rs6000-aix-tdep.c $(defs_h) $(gdb_string_h) $(osabi_h) \
 	$(regcache_h) $(regset_h) $(rs6000_tdep_h) $(ppc_tdep_h)
 s390-nat.o: s390-nat.c $(defs_h) $(regcache_h) $(inferior_h) \
-	$(s390_tdep_h) $(target_h) $(linux_nat_h)
+	$(s390_tdep_h) $(target_h) $(observer_h) $(linux_nat_h)
 s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
 	$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \
 	$(floatformat_h) $(regcache_h) $(trad_frame_h) $(frame_base_h) \
 	$(frame_unwind_h) $(dwarf2_frame_h) $(reggroups_h) $(regset_h) \
 	$(value_h) $(gdb_assert_h) $(dis_asm_h) $(solib_svr4_h) \
 	$(prologue_value_h) $(s390_tdep_h)
+scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
+	$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
+	$(scm_tags_h)
+scm-lang.o: scm-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
+	$(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \
+	$(scm_tags_h) $(source_h) $(gdb_string_h) $(gdbcore_h) $(infcall_h)
+scm-valprint.o: scm-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \
+	$(expression_h) $(parser_defs_h) $(language_h) $(value_h) \
+	$(scm_lang_h) $(valprint_h) $(gdbcore_h) $(c_lang_h)
 score-tdep.o: score-tdep.c $(defs_h) $(gdb_assert_h) $(inferior_h) \
 	$(symtab_h) $(objfiles_h) $(gdbcore_h) $(target_h) \
 	$(arch_utils_h) $(regcache_h) $(dis_asm_h) $(frame_unwind_h) \
@@ -2626,7 +2646,7 @@
 	$(gregset_h) $(sparc64_tdep_h) $(sparc_tdep_h) \
 	$(sparc_nat_h) $(inferior_h) $(target_h) $(linux_nat_h)
 sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(frame_h) \
-	$(frame_unwind_h) $(dwarf2-frame_h) $(regset_h) $(regcache_h) \
+	$(frame_unwind_h) $(dwarf2_frame_h) $(regset_h) $(regcache_h) \
 	$(gdbarch_h) $(gdbcore_h) $(osabi_h) $(solib_svr4_h) $(symtab_h) \
 	$(trad_frame_h) $(tramp_frame_h) $(sparc64_tdep_h)
 sparc64-nat.o: sparc64-nat.c $(defs_h) $(gdbarch_h) $(sparc64_tdep_h) \
@@ -2727,7 +2747,7 @@
 	$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
 	$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
 	$(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \
-	$(solist_h)
+	$(solist_h) $(ada_lang_h)
 target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
 	$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
 	$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
@@ -2808,7 +2828,7 @@
 	$(frame_unwind_h) $(osabi_h) $(symtab_h) $(trad_frame_h) \
 	$(vax_tdep_h) $(gdb_string_h)
 vax-tdep.o: vax-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) \
-	$(float_format_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
+	$(floatformat_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
 	$(gdbcore_h) $(gdbtypes_h) $(osabi_h) $(regcache_h) $(regset_h) \
 	$(trad_frame_h) $(value_h) $(gdb_string_h) $(vax_tdep_h)
 vec.o: vec.c $(defs_h) $(vec_h)
@@ -2817,6 +2837,7 @@
 	$(regcache_h) $(top_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \
 	$(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) $(exec_h) $(solist_h) \
 	$(solib_h) $(i386_tdep_h) $(i387_tdep_h)
+win32-termcap.o: win32-termcap.c
 wrapper.o: wrapper.c $(defs_h) $(value_h) $(exceptions_h) $(wrapper_h) \
 	$(ui_out_h)
 xcoffread.o: xcoffread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(gdb_stat_h) \
@@ -2836,9 +2857,6 @@
 	$(gdbcmd_h) $(gdbcore_h) $(value_h) $(dis_asm_h) $(inferior_h) \
 	$(gdb_string_h) $(gdb_assert_h) $(arch_utils_h) $(floatformat_h) \
 	$(regcache_h) $(doublest_h) $(osabi_h) $(objfiles_h)
-xtensa-linux-tdep.o: xtensa-linux-tdep.c $(defs_h) $(inferior_h) \
-	$(gdbcore_h) $(regcache_h) $(osabi_h) $(gdb_string_h) \
-	$(xtensa_tdep_h) $(xtensa_linux_tdep_h)
 xtensa-tdep.o: xtensa-tdep.c $(defs_h) $(doublest_h) $(frame_h) \
 	$(frame_unwind_h) $(frame_base_h) $(inferior_h) $(symtab_h) \
 	$(value_h) $(gdbcmd_h) $(gdbcore_h) $(dis_asm_h) $(symfile_h) \
@@ -2878,7 +2896,7 @@
 	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c
 cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \
 	$(ui_out_h) $(gdb_string_h) $(exceptions_h) $(top_h) $(cli_cmds_h) \
-	$(cli_decode_h) $(cli_script_h) $(gdb_assert_h)
+	$(cli_decode_h) $(cli_script_h) $(gdb_assert_h) $(breakpoint_h)
 	$(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-script.c
 cli-setshow.o: $(srcdir)/cli/cli-setshow.c $(defs_h) $(readline_tilde_h) \
 	$(value_h) $(gdb_string_h) $(ui_out_h) $(cli_decode_h) $(cli_cmds_h) \
Index: gdb/linux-thread-db.c
===================================================================
--- gdb.orig/linux-thread-db.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/linux-thread-db.c	2007-08-13 06:21:29.000000000 -0700
@@ -36,6 +36,7 @@
 #include "target.h"
 #include "regcache.h"
 #include "solib-svr4.h"
+#include "observer.h"
 #include "gdbcore.h"
 #include "observer.h"
 #include "linux-nat.h"
@@ -675,6 +676,7 @@
 {
   struct thread_info *tp;
   td_err_e err;
+  ptid_t new_ptid;
 
   /* If we're being called after a TD_CREATE event, we may already
      know about this thread.  There are two ways this can happen.  We
@@ -893,7 +895,8 @@
     thread_db_find_new_threads ();
 
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
-      && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
+      && (ourstatus->value.sig == TARGET_SIGNAL_TRAP
+          || ourstatus->value.sig == TARGET_SIGNAL_ILL))
     /* Check for a thread event.  */
     check_event (ptid);
 
Index: gdb/i386-linux-nat.c
===================================================================
--- gdb.orig/i386-linux-nat.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/i386-linux-nat.c	2007-08-13 06:22:11.000000000 -0700
@@ -587,10 +587,9 @@
   int tid;
   unsigned long value;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
 
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
      ptrace call fails breaks debugging remote targets.  The correct
@@ -615,10 +614,9 @@
 {
   int tid;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
 
   errno = 0;
   ptrace (PTRACE_POKEUSER, tid,
Index: gdb/ia64-linux-nat.c
===================================================================
--- gdb.orig/ia64-linux-nat.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/ia64-linux-nat.c	2007-08-13 06:21:29.000000000 -0700
@@ -29,6 +29,7 @@
 #include "regcache.h"
 #include "ia64-tdep.h"
 #include "linux-nat.h"
+#include "observer.h"
 
 #include <signal.h>
 #include <sys/ptrace.h>
@@ -552,10 +553,10 @@
   return onecount <= 1;
 }
 
+/* Internal routine to insert one watchpoint for a specified thread.  */
 static int
-ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+ia64_linux_insert_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rw)
 {
-  ptid_t ptid = inferior_ptid;
   int idx;
   long dbr_addr, dbr_mask;
   int max_watchpoints = 4;
@@ -600,10 +601,39 @@
   return 0;
 }
 
+/* Internal callback routine which can be used via iterate_over_lwps
+   to insert a specific watchpoint from all active threads.  */
 static int
-ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type)
+ia64_linux_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return ia64_linux_insert_one_watchpoint (lwp->ptid, args->addr,
+                 args->len, args->type);
+}
+
+/* Insert a watchpoint for all threads.  */
+int
+ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+  args.type = rw;
+
+  /* For ia64, watchpoints must be inserted/removed on each thread so
+     we iterate over the lwp list.  */
+  if (iterate_over_lwps (&ia64_linux_insert_watchpoint_callback, &args))
+    return -1;
+
+  return 0;
+}
+
+/* Internal routine to remove one watchpoint for a specified thread.  */
+static int
+ia64_linux_remove_one_watchpoint (ptid_t ptid, CORE_ADDR addr, int len)
 {
-  ptid_t ptid = inferior_ptid;
   int idx;
   long dbr_addr, dbr_mask;
   int max_watchpoints = 4;
@@ -625,13 +655,56 @@
   return -1;
 }
 
+/* Internal callback routine which can be used via iterate_over_lwps
+   to remove a specific watchpoint from all active threads.  */
+static int
+ia64_linux_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  struct linux_watchpoint *args = (struct linux_watchpoint *)data;
+
+  return ia64_linux_remove_one_watchpoint (lwp->ptid, args->addr,
+		 		     	   args->len);
+}
+
+/* Remove a watchpoint for all threads.  */
+int
+ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
+{
+  struct linux_watchpoint args;
+
+  args.addr = addr;
+  args.len = len;
+  args.type = rw;
+
+  /* For ia64, watchpoints must be inserted/removed on each thread so
+     we iterate over the lwp list.  */
+  if (iterate_over_lwps (&ia64_linux_remove_watchpoint_callback, &args))
+    return -1;
+
+  return 0;
+}
+
+/* Callback to find lwp_info struct for a given lwp.  */
+static int
+find_lwp_info (struct lwp_info *lp, void *data)
+{
+  int lwp = *(int *)data;
+
+  if (lwp == TIDGET (lp->ptid))
+    return 1;
+
+  return 0;
+}
+
 static int
 ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
 {
   CORE_ADDR psr;
   int tid;
   struct siginfo siginfo;
+  struct siginfo *siginfo_p;
   ptid_t ptid = inferior_ptid;
+  struct lwp_info *lp;
   struct regcache *regcache = get_current_regcache ();
 
   tid = TIDGET(ptid);
@@ -639,10 +712,19 @@
     tid = PIDGET (ptid);
   
   errno = 0;
-  ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, &siginfo);
+  /* Check to see if we have already cached the siginfo for this
+     event.  */
+  lp = iterate_over_lwps (find_lwp_info, &tid);
+  if (lp && lp->saved_trap_data != NULL)
+    siginfo_p = (struct siginfo *)lp->saved_trap_data;
+  else
+    {
+      siginfo_p = &siginfo;
+      ptrace (PTRACE_GETSIGINFO, tid, (PTRACE_TYPE_ARG3) 0, siginfo_p);
+    }
 
-  if (errno != 0 || siginfo.si_signo != SIGTRAP || 
-      (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
+  if (errno != 0 || siginfo_p->si_signo != SIGTRAP ||
+      (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
     return 0;
 
   regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr);
@@ -650,7 +732,7 @@
                            for the next instruction */
   regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr);
 
-  *addr_p = (CORE_ADDR)siginfo.si_addr;
+  *addr_p = (CORE_ADDR)siginfo_p->si_addr;
   return 1;
 }
 
@@ -798,6 +880,31 @@
 			     offset, len);
 }
 
+/* Observer function for a new thread attach.  We need to insert
+   existing watchpoints on the new thread.  */
+static void
+ia64_linux_new_thread (ptid_t ptid)
+{
+  insert_watchpoints_for_new_thread (ptid,
+		  		     &ia64_linux_insert_one_watchpoint);
+}
+
+/* For ia64 linux, we must save the siginfo data as part of the state
+   of a queued SIGTRAP.  This is because siginfo is used to determine
+   if a watchpoint has occurred and the information will be lost if
+   a SIGSTOP is issued to the thread.  */
+void
+ia64_linux_save_sigtrap_info (void *queue_data)
+{
+  struct lwp_info *lp = (struct lwp_info *)queue_data;
+
+  if (lp->saved_trap_data == NULL)
+    lp->saved_trap_data = xmalloc (sizeof(struct siginfo));
+
+  ptrace (PTRACE_GETSIGINFO, ptid_get_lwp (lp->ptid), (PTRACE_TYPE_ARG3) 0,
+          lp->saved_trap_data);
+}
+
 void _initialize_ia64_linux_nat (void);
 
 void
@@ -836,4 +943,7 @@
 
   /* Register the target.  */
   linux_nat_add_target (t);
+
+  observer_attach_linux_new_thread (ia64_linux_new_thread);
+  observer_attach_sigtrap (ia64_linux_save_sigtrap_info);
 }
Index: gdb/amd64-linux-nat.c
===================================================================
--- gdb.orig/amd64-linux-nat.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/amd64-linux-nat.c	2007-08-13 06:22:11.000000000 -0700
@@ -242,10 +242,9 @@
   int tid;
   unsigned long value;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
 
   /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
      ptrace call fails breaks debugging remote targets.  The correct
@@ -270,10 +269,9 @@
 {
   int tid;
 
-  /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
-     multi-threaded processes here.  For now, pretend there is just
-     one thread.  */
-  tid = PIDGET (inferior_ptid);
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
 
   errno = 0;
   ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value);
Index: gdb/s390-nat.c
===================================================================
--- gdb.orig/s390-nat.c	2007-08-10 14:32:29.000000000 -0700
+++ gdb/s390-nat.c	2007-08-13 06:21:29.000000000 -0700
@@ -29,6 +29,7 @@
 #include "linux-nat.h"
 
 #include "s390-tdep.h"
+#include "observer.h"
 
 #include <asm/ptrace.h>
 #include <sys/ptrace.h>
@@ -113,14 +114,14 @@
 			      (char *)regp + regmap_fpregset[i]);
 }
 
-/* Find the TID for the current inferior thread to use with ptrace.  */
+/* Find the TID for use with ptrace.  */
 static int
-s390_inferior_tid (void)
+s390_tid (ptid_t ptid)
 {
   /* GNU/Linux LWP ID's are process ID's.  */
-  int tid = TIDGET (inferior_ptid);
+  int tid = TIDGET (ptid);
   if (tid == 0)
-    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+    tid = PIDGET (ptid); /* Not a threaded program.  */
 
   return tid;
 }
@@ -204,7 +205,7 @@
 static void
 s390_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
 {
-  int tid = s390_inferior_tid ();
+  int tid = s390_tid (inferior_ptid);
 
   if (regnum == -1 
       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
@@ -220,7 +221,7 @@
 static void
 s390_linux_store_inferior_registers (struct regcache *regcache, int regnum)
 {
-  int tid = s390_inferior_tid ();
+  int tid = s390_tid (inferior_ptid);
 
   if (regnum == -1 
       || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1))
@@ -262,7 +263,7 @@
   parea.len = sizeof (per_lowcore);
   parea.process_addr = (addr_t) & per_lowcore;
   parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore);
-  if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0)
+  if (ptrace (PTRACE_PEEKUSR_AREA, s390_tid (inferior_ptid), &parea) < 0)
     perror_with_name (_("Couldn't retrieve watchpoint status"));
 
   return per_lowcore.perc_storage_alteration == 1
@@ -270,9 +271,9 @@
 }
 
 static void
-s390_fix_watch_points (void)
+s390_fix_watch_points (ptid_t ptid)
 {
-  int tid = s390_inferior_tid ();
+  int tid = s390_tid (ptid);
 
   per_struct per_info;
   ptrace_area parea;
@@ -309,6 +310,16 @@
     perror_with_name (_("Couldn't modify watchpoint status"));
 }
 
+/* Callback routine to use with iterate_over_lwps to insert a specified
+   watchpoint on all threads.  */
+static int
+s390_insert_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  s390_fix_watch_points (lwp->ptid);
+  return 0;
+}
+
+/* Insert a specified watchpoint on all threads.  */
 static int
 s390_insert_watchpoint (CORE_ADDR addr, int len, int type)
 {
@@ -322,10 +333,24 @@
   area->next = watch_base;
   watch_base = area;
 
-  s390_fix_watch_points ();
+  /* For the S390, a watchpoint must be inserted/removed for each
+     thread so we iterate over the list of existing lwps.  */
+  if (iterate_over_lwps (&s390_insert_watchpoint_callback, NULL))
+    return -1;
+
   return 0;
 }
 
+/* Callback routine to use with iterate_over_lwps to remove a specified
+   watchpoint from all threads.  */
+static int
+s390_remove_watchpoint_callback (struct lwp_info *lwp, void *data)
+{
+  s390_fix_watch_points (lwp->ptid);
+  return 0;
+}
+
+/* Remove a specified watchpoint from all threads.  */
 static int
 s390_remove_watchpoint (CORE_ADDR addr, int len, int type)
 {
@@ -347,7 +372,11 @@
   *parea = area->next;
   xfree (area);
 
-  s390_fix_watch_points ();
+  /* For the S390, a watchpoint must be inserted/removed for each
+     thread so we iterate over the list of existing lwps.  */
+  if (iterate_over_lwps (&s390_remove_watchpoint_callback, NULL))
+    return -1;
+
   return 0;
 }
 
@@ -363,6 +392,15 @@
   return 1;
 }
 
+/* New thread observer that inserts all existing watchpoints on the
+   new thread.  */
+static void
+s390_linux_new_thread (ptid_t ptid)
+{
+  /* Add existing watchpoints to new thread.  */
+  s390_fix_watch_points (ptid);
+}
+
 
 void _initialize_s390_nat (void);
 
@@ -388,4 +426,6 @@
 
   /* Register the target.  */
   linux_nat_add_target (t);
+
+  observer_attach_linux_new_thread (s390_linux_new_thread);
 }

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