2012-01-25 Luis Machado * 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). */