Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] Fix breakpoint updates for multi-inferior
@ 2012-01-25 21:27 Luis Gustavo
  2012-02-07 23:44 ` Luis Gustavo
  2012-02-08 15:17 ` Pedro Alves
  0 siblings, 2 replies; 14+ messages in thread
From: Luis Gustavo @ 2012-01-25 21:27 UTC (permalink / raw)
  To: gdb-patches

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

Hi,

While working on the target-side condition evaluation patch, i stumbled 
upon the strange situation where GDB had more than a single "inserted" 
location in a list with multiple duplicate locations.

Further investigation showed that the logic for finding the first 
inserted location at a specific address does not work when multiple 
inferiors are being debugged. This code is inside 
update_global_location_list (...).

This is partly because we expect the list of locations to be sorted by 
breakpoint numbers and addresses.

Suppose we're going through locations at address FOO, and we already 
defined the "first" for that set of locations. When a location does not 
match the "first" location of that address, we then assume we've gone 
past the locations at address FOO. This is correct for single inferiors.

Now, consider a multi-inferior scenario and breakpoints with locations 
on multiple inferiors. The code will fail to match two locations due to 
the difference between the locations' program spaces, thus failing to 
mark duplicate locations correctly.

This patch solves this by updating the locations one program space at a 
time, thus preventing multiple insertions of the same location.

This bug shows up when doing multi-inferior debugging in GDBServer. You 
will notice GDB sending multiple insert/remove requests for the same 
address.

OK?

Luis

[-- Attachment #2: 0001-fix_multiprocess_breaks.diff --]
[-- Type: text/x-patch, Size: 6984 bytes --]

2012-01-25  Luis Machado  <lgustavo@codesourcery.com>

	* breakpoint.c (update_global_location_list): Handle *point
	updates one program space at a time.
	* progspace.h (ALL_PROGRAM_SPACES): New helper macro.

Index: gdb/gdb/breakpoint.c
===================================================================
--- gdb.orig/gdb/breakpoint.c	2012-01-25 10:19:35.453821938 -0200
+++ gdb/gdb/breakpoint.c	2012-01-25 11:11:17.721821938 -0200
@@ -10379,6 +10379,7 @@ update_global_location_list (int should_
      built bp_location from the current state of ALL_BREAKPOINTS.  */
   struct bp_location **old_location, **old_locp;
   unsigned old_location_count;
+  struct program_space *cur_pspace;
 
   old_location = bp_location;
   old_location_count = bp_location_count;
@@ -10586,72 +10587,88 @@ update_global_location_list (int should_
 	}
     }
 
-  /* Rescan breakpoints at the same address and section, marking the
-     first one as "first" and any others as "duplicates".  This is so
-     that the bpt instruction is only inserted once.  If we have a
-     permanent breakpoint at the same place as BPT, make that one the
-     official one, and the rest as duplicates.  Permanent breakpoints
-     are sorted first for the same address.
-
-     Do the same for hardware watchpoints, but also considering the
-     watchpoint's type (regular/access/read) and length.  */
-
-  bp_loc_first = NULL;
-  wp_loc_first = NULL;
-  awp_loc_first = NULL;
-  rwp_loc_first = NULL;
-  ALL_BP_LOCATIONS (loc, locp)
+  /* For each program space, go through the list of *points for that specific
+     program space.  This is needed due to assumption (by the code below) that
+     two locations don't match only if they don't have the same address/type,
+     since the location list is sorted first by addresses/breakpoint numbers.
+     The locations also don't match when their program spaces are different
+     (multiprocess).  */
+
+  ALL_PROGRAM_SPACES (cur_pspace)
     {
-      /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always
-	 non-NULL.  */
-      struct bp_location **loc_first_p;
-      b = loc->owner;
-
-      if (!should_be_inserted (loc)
-	  || !breakpoint_address_is_meaningful (b)
-	  /* Don't detect duplicate for tracepoint locations because they are
-	   never duplicated.  See the comments in field `duplicate' of
-	   `struct bp_location'.  */
-	  || is_tracepoint (b))
-	continue;
-
-      /* Permanent breakpoint should always be inserted.  */
-      if (b->enable_state == bp_permanent && ! loc->inserted)
-	internal_error (__FILE__, __LINE__,
-			_("allegedly permanent breakpoint is not "
-			"actually inserted"));
-
-      if (b->type == bp_hardware_watchpoint)
-	loc_first_p = &wp_loc_first;
-      else if (b->type == bp_read_watchpoint)
-	loc_first_p = &rwp_loc_first;
-      else if (b->type == bp_access_watchpoint)
-	loc_first_p = &awp_loc_first;
-      else
-	loc_first_p = &bp_loc_first;
-
-      if (*loc_first_p == NULL
-	  || (overlay_debugging && loc->section != (*loc_first_p)->section)
-	  || !breakpoint_locations_match (loc, *loc_first_p))
+      /* Rescan breakpoints at the same address and section, marking the
+	 first one as "first" and any others as "duplicates".  This is so
+     	 that the bpt instruction is only inserted once.  If we have a
+     	 permanent breakpoint at the same place as BPT, make that one the
+     	 official one, and the rest as duplicates.  Permanent breakpoints
+     	 are sorted first for the same address.
+
+	 Do the same for hardware watchpoints, but also considering the
+	 watchpoint's type (regular/access/read) and length.  */
+
+      bp_loc_first = NULL;
+      wp_loc_first = NULL;
+      awp_loc_first = NULL;
+      rwp_loc_first = NULL;
+
+      ALL_BP_LOCATIONS (loc, locp)
 	{
-	  *loc_first_p = loc;
-	  loc->duplicate = 0;
-	  continue;
-	}
+	  /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always
+	     non-NULL.  */
+	  struct bp_location **loc_first_p;
+	  b = loc->owner;
+
+	  /* Skip this location if it does not belong to the current
+	     program space we are looking for.  */
+	  if (loc->pspace != cur_pspace)
+	    continue;
+
+	  if (!should_be_inserted (loc)
+	      || !breakpoint_address_is_meaningful (b)
+	      /* Don't detect duplicate for tracepoint locations because they
+		 are never duplicated.  See the comments in field `duplicate' of
+	   `	 struct bp_location'.  */
+	      || is_tracepoint (b))
+	    continue;
+
+	  /* Permanent breakpoint should always be inserted.  */
+	  if (b->enable_state == bp_permanent && ! loc->inserted)
+	    internal_error (__FILE__, __LINE__,
+			    _("allegedly permanent breakpoint is not "
+			    "actually inserted"));
+
+	  if (b->type == bp_hardware_watchpoint)
+	    loc_first_p = &wp_loc_first;
+	  else if (b->type == bp_read_watchpoint)
+	    loc_first_p = &rwp_loc_first;
+	  else if (b->type == bp_access_watchpoint)
+	    loc_first_p = &awp_loc_first;
+	  else
+	    loc_first_p = &bp_loc_first;
 
+	  if (*loc_first_p == NULL
+	      || (overlay_debugging && loc->section != (*loc_first_p)->section)
+	      || !breakpoint_locations_match (loc, *loc_first_p))
+	    {
+	      *loc_first_p = loc;
+	      loc->duplicate = 0;
+	      continue;
+	    }
 
-      /* This and the above ensure the invariant that the first location
-	 is not duplicated, and is the inserted one.
-	 All following are marked as duplicated, and are not inserted.  */
-      if (loc->inserted)
-	swap_insertion (loc, *loc_first_p);
-      loc->duplicate = 1;
-
-      if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted
-	  && b->enable_state != bp_permanent)
-	internal_error (__FILE__, __LINE__,
-			_("another breakpoint was inserted on top of "
-			"a permanent breakpoint"));
+	  /* This and the above ensure the invariant that the first location
+	     is not duplicated, and is the inserted one.
+	     All following are marked as duplicated, and are not inserted.  */
+	  if (loc->inserted)
+	    swap_insertion (loc, *loc_first_p);
+	  loc->duplicate = 1;
+
+	  if ((*loc_first_p)->owner->enable_state == bp_permanent
+	      && loc->inserted
+	      && b->enable_state != bp_permanent)
+	    internal_error (__FILE__, __LINE__,
+			    _("another breakpoint was inserted on top of "
+			    "a permanent breakpoint"));
+	}
     }
 
   if (breakpoints_always_inserted_mode () && should_insert
Index: gdb/gdb/progspace.h
===================================================================
--- gdb.orig/gdb/progspace.h	2012-01-25 10:21:24.321821938 -0200
+++ gdb/gdb/progspace.h	2012-01-25 10:41:55.701821938 -0200
@@ -193,6 +193,13 @@ struct program_space
     unsigned num_data;
   };
 
+/* Iterate over all program spaces.  */
+
+#define ALL_PROGRAM_SPACES(PSPACE)	      \
+	for (PSPACE = program_spaces;	      \
+	     PSPACE;			      \
+	     PSPACE = PSPACE->next)
+
 /* The object file that the main symbol table was loaded from (e.g. the
    argument to the "symbol-file" or "file" command).  */
 

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

end of thread, other threads:[~2012-02-24 15:23 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-25 21:27 [PATCH] Fix breakpoint updates for multi-inferior Luis Gustavo
2012-02-07 23:44 ` Luis Gustavo
2012-02-08 15:17 ` Pedro Alves
2012-02-08 15:27   ` Luis Gustavo
2012-02-08 15:47     ` Pedro Alves
2012-02-08 17:28       ` [patch] update_global_location_list my comment fix [Re: [PATCH] Fix breakpoint updates for multi-inferior] Jan Kratochvil
2012-02-08 23:19         ` Luis Gustavo
2012-02-08 23:32           ` Joel Brobecker
2012-02-08 23:40             ` Luis Gustavo
2012-02-09  8:23               ` Jan Kratochvil
2012-02-09 11:05                 ` Luis Gustavo
2012-02-09 11:32                   ` Pedro Alves
2012-02-24 15:24                     ` Luis Gustavo
2012-02-09  8:21         ` [commit] " Jan Kratochvil

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