* [8/9] multiple locations
@ 2007-09-07 22:49 Vladimir Prus
2007-09-07 22:51 ` Vladimir Prus
` (2 more replies)
0 siblings, 3 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-09-07 22:49 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 405 bytes --]
This patch allows a breakpoint to have several breakpoint locations.
There's lot of mechanical changes -- from iteration over breakpoints
to iteration over locations. Also, this splits breakpoint enable/disable
state, changeable by user, from 'shlib_disabled' state, maintained by
gdb and stored inside location. The breakpoint printing code is modified
to print locations of breakpoint. OK?
- Volodya
[-- Attachment #2: mainline_8_multiple_locations.ChangeLog --]
[-- Type: text/plain, Size: 3225 bytes --]
gdb/
* breakpoint.h (enum enable_state): Remove the
bp_shlib_disabled enumerator.
(struct bp_location): New members shlib_disabled,
global_next, enabled and function_name.
Rename pending to condition_not_parsed.
* breakpoint.c (ALL_BP_LOCATIONS): Iterate over global_next.
(ALL_BP_LOCATIONS_SAFE): Likewise.
(breakpoint_enabled): Don't check for pending.
(condition_command): Free and update all locations of
a breakpoint.
(insert_bp_location): Adjust.
(software_breakpoint_inserted_here_p): Don't care
if breakpoint is enabled, as soon as it's inserted.
(print_it_typical): Print bpstat's location, not
bpstat's breakpoint's location.
(bpstat_stop_status): Iterate over all locations, not
all breakpoints.
(print_breakpoint_location): New.
(print_one_breakpoint): Renamed to
(print_one_breakpoint_location): ...this. Take
parameters to describe which location is being
printed. Modify code to properly print header
for several locations and individual locations.
(print_one_breakpoint): Print all locations.
(breakpoint_has_pc): New.
(describe_other_breakpoints): Use the above.
(check_duplicates): Renamed to...
(check_duplicates_for): .. this.
(check_duplicates): Use check_duplicates_for.
(allocate_bp_location): Adjust.
(set_raw_breakpoint_without_location): New,
extracted from set_raw_breakpoint.
(set_breakpoint_location_function): New.
(set_raw_breakpoint): Use
set_raw_breakpoint_without_location.
(make_breakpoint_permanent): Mark all locations
as inserted.
(disable_breakpoints_in_shlibs): Iterate over
locations.
(disable_breakpoints_in_unloaded_shlib): Likewise.
(re_enable_breakpoints_in_shlibs): Likewise.
(mention): Say "pending" when breakpoint has
zero locations. If breakpoint has more than one
location, say so.
(add_location_to_breakpoint): New.
(create_breakpoint): Accept symtabs_and_lines, not
symtab_and_line. Pass extra sals to
add_location_to_breakpoint.
(create_breakpoints): Pass symtabs_and_lines to
create_breakpoints.
(break_command_1): Make pending breakpoints
have zero locations.
(do_captured_breakpoint): Remove wrong allocation.
(clear_command): Iterate over all locations.
(unlink_locations_from_global_list): Renamed
from unlink_location_from_global_list. Remove
all locations.
(delete_breakpoint): Remove all locations.
Iterate over all locations when deciding which
other location to re-enable.
(all_locations_are_pending): New.
(update_breakpoint_locations): Renamed from
update_breakpoint_location. Try to match old
and new locations using names of containing
functions.
(breakpoint_re_set_one): Adjust.
(find_location_by_number): New.
(disable_command): Allow disabling individual location.
(enable_command): Allow enabling individual location.
* breakpoint.c: Adjust all uses of breakpoint's
enable state to for bp_shlib_disabled change.
gdb/testsuite/
* gdb.base/condbreak.exp: Adjust.
* gdb.base/annota1.exp: Adjust for 'info break'
format changes.
* gdb.base/annota3.exp: Likewise.
* gdb.base/break.exp: Likewise.
* gdb.base/condbreak.exp: Likewise.
* gdb.base/pending.exp: Likewise.
* gdb.base/sepdebug.exp: Likewise.
* gdb.base/unload.exp: Likewise.
* gdb.base/ovldbreak.exp: Likewise.
[-- Attachment #3: mainline_8_multiple_locations.diff --]
[-- Type: text/x-diff, Size: 56602 bytes --]
--- gdb/breakpoint.c (/work/mb_mainline/7_pending) (revision 4751)
+++ gdb/breakpoint.c (/work/mb_mainline/8_multiple_locations) (revision 4751)
@@ -275,11 +275,11 @@ static int overlay_events_enabled;
/* Similar iterators for the low-level breakpoints. */
-#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->next)
+#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->global_next)
#define ALL_BP_LOCATIONS_SAFE(B,TMP) \
for (B = bp_location_chain; \
- B ? (TMP=B->next, 1): 0; \
+ B ? (TMP=B->global_next, 1): 0; \
B = TMP)
/* True if breakpoint hit counts should be displayed in breakpoint info. */
@@ -356,7 +356,7 @@ static struct exception_event_record *cu
static int
breakpoint_enabled (struct breakpoint *b)
{
- return (b->enable_state == bp_enabled && !b->pending);
+ return (b->enable_state == bp_enabled);
}
/* Set breakpoint count to NUM. */
@@ -572,10 +572,13 @@ condition_command (char *arg, int from_t
if (b->number == bnum)
{
struct bp_location *loc = b->loc;
- if (loc->cond)
+ for (; loc; loc = loc->next)
{
- xfree (loc->cond);
- loc->cond = 0;
+ if (loc->cond)
+ {
+ xfree (loc->cond);
+ loc->cond = 0;
+ }
}
if (b->cond_string != NULL)
xfree (b->cond_string);
@@ -592,10 +595,11 @@ condition_command (char *arg, int from_t
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = savestring (arg, strlen (arg));
- if (!b->pending)
+ b->condition_not_parsed = 0;
+ for (loc = b->loc; loc; loc = loc->next)
{
- b->loc->cond = parse_exp_1 (&arg,
- block_for_pc (b->loc->address), 0);
+ arg = p;
+ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
@@ -846,7 +850,7 @@ insert_bp_location (struct bp_location *
if (!breakpoint_enabled (bpt->owner))
return 0;
- if (bpt->inserted || bpt->duplicate)
+ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
return 0;
/* Initialize the target-specific information. */
@@ -969,7 +973,7 @@ Note: automatically using hardware break
{
/* See also: disable_breakpoints_in_shlibs. */
val = 0;
- bpt->owner->enable_state = bp_shlib_disabled;
+ bpt->shlib_disabled = 1;
if (!*disabled_breaks)
{
fprintf_unfiltered (tmp_error_stream,
@@ -1808,9 +1812,7 @@ software_breakpoint_inserted_here_p (COR
if (bpt->loc_type != bp_loc_software_breakpoint)
continue;
- if ((breakpoint_enabled (bpt->owner)
- || bpt->owner->enable_state == bp_permanent)
- && bpt->inserted
+ if (bpt->inserted
&& bpt->address == pc) /* bp is enabled and matches pc */
{
if (overlay_debugging
@@ -2160,6 +2162,7 @@ print_it_typical (bpstat bs)
{
struct cleanup *old_chain, *ui_out_chain;
struct breakpoint *b;
+ struct bp_location *bl;
struct ui_stream *stb;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2167,15 +2170,16 @@ print_it_typical (bpstat bs)
which has since been deleted. */
if (bs->breakpoint_at == NULL)
return PRINT_UNKNOWN;
- b = bs->breakpoint_at->owner;
+ bl = bs->breakpoint_at;
+ b = bl->owner;
switch (b->type)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
- if (b->loc->address != b->loc->requested_address)
- breakpoint_adjustment_warning (b->loc->requested_address,
- b->loc->address,
+ if (bl->address != bl->requested_address)
+ breakpoint_adjustment_warning (bl->requested_address,
+ bl->address,
b->number, 1);
annotate_breakpoint (b->number);
ui_out_text (uiout, "\nBreakpoint ");
@@ -2672,7 +2676,8 @@ which its expression is valid.\n");
bpstat
bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint)
{
- struct breakpoint *b, *temp;
+ struct breakpoint *b = NULL;
+ struct bp_location *bl;
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
int real_breakpoint = 0;
/* Root of the chain of bpstat's */
@@ -2681,8 +2686,10 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
bpstat bs = root_bs;
int thread_id = pid_to_thread_id (ptid);
- ALL_BREAKPOINTS_SAFE (b, temp)
+ ALL_BP_LOCATIONS (bl)
{
+ b = bl->owner;
+ gdb_assert (b);
if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
continue;
@@ -2697,11 +2704,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw) /* a non-watchpoint bp */
{
- if (b->loc->address != bp_addr) /* address doesn't match */
+ if (bl->address != bp_addr) /* address doesn't match */
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2719,11 +2726,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
if (b->type == bp_hardware_breakpoint)
{
- if (b->loc->address != bp_addr)
+ if (bl->address != bp_addr)
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2774,7 +2781,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* Come here if it's a watchpoint, or if the break address matches */
- bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */
+ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */
/* Watchpoints may change this, if not found to have triggered. */
bs->stop = 1;
@@ -2926,19 +2933,19 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
{
int value_is_zero = 0;
- if (b->loc->cond)
+ if (bl->cond)
{
/* Need to select the frame, with all that implies
so that the conditions will have the right context. */
select_frame (get_current_frame ());
value_is_zero
- = catch_errors (breakpoint_cond_eval, (b->loc->cond),
+ = catch_errors (breakpoint_cond_eval, (bl->cond),
"Error in testing breakpoint condition:\n",
RETURN_MASK_ALL);
/* FIXME-someday, should give breakpoint # */
free_all_values ();
}
- if (b->loc->cond && value_is_zero)
+ if (bl->cond && value_is_zero)
{
bs->stop = 0;
/* Don't consider this a hit. */
@@ -2985,9 +2992,9 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* The value of a hardware watchpoint hasn't changed, but the
intermediate memory locations we are watching may have. */
if (bs && !bs->stop &&
- (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
- bs->breakpoint_at->owner->type == bp_read_watchpoint ||
- bs->breakpoint_at->owner->type == bp_access_watchpoint))
+ (b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint))
{
remove_breakpoints ();
insert_breakpoints ();
@@ -3349,10 +3356,54 @@ bpstat_get_triggered_catchpoints (bpstat
*cp_list = bs;
}
+static void print_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ char *wrap_indent,
+ struct ui_stream *stb)
+{
+ if (b->source_file)
+ {
+ struct symbol *sym
+ = find_pc_sect_function (loc->address, loc->section);
+ if (sym)
+ {
+ ui_out_text (uiout, "in ");
+ ui_out_field_string (uiout, "func",
+ SYMBOL_PRINT_NAME (sym));
+ ui_out_wrap_hint (uiout, wrap_indent);
+ ui_out_text (uiout, " at ");
+ }
+ ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_text (uiout, ":");
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ struct symtab_and_line sal = find_pc_line (loc->address, 0);
+ char *fullname = symtab_to_fullname (sal.symtab);
+
+ if (fullname)
+ ui_out_field_string (uiout, "fullname", fullname);
+ }
+
+ ui_out_field_int (uiout, "line", b->line_number);
+ }
+ else if (!b->loc)
+ {
+ ui_out_field_string (uiout, "pending", b->addr_string);
+ }
+ else
+ {
+ print_address_symbolic (loc->address, stb->stream, demangle, "");
+ ui_out_field_stream (uiout, "at", stb);
+ }
+}
+
/* Print B to gdb_stdout. */
static void
-print_one_breakpoint (struct breakpoint *b,
- CORE_ADDR *last_addr)
+print_one_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ int loc_number,
+ CORE_ADDR *last_addr)
{
struct command_line *l;
struct symbol *sym;
@@ -3397,30 +3448,79 @@ print_one_breakpoint (struct breakpoint
struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
struct cleanup *bkpt_chain;
+ int header_of_multiple = 0;
+ int part_of_multiple = (loc != NULL);
+
+ gdb_assert (!loc || loc_number != 0);
+ /* See comment in print_one_breakpoint concerning
+ treatment of breakpoints with single disabled
+ location. */
+ if (loc == NULL
+ && (b->loc != NULL
+ && (b->loc->next != NULL || !b->loc->enabled)))
+ header_of_multiple = 1;
+ if (loc == NULL)
+ loc = b->loc;
+
annotate_record ();
bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
/* 1 */
annotate_field (0);
- ui_out_field_int (uiout, "number", b->number);
+ if (part_of_multiple)
+ {
+ char buf[30];
+ sprintf (buf, "%d.%d", b->number, loc_number);
+ ui_out_field_string (uiout, "number", buf);
+ }
+ else
+ {
+ ui_out_field_int (uiout, "number", b->number);
+ }
/* 2 */
annotate_field (1);
- if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
- || ((int) b->type != bptypes[(int) b->type].type))
- internal_error (__FILE__, __LINE__,
- _("bptypes table does not describe type #%d."),
- (int) b->type);
- ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "type");
+ else
+ {
+ if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
+ || ((int) b->type != bptypes[(int) b->type].type))
+ internal_error (__FILE__, __LINE__,
+ _("bptypes table does not describe type #%d."),
+ (int) b->type);
+ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ }
/* 3 */
annotate_field (2);
- ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "disp");
+ else
+ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+
/* 4 */
annotate_field (3);
- ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
- ui_out_spaces (uiout, 2);
+ if (part_of_multiple)
+ ui_out_field_string (uiout, "enabled",
+ loc->shlib_disabled
+ ? (loc->enabled ? "y(p)" : "n(p)")
+ : (loc->enabled ? "y" : "n"));
+ else
+ {
+ int pending = (b->loc == NULL || b->loc->shlib_disabled);
+ /* For header of multiple, there's no point showing pending
+ state -- it will be apparent from the locations. */
+ if (header_of_multiple)
+ pending = 0;
+ ui_out_field_fmt (uiout, "enabled", "%c%s",
+ bpenables[(int) b->enable_state],
+ pending ? "(p)" : "");
+ if (!pending)
+ ui_out_spaces (uiout, 3);
+ }
+
/* 5 and 6 */
strcpy (wrap_indent, " ");
@@ -3433,7 +3533,14 @@ print_one_breakpoint (struct breakpoint
}
if (b->ops != NULL && b->ops->print_one != NULL)
- b->ops->print_one (b, last_addr);
+ {
+ /* Although the print_one can possibly print
+ all locations, calling it here is not likely
+ to get any nice result. So, make sure there's
+ just one location. */
+ gdb_assert (b->loc == NULL || b->loc->next == NULL);
+ b->ops->print_one (b, last_addr);
+ }
else
switch (b->type)
{
@@ -3545,51 +3652,22 @@ print_one_breakpoint (struct breakpoint
if (addressprint)
{
annotate_field (4);
- if (b->pending)
+ if (b->loc == NULL)
ui_out_field_string (uiout, "addr", "<PENDING>");
+ else if (header_of_multiple)
+ ui_out_field_string (uiout, "addr", "<MULTIPLE>");
else
- ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ ui_out_field_core_addr (uiout, "addr", loc->address);
}
annotate_field (5);
- *last_addr = b->loc->address;
- if (b->source_file)
- {
- sym = find_pc_sect_function (b->loc->address, b->loc->section);
- if (sym)
- {
- ui_out_text (uiout, "in ");
- ui_out_field_string (uiout, "func",
- SYMBOL_PRINT_NAME (sym));
- ui_out_wrap_hint (uiout, wrap_indent);
- ui_out_text (uiout, " at ");
- }
- ui_out_field_string (uiout, "file", b->source_file);
- ui_out_text (uiout, ":");
-
- if (ui_out_is_mi_like_p (uiout))
- {
- struct symtab_and_line sal = find_pc_line (b->loc->address, 0);
- char *fullname = symtab_to_fullname (sal.symtab);
-
- if (fullname)
- ui_out_field_string (uiout, "fullname", fullname);
- }
-
- ui_out_field_int (uiout, "line", b->line_number);
- }
- else if (b->pending)
- {
- ui_out_field_string (uiout, "pending", b->addr_string);
- }
- else
- {
- print_address_symbolic (b->loc->address, stb->stream, demangle, "");
- ui_out_field_stream (uiout, "at", stb);
- }
+ if (!header_of_multiple)
+ print_breakpoint_location (b, loc, wrap_indent, stb);
+ if (b->loc)
+ *last_addr = b->loc->address;
break;
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME: This seems to be redundant and lost here; see the
"stop only in" line a little further down. */
@@ -3599,7 +3677,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
- if (frame_id_p (b->frame_id))
+ if (part_of_multiple && frame_id_p (b->frame_id))
{
annotate_field (6);
ui_out_text (uiout, "\tstop only in stack frame at ");
@@ -3609,27 +3687,18 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (b->loc->cond && !ada_exception_catchpoint_p (b))
+ if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
{
/* We do not print the condition for Ada exception catchpoints
because the condition is an internal implementation detail
that we do not want to expose to the user. */
annotate_field (7);
ui_out_text (uiout, "\tstop only if ");
- print_expression (b->loc->cond, stb->stream);
- ui_out_field_stream (uiout, "cond", stb);
- ui_out_text (uiout, "\n");
- }
-
- if (b->pending && b->cond_string)
- {
- annotate_field (7);
- ui_out_text (uiout, "\tstop only if ");
ui_out_field_string (uiout, "cond", b->cond_string);
ui_out_text (uiout, "\n");
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME should make an annotation for this */
ui_out_text (uiout, "\tstop only in thread ");
@@ -3637,7 +3706,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (show_breakpoint_hit_counts && b->hit_count)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
{
/* FIXME should make an annotation for this */
if (ep_is_catchpoint (b))
@@ -3655,10 +3724,10 @@ print_one_breakpoint (struct breakpoint
/* Output the count also if it is zero, but only if this is
mi. FIXME: Should have a better test for this. */
if (ui_out_is_mi_like_p (uiout))
- if (show_breakpoint_hit_counts && b->hit_count == 0)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
ui_out_field_int (uiout, "times", b->hit_count);
- if (b->ignore_count)
+ if (!part_of_multiple && b->ignore_count)
{
annotate_field (8);
ui_out_text (uiout, "\tignore next ");
@@ -3666,7 +3735,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, " hits\n");
}
- if ((l = b->commands))
+ if (!part_of_multiple && (l = b->commands))
{
struct cleanup *script_chain;
@@ -3679,6 +3748,35 @@ print_one_breakpoint (struct breakpoint
do_cleanups (old_chain);
}
+static void
+print_one_breakpoint (struct breakpoint *b,
+ CORE_ADDR *last_addr)
+{
+ print_one_breakpoint_location (b, NULL, 0, last_addr);
+
+ /* If this breakpoint has custom print function,
+ it's already printed. Otherwise, print individual
+ locations, if any. */
+ if (b->ops == NULL || b->ops->print_one == NULL)
+ {
+ /* If breakpoint has a single location that is
+ disabled, we print it as if it had
+ several locations, since otherwise it's hard to
+ represent "breakpoint enabled, location disabled"
+ situation. */
+ if (b->loc
+ && (b->loc->next || !b->loc->enabled)
+ && !ui_out_is_mi_like_p (uiout))
+ {
+ struct bp_location *loc;
+ int n = 1;
+ for (loc = b->loc; loc; loc = loc->next, ++n)
+ print_one_breakpoint_location (b, loc, n, last_addr);
+ }
+ }
+}
+
+
struct captured_breakpoint_query_args
{
int bnum;
@@ -3780,7 +3878,7 @@ breakpoint_1 (int bnum, int allflag)
ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
if (nr_printable_breakpoints > 0)
annotate_field (3);
- ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
+ ui_out_table_header (uiout, 4, ui_left, "enabled", "Enb"); /* 4 */
if (addressprint)
{
if (nr_printable_breakpoints > 0)
@@ -3852,6 +3950,19 @@ maintenance_info_breakpoints (char *bnum
breakpoint_1 (bnum, 1);
}
+static int
+breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
+{
+ struct bp_location *bl = b->loc;
+ for (; bl; bl = bl->next)
+ {
+ if (bl->address == pc
+ && (!overlay_debugging || bl->section == section))
+ return 1;
+ }
+ return 0;
+}
+
/* Print a message describing any breakpoints set at PC. */
static void
@@ -3861,9 +3972,7 @@ describe_other_breakpoints (CORE_ADDR pc
struct breakpoint *b;
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- others++;
+ others += breakpoint_has_pc (b, pc, section);
if (others > 0)
{
if (others == 1)
@@ -3871,26 +3980,24 @@ describe_other_breakpoints (CORE_ADDR pc
else /* if (others == ???) */
printf_filtered (_("Note: breakpoints "));
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- {
- others--;
- printf_filtered ("%d", b->number);
- if (b->thread == -1 && thread != -1)
- printf_filtered (" (all threads)");
- else if (b->thread != -1)
- printf_filtered (" (thread %d)", b->thread);
- printf_filtered ("%s%s ",
- ((b->enable_state == bp_disabled ||
- b->enable_state == bp_shlib_disabled ||
- b->enable_state == bp_call_disabled)
- ? " (disabled)"
- : b->enable_state == bp_permanent
- ? " (permanent)"
- : ""),
- (others > 1) ? ","
- : ((others == 1) ? " and" : ""));
- }
+ if (breakpoint_has_pc (b, pc, section))
+ {
+ others--;
+ printf_filtered ("%d", b->number);
+ if (b->thread == -1 && thread != -1)
+ printf_filtered (" (all threads)");
+ else if (b->thread != -1)
+ printf_filtered (" (thread %d)", b->thread);
+ printf_filtered ("%s%s ",
+ ((b->enable_state == bp_disabled ||
+ b->enable_state == bp_call_disabled)
+ ? " (disabled)"
+ : b->enable_state == bp_permanent
+ ? " (permanent)"
+ : ""),
+ (others > 1) ? ","
+ : ((others == 1) ? " and" : ""));
+ }
printf_filtered (_("also set at pc "));
deprecated_print_address_numeric (pc, 1, gdb_stdout);
printf_filtered (".\n");
@@ -3951,22 +4058,17 @@ breakpoint_address_is_meaningful (struct
that one the official one, and the rest as duplicates. */
static void
-check_duplicates (struct breakpoint *bpt)
+check_duplicates_for (CORE_ADDR address, asection *section)
{
struct bp_location *b;
int count = 0;
struct bp_location *perm_bp = 0;
- CORE_ADDR address = bpt->loc->address;
- asection *section = bpt->loc->section;
-
- if (! breakpoint_address_is_meaningful (bpt))
- return;
ALL_BP_LOCATIONS (b)
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled
+ && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -3999,9 +4101,8 @@ check_duplicates (struct breakpoint *bpt
if (b != perm_bp)
{
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -4018,6 +4119,18 @@ check_duplicates (struct breakpoint *bpt
}
static void
+check_duplicates (struct breakpoint *bpt)
+{
+ struct bp_location *bl = bpt->loc;
+
+ if (! breakpoint_address_is_meaningful (bpt))
+ return;
+
+ for (; bl; bl = bl->next)
+ check_duplicates_for (bl->address, bl->section);
+}
+
+static void
breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
int bnum, int have_bnum)
{
@@ -4089,6 +4202,8 @@ allocate_bp_location (struct breakpoint
loc->owner = bpt;
loc->cond = NULL;
+ loc->shlib_disabled = 0;
+ loc->enabled = 1;
switch (bp_type)
{
@@ -4134,9 +4249,9 @@ allocate_bp_location (struct breakpoint
bp_location_chain = loc;
else
{
- while (loc_p->next)
- loc_p = loc_p->next;
- loc_p->next = loc;
+ while (loc_p->global_next)
+ loc_p = loc_p->global_next;
+ loc_p->global_next = loc;
}
return loc;
@@ -4165,37 +4280,17 @@ static void free_bp_location (struct bp_
should happen, a bogus breakpoint will be left on the chain. */
struct breakpoint *
-set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+set_raw_breakpoint_without_location (enum bptype bptype)
{
struct breakpoint *b, *b1;
- CORE_ADDR adjusted_address;
b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
memset (b, 0, sizeof (*b));
- /* Adjust the breakpoint's address prior to allocating a location.
- Once we call allocate_bp_location(), that mostly uninitialized
- location will be placed on the location chain. Adjustment of the
- breakpoint may cause read_memory_nobpt() to be called and we do
- not want its scan of the location chain to find a breakpoint and
- location that's only been partially initialized. */
- adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
-
- b->loc = allocate_bp_location (b, bptype);
- b->loc->requested_address = sal.pc;
- b->loc->address = adjusted_address;
-
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
- b->loc->section = sal.section;
b->type = bptype;
b->language = current_language->la_language;
b->input_radix = input_radix;
b->thread = -1;
- b->line_number = sal.line;
b->enable_state = bp_enabled;
b->next = 0;
b->silent = 0;
@@ -4207,7 +4302,7 @@ set_raw_breakpoint (struct symtab_and_li
b->forked_inferior_pid = 0;
b->exec_pathname = NULL;
b->ops = NULL;
- b->pending = 0;
+ b->condition_not_parsed = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
@@ -4222,6 +4317,65 @@ set_raw_breakpoint (struct symtab_and_li
b1 = b1->next;
b1->next = b;
}
+ return b;
+}
+
+/* Initialize loc->function_name. */
+static void
+set_breakpoint_location_function (struct bp_location *loc)
+{
+ if (loc->owner->type == bp_breakpoint
+ || loc->owner->type == bp_hardware_breakpoint)
+ {
+ find_pc_partial_function (loc->address, &(loc->function_name),
+ NULL, NULL);
+ if (loc->function_name)
+ loc->function_name = xstrdup (loc->function_name);
+ }
+}
+
+/* set_raw_breakpoint() is a low level routine for allocating and
+ partially initializing a breakpoint of type BPTYPE. The newly
+ created breakpoint's address, section, source file name, and line
+ number are provided by SAL. The newly created and partially
+ initialized breakpoint is added to the breakpoint chain and
+ is also returned as the value of this function.
+
+ It is expected that the caller will complete the initialization of
+ the newly created breakpoint struct as well as output any status
+ information regarding the creation of a new breakpoint. In
+ particular, set_raw_breakpoint() does NOT set the breakpoint
+ number! Care should be taken to not allow an error() to occur
+ prior to completing the initialization of the breakpoint. If this
+ should happen, a bogus breakpoint will be left on the chain. */
+
+struct breakpoint *
+set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+{
+ struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
+ CORE_ADDR adjusted_address;
+
+ /* Adjust the breakpoint's address prior to allocating a location.
+ Once we call allocate_bp_location(), that mostly uninitialized
+ location will be placed on the location chain. Adjustment of the
+ breakpoint may cause read_memory_nobpt() to be called and we do
+ not want its scan of the location chain to find a breakpoint and
+ location that's only been partially initialized. */
+ adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+
+ b->loc = allocate_bp_location (b, bptype);
+ b->loc->requested_address = sal.pc;
+ b->loc->address = adjusted_address;
+
+ if (sal.symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+ b->loc->section = sal.section;
+ b->line_number = sal.line;
+
+ set_breakpoint_location_function (b->loc);
check_duplicates (b);
breakpoints_changed ();
@@ -4235,10 +4389,16 @@ set_raw_breakpoint (struct symtab_and_li
void
make_breakpoint_permanent (struct breakpoint *b)
{
+ struct bp_location *bl;
b->enable_state = bp_permanent;
- /* By definition, permanent breakpoints are already present in the code. */
- b->loc->inserted = 1;
+ /* By definition, permanent breakpoints are already present in the code.
+ Mark all locations as inserted. For now, make_breakpoint_permanent
+ is called in just one place, so it's hard to say if it's reasonable
+ to have permanent breakpoint with multiple locations or not,
+ but it's easy to implmement. */
+ for (bl = b->loc; bl; bl = bl->next)
+ bl->inserted = 1;
}
static struct breakpoint *
@@ -4431,20 +4591,28 @@ create_solib_event_breakpoint (CORE_ADDR
void
disable_breakpoints_in_shlibs (void)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
+ struct breakpoint *b = loc->owner;
+ /* We apply the check to all breakpoints, including disabled
+ for those with loc->duplicate set. This is so that when breakpoint
+ becomes enabled, or the duplicate is removed, gdb will try to insert
+ all breakpoints. If we don't set shlib_disabled here, we'll try
+ to insert those breakpoints and fail. */
if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
- && breakpoint_enabled (b) && !b->loc->duplicate
+ && !loc->shlib_disabled
#ifdef PC_SOLIB
- && PC_SOLIB (b->loc->address)
+ && PC_SOLIB (loc->address)
#else
- && solib_address (b->loc->address)
+ && solib_address (loc->address)
#endif
)
- b->enable_state = bp_shlib_disabled;
+ {
+ loc->shlib_disabled = 1;
+ }
}
}
@@ -4454,27 +4622,28 @@ disable_breakpoints_in_shlibs (void)
void
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
- if ((b->loc->loc_type == bp_loc_hardware_breakpoint
- || b->loc->loc_type == bp_loc_software_breakpoint)
- && breakpoint_enabled (b) && !b->loc->duplicate)
+ struct breakpoint *b = loc->owner;
+ if ((loc->loc_type == bp_loc_hardware_breakpoint
+ || loc->loc_type == bp_loc_software_breakpoint)
+ && !loc->shlib_disabled)
{
#ifdef PC_SOLIB
- char *so_name = PC_SOLIB (b->loc->address);
+ char *so_name = PC_SOLIB (loc->address);
#else
- char *so_name = solib_address (b->loc->address);
+ char *so_name = solib_address (loc->address);
#endif
if (so_name && !strcmp (so_name, solib->so_name))
{
- b->enable_state = bp_shlib_disabled;
+ loc->shlib_disabled = 1;
/* At this point, we cannot rely on remove_breakpoint
succeeding so we must mark the breakpoint as not inserted
to prevent future errors occurring in remove_breakpoints. */
- b->loc->inserted = 0;
+ loc->inserted = 0;
if (!disabled_shlib_breaks)
{
target_terminal_ours_for_output ();
@@ -4894,7 +5063,7 @@ mention (struct breakpoint *b)
{
/* i18n: cagney/2005-02-11: Below needs to be merged into a
single string. */
- if (b->pending)
+ if (b->loc == NULL)
{
printf_filtered (_(" (%s) pending."), b->addr_string);
}
@@ -4908,6 +5077,16 @@ mention (struct breakpoint *b)
if (b->source_file)
printf_filtered (": file %s, line %d.",
b->source_file, b->line_number);
+
+ if (b->loc->next)
+ {
+ struct bp_location *loc = b->loc;
+ int n = 0;
+ for (; loc; loc = loc->next)
+ ++n;
+ printf_filtered (" (%d locations)", n);
+ }
+
}
}
do_cleanups (old_chain);
@@ -4917,6 +5096,24 @@ mention (struct breakpoint *b)
}
\f
+static struct bp_location *
+add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+ const struct symtab_and_line *sal)
+{
+ struct bp_location *loc, **tmp;
+
+ loc = allocate_bp_location (b, bptype);
+ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
+ ;
+ *tmp = loc;
+ loc->requested_address = sal->pc;
+ loc->address = adjust_breakpoint_address (loc->requested_address,
+ bptype);
+ loc->section = sal->section;
+
+ set_breakpoint_location_function (loc);
+ return loc;
+}
/* Create a breakpoint with SAL as location. Use ADDR_STRING
as textual description of the location, and COND_STRING
@@ -4926,13 +5123,14 @@ mention (struct breakpoint *b)
create_breakpoints function. */
static void
-create_breakpoint (struct symtab_and_line sal, char *addr_string,
+create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count, int from_tty,
struct breakpoint *pending_bp)
{
- struct breakpoint *b;
+ struct breakpoint *b = NULL;
+ int i;
if (type == bp_hardware_breakpoint)
{
@@ -4946,50 +5144,46 @@ create_breakpoint (struct symtab_and_lin
error (_("Hardware breakpoints used exceeds limit."));
}
- if (from_tty)
- describe_other_breakpoints (sal.pc, sal.section, thread);
-
- b = set_raw_breakpoint (sal, type);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->thread = thread;
+ for (i = 0; i < sals.nelts; ++i)
+ {
+ struct symtab_and_line sal = sals.sals[i];
+ struct bp_location *loc;
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc, sal.section, thread);
+
+ if (i == 0)
+ {
+ b = set_raw_breakpoint (sal, type);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->thread = thread;
- b->cond_string = cond_string;
- b->ignore_count = ignore_count;
- b->enable_state = bp_enabled;
- b->disposition = disposition;
- /* If resolving a pending breakpoint, a check must be made to see if
- the user has specified a new condition or commands for the
- breakpoint. A new condition will override any condition that was
- initially specified with the initial breakpoint command. */
- if (pending_bp)
- {
- if (pending_bp->cond_string)
- b->cond_string = savestring (pending_bp->cond_string,
- strlen (pending_bp->cond_string));
-
- /* If there are commands associated with the breakpoint, they should
- be copied too. */
- if (pending_bp->commands)
- b->commands = copy_command_lines (pending_bp->commands);
-
- /* We have to copy over the ignore_count and thread as well. */
- b->ignore_count = pending_bp->ignore_count;
- b->thread = pending_bp->thread;
- }
+ b->cond_string = cond_string;
+ b->ignore_count = ignore_count;
+ b->enable_state = bp_enabled;
+ b->disposition = disposition;
- if (b->cond_string)
- {
- char *arg = b->cond_string;
- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
- if (*arg)
+ loc = b->loc;
+ }
+ else
{
- if (pending_bp)
- error (_("Junk at end of pending breakpoint condition expression"));
- else
- error (_("Garbage %s follows condition"), arg);
+ loc = add_location_to_breakpoint (b, type, &sal);
+ }
+
+ if (b->cond_string)
+ {
+ char *arg = b->cond_string;
+ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ {
+ if (pending_bp)
+ error (_("Junk at end of pending breakpoint condition expression"));
+ else
+ error (_("Garbage %s follows condition"), arg);
+ }
}
- }
+ }
if (addr_string)
b->addr_string = addr_string;
@@ -5031,7 +5225,11 @@ create_breakpoints (struct symtabs_and_l
int i;
for (i = 0; i < sals.nelts; ++i)
{
- create_breakpoint (sals.sals[i], addr_string[i],
+ struct symtabs_and_lines sals2;
+ sals2.sals = sals.sals + i;
+ sals2.nelts = 1;
+
+ create_breakpoint (sals2, addr_string[i],
cond_string, type, disposition,
thread, ignore_count, from_tty,
pending_bp);
@@ -5360,19 +5558,19 @@ break_command_1 (char *arg, int flag, in
make_cleanup (xfree, copy_arg);
- b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
- : bp_breakpoint);
+ b = set_raw_breakpoint_without_location (hardwareflag
+ ? bp_hardware_breakpoint
+ : bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->loc->cond = NULL;
b->thread = thread;
b->addr_string = addr_string[0];
b->cond_string = cond_string;
b->ignore_count = ignore_count;
- b->pending = 1;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->from_tty = from_tty;
b->flag = flag;
+ b->condition_not_parsed = 1;
mention (b);
}
@@ -5411,7 +5609,7 @@ do_captured_breakpoint (struct ui_out *u
struct cleanup *breakpoint_chain = NULL;
int i;
char **addr_string;
- char *cond_string;
+ char *cond_string = 0;
char *address_end;
@@ -5440,10 +5638,6 @@ do_captured_breakpoint (struct ui_out *u
cond = xcalloc (sals.nelts, sizeof (struct expression *));
make_cleanup (xfree, cond);
- /* Allocate space for all the cond strings. */
- cond_string = xcalloc (sals.nelts, sizeof (char **));
- make_cleanup (xfree, cond_string);
-
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
to be part of a breakpoint. If the breakpoint create goes
@@ -6733,23 +6927,35 @@ clear_command (char *arg, int from_tty)
breakpoint chain, and add them to the 'found' chain. */
ALL_BREAKPOINTS_SAFE (b, tmp)
{
+ int match = 0;
/* Are we going to delete b? */
if (b->type != bp_none
&& b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- /* Not if b is a watchpoint of any sort... */
- && (((sal.pc && (b->loc->address == sal.pc))
- && (!section_is_overlay (b->loc->section)
- || b->loc->section == sal.section))
- /* Yes, if sal.pc matches b (modulo overlays). */
- || ((default_match || (0 == sal.pc))
- && b->source_file != NULL
- && sal.symtab != NULL
- && strcmp (b->source_file, sal.symtab->filename) == 0
- && b->line_number == sal.line)))
- /* Yes, if sal source file and line matches b. */
+ && b->type != bp_access_watchpoint)
+ {
+ struct bp_location *loc = b->loc;
+ for (; loc; loc = loc->next)
+ {
+ int pc_match = sal.pc
+ && (loc->address == sal.pc)
+ && (!section_is_overlay (loc->section)
+ || loc->section == sal.section);
+ int line_match = ((default_match || (0 == sal.pc))
+ && b->source_file != NULL
+ && sal.symtab != NULL
+ && strcmp (b->source_file, sal.symtab->filename) == 0
+ && b->line_number == sal.line);
+ if (pc_match || line_match)
+ {
+ match = 1;
+ break;
+ }
+ }
+ }
+
+ if (match)
{
/* Remove it from breakpoint_chain... */
if (b == breakpoint_chain)
@@ -6824,6 +7030,35 @@ breakpoint_auto_delete (bpstat bs)
}
}
+/* Remove locations of breakpoint BPT from
+ the global list of breakpoint locations. */
+
+static void
+unlink_locations_from_global_list (struct breakpoint *bpt)
+{
+ /* This code assumes that the locations
+ of a breakpoint are found in the global list
+ in the same order, but not necessary adjacent. */
+ struct bp_location **tmp = &bp_location_chain;
+ struct bp_location *here = bpt->loc;
+
+ if (here == NULL)
+ return;
+
+ for (; *tmp && here;)
+ {
+ if (*tmp == here)
+ {
+ *tmp = here->global_next;
+ here = here->next;
+ }
+ else
+ {
+ tmp = &((*tmp)->global_next);
+ }
+ }
+}
+
/* Delete a breakpoint and clean up all traces of it in the data
structures. */
@@ -6856,17 +7091,23 @@ delete_breakpoint (struct breakpoint *bp
deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
- if (bpt->loc->inserted)
- remove_breakpoint (bpt->loc, mark_inserted);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ if (loc->inserted)
+ remove_breakpoint (loc, mark_inserted);
- free_valchain (bpt->loc);
+ free_valchain (loc);
+
+ if (loc->cond)
+ xfree (loc->cond);
+
+ if (loc->function_name)
+ xfree (loc->function_name);
+ }
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
- if (bp_location_chain == bpt->loc)
- bp_location_chain = bpt->loc->next;
-
/* If we have callback-style exception catchpoints, don't go through
the adjustments to the C++ runtime library etc. if the inferior
isn't actually running. target_enable_exception_callback for a
@@ -6896,82 +7137,83 @@ delete_breakpoint (struct breakpoint *bp
break;
}
- ALL_BP_LOCATIONS (loc)
- if (loc->next == bpt->loc)
- {
- loc->next = bpt->loc->next;
- break;
- }
+ unlink_locations_from_global_list (bpt);
check_duplicates (bpt);
- /* If this breakpoint was inserted, and there is another breakpoint
- at the same address, we need to insert the other breakpoint. */
- if (bpt->loc->inserted
- && bpt->type != bp_hardware_watchpoint
+
+ if (bpt->type != bp_hardware_watchpoint
&& bpt->type != bp_read_watchpoint
&& bpt->type != bp_access_watchpoint
&& bpt->type != bp_catch_fork
&& bpt->type != bp_catch_vfork
&& bpt->type != bp_catch_exec)
- {
- ALL_BREAKPOINTS (b)
- if (b->loc->address == bpt->loc->address
- && b->loc->section == bpt->loc->section
- && !b->loc->duplicate
- && b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && !b->pending
- && b->enable_state != bp_call_disabled)
- {
- int val;
-
- /* We should never reach this point if there is a permanent
- breakpoint at the same address as the one being deleted.
- If there is a permanent breakpoint somewhere, it should
- always be the only one inserted. */
- if (b->enable_state == bp_permanent)
- internal_error (__FILE__, __LINE__,
- _("another breakpoint was inserted on top of "
- "a permanent breakpoint"));
-
- memset (&b->loc->target_info, 0, sizeof (b->loc->target_info));
- b->loc->target_info.placed_address = b->loc->address;
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (&b->loc->target_info);
- else
- val = target_insert_breakpoint (&b->loc->target_info);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ /* If this breakpoint location was inserted, and there is
+ another breakpoint at the same address, we need to
+ insert the other breakpoint. */
+ if (loc->inserted)
+ {
+ struct bp_location *loc2;
+ ALL_BP_LOCATIONS (loc2)
+ if (loc2->address == loc->address
+ && loc2->section == loc->section
+ && !loc->duplicate
+ && loc2->owner->enable_state != bp_disabled
+ && loc2->enabled
+ && !loc2->shlib_disabled
+ && loc2->owner->enable_state != bp_call_disabled)
+ {
+ int val;
- /* If there was an error in the insert, print a message, then stop execution. */
- if (val != 0)
- {
- struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
-
+ /* We should never reach this point if there is a permanent
+ breakpoint at the same address as the one being deleted.
+ If there is a permanent breakpoint somewhere, it should
+ always be the only one inserted. */
+ if (loc2->owner->enable_state == bp_permanent)
+ internal_error (__FILE__, __LINE__,
+ _("another breakpoint was inserted on top of "
+ "a permanent breakpoint"));
+
+ memset (&loc2->target_info, 0, sizeof (loc2->target_info));
+ loc2->target_info.placed_address = loc2->address;
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (&loc2->target_info);
+ else
+ val = target_insert_breakpoint (&loc2->target_info);
- if (b->type == bp_hardware_breakpoint)
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d.\n"
- "You may have requested too many hardware breakpoints.\n",
- b->number);
- }
- else
- {
- fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
- fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
- deprecated_print_address_numeric (b->loc->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- }
-
- fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
- target_terminal_ours_for_output ();
- error_stream(tmp_error_stream);
- }
- else
- b->loc->inserted = 1;
- }
- }
+ /* If there was an error in the insert, print a message, then stop execution. */
+ if (val != 0)
+ {
+ struct ui_file *tmp_error_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_error_stream);
+
+
+ if (b->type == bp_hardware_breakpoint)
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert hardware breakpoint %d.\n"
+ "You may have requested too many hardware breakpoints.\n",
+ b->number);
+ }
+ else
+ {
+ fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
+ fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
+ deprecated_print_address_numeric (loc2->address, 1, tmp_error_stream);
+ fprintf_filtered (tmp_error_stream, ": %s.\n",
+ safe_strerror (val));
+ }
+
+ fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
+ target_terminal_ours_for_output ();
+ error_stream(tmp_error_stream);
+ }
+ else
+ loc2->inserted = 1;
+ }
+ }
+ }
free_command_lines (&bpt->commands);
if (bpt->cond_string != NULL)
@@ -7013,9 +7255,12 @@ delete_breakpoint (struct breakpoint *bp
bp, we mark it as deleted before freeing its storage. */
bpt->type = bp_none;
- if (bpt->loc->cond)
- xfree (bpt->loc->cond);
- xfree (bpt->loc);
+ for (loc = bpt->loc; loc;)
+ {
+ struct bp_location *loc_next = loc->next;
+ xfree (loc);
+ loc = loc_next;
+ }
xfree (bpt);
}
@@ -7083,94 +7328,95 @@ delete_command (char *arg, int from_tty)
map_breakpoint_numbers (arg, delete_breakpoint);
}
-static void
-unlink_locations_from_global_list (struct breakpoint *bpt)
- /* Remove locations of this breakpoint from the list of
- all breakpoint locations. */
+static int
+all_locations_are_pending (struct bp_location *loc)
{
- struct bp_location **tmp = &bp_location_chain;
- struct bp_location *here = bpt->loc;
-
- if (here == NULL)
- return;
-
- for (; *tmp && *tmp != here; tmp = &((*tmp)->next));
- gdb_assert (*tmp);
-
- *tmp = here->next;
+ for (; loc; loc = loc->next)
+ if (!loc->shlib_disabled)
+ return 0;
+ return 1;
}
-
static void
-update_breakpoint_location (struct breakpoint *b,
- struct symtabs_and_lines sals)
+update_breakpoint_locations (struct breakpoint *b,
+ struct symtabs_and_lines sals)
{
int i;
char *s;
- /* FIXME: memleak. */
- struct bp_location *existing = b->loc;
- struct bp_location *loc;
- struct symtab_and_line sal;
-
- if (b->enable_state == bp_shlib_disabled && sals.nelts == 0)
+ struct bp_location *existing_locations = b->loc;
+
+ /* If there's no new locations, and all existing locations
+ are pending, don't do anything. This optimizes
+ the common case where all locations are in the same
+ shared library, that was unloaded. We'd like to
+ retain the location, so that when the library
+ is loaded again, we don't loose the enabled/disabled
+ status of the individual locations. */
+ if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
return;
unlink_locations_from_global_list (b);
b->loc = NULL;
- gdb_assert (sals.nelts == 0 || sals.nelts == 1);
- if (sals.nelts == 0)
- return;
- sal = sals.sals[0];
-
- loc = allocate_bp_location (b, b->type);
- loc->requested_address = sal.pc;
- loc->address = adjust_breakpoint_address (loc->requested_address,
- b->type);
- loc->section = sal.section;
- b->loc = loc;
-
- /* Reparse conditions, they might contain references to the
- old symtab. */
- if (b->cond_string != NULL)
+ for (i = 0; i < sals.nelts; ++i)
{
- struct gdb_exception e;
-
- s = b->cond_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc),
- 0);
- }
- if (e.reason < 0)
- {
- warning (_("failed to reevaluate condition for breakpoint %d: %s"),
- b->number, e.message);
- b->enable_state = bp_disabled;
- }
- }
+ struct bp_location *new_loc =
+ add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
- if (b->source_file != NULL)
- xfree (b->source_file);
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file =
- savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
+ /* Reparse conditions, they might contain references to the
+ old symtab. */
+ if (b->cond_string != NULL)
+ {
+ struct gdb_exception e;
- if (b->line_number == 0)
- b->line_number = sal.line;
+ s = b->cond_string;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc),
+ 0);
+ }
+ if (e.reason < 0)
+ {
+ warning (_("failed to reevaluate condition for breakpoint %d: %s"),
+ b->number, e.message);
+ new_loc->enabled = 0;
+ }
+ }
- if (b->enable_state == bp_shlib_disabled)
- b->enable_state = bp_enabled;
+ if (b->source_file != NULL)
+ xfree (b->source_file);
+ if (sals.sals[i].symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file =
+ savestring (sals.sals[i].symtab->filename,
+ strlen (sals.sals[i].symtab->filename));
- b->pending = 0;
+ if (b->line_number == 0)
+ b->line_number = sals.sals[i].line;
+ }
- check_duplicates (b);
+ /* If possible, carry over 'disable' status from existing breakpoints. */
+ {
+ struct bp_location *e = existing_locations;
+ for (; e; e = e->next)
+ {
+ if (!e->enabled && e->function_name)
+ {
+ struct bp_location *l = b->loc;
+ for (; l; l = l->next)
+ if (l->function_name
+ && strcmp (e->function_name, l->function_name) == 0)
+ {
+ l->enabled = 0;
+ break;
+ }
+ }
+ }
+ }
- if (existing)
- free_bp_location (existing);
+ if (existing_locations)
+ free_bp_location (existing_locations);
}
@@ -7227,8 +7473,10 @@ breakpoint_re_set_one (void *bint)
don't need extra messages. If breakpoint is in bp_shlib_disabled
state, then user already saw the message about that breakpoint
being disabled, and don't want to see more errors. */
- if (not_found && (b->pending || b->enable_state == bp_shlib_disabled
- || b->enable_state == bp_disabled))
+ if (not_found
+ && (b->condition_not_parsed
+ || (b->loc && b->loc->shlib_disabled)
+ || b->enable_state == bp_disabled))
not_found_and_ok = 1;
if (!not_found_and_ok)
@@ -7249,7 +7497,7 @@ breakpoint_re_set_one (void *bint)
gdb_assert (sals.nelts == 1);
resolve_sal_pc (&sals.sals[0]);
- if (b->pending && s && s[0])
+ if (b->condition_not_parsed && s && s[0])
{
char *cond_string = 0;
int thread = -1;
@@ -7258,9 +7506,14 @@ breakpoint_re_set_one (void *bint)
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
+ b->condition_not_parsed = 0;
}
- update_breakpoint_location (b, sals);
+ update_breakpoint_locations (b, sals);
+
+ /* Now that this is re-enabled, check_duplicates
+ can be used. */
+ check_duplicates (b);
xfree (sals.sals);
break;
@@ -7524,6 +7777,48 @@ map_breakpoint_numbers (char *args, void
}
}
+static struct bp_location *
+find_location_by_number (char *number)
+{
+ char *dot = strchr (number, '.');
+ char *p1;
+ int bp_num;
+ int loc_num;
+ struct breakpoint *b;
+ struct bp_location *loc;
+
+ *dot = '\0';
+
+ p1 = number;
+ bp_num = get_number_or_range (&p1);
+ if (bp_num == 0)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bp_num)
+ {
+ break;
+ }
+
+ if (!b || b->number != bp_num)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ p1 = dot+1;
+ loc_num = get_number_or_range (&p1);
+ if (loc_num == 0)
+ error (_("Bad breakpoint location number '%s'"), number);
+
+ --loc_num;
+ loc = b->loc;
+ for (;loc_num && loc; --loc_num, loc = loc->next)
+ ;
+ if (!loc)
+ error (_("Bad breakpoint location number '%s'"), dot+1);
+
+ return loc;
+}
+
+
/* Set ignore-count of breakpoint number BPTNUM to COUNT.
If from_tty is nonzero, it prints a message to that effect,
which ends with a period (no newline). */
@@ -7579,6 +7874,13 @@ disable_command (char *args, int from_tt
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 0;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, disable_breakpoint);
}
@@ -7711,6 +8013,13 @@ enable_command (char *args, int from_tty
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 1;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, enable_breakpoint);
}
--- gdb/breakpoint.h (/work/mb_mainline/7_pending) (revision 4751)
+++ gdb/breakpoint.h (/work/mb_mainline/8_multiple_locations) (revision 4751)
@@ -143,9 +143,6 @@ enum enable_state
{
bp_disabled, /* The eventpoint is inactive, and cannot trigger. */
bp_enabled, /* The eventpoint is active, and can trigger. */
- bp_shlib_disabled, /* The eventpoint's address is in an unloaded solib.
- The eventpoint will be automatically enabled
- and reset when that solib is loaded. */
bp_call_disabled, /* The eventpoint has been disabled while a call
into the inferior is "in flight", because some
eventpoints interfere with the implementation of
@@ -232,9 +229,14 @@ enum bp_loc_type
struct bp_location
{
- /* Chain pointer to the next breakpoint location. */
+ /* Chain pointer to the next breakpoint location for
+ the same parent breakpoint. */
struct bp_location *next;
+ /* Pointer to the next breakpoint location, in a global
+ list of all breakpoint locations. */
+ struct bp_location *global_next;
+
/* Type of this breakpoint location. */
enum bp_loc_type loc_type;
@@ -249,6 +251,14 @@ struct bp_location
PC locations, the evaluation of expression can be different for
different PCs. */
struct expression *cond;
+
+ /* This location's address is in an unloaded solib, and so this
+ location should not be inserted. It will be automatically
+ enabled when that solib is loaded. */
+ char shlib_disabled;
+
+ /* Is this particular location enabled. */
+ char enabled;
/* Nonzero if this breakpoint is now inserted. */
char inserted;
@@ -281,6 +291,8 @@ struct bp_location
processor's architectual constraints. */
CORE_ADDR requested_address;
+ char *function_name;
+
/* Details of the placed breakpoint, when inserted. */
struct bp_target_info target_info;
@@ -423,8 +435,10 @@ struct breakpoint
second bit : 0 normal breakpoint, 1 hardware breakpoint. */
int flag;
- /* Is breakpoint pending on shlib loads? */
- int pending;
+ /* Is breakpoint's condition not yet parsed because we found
+ no location initially so had no context to parse
+ the condition in. */
+ int condition_not_parsed;
};
\f
/* The following stuff is an abstract data type "bpstat" ("breakpoint
--- gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/7_pending) (revision 4751)
+++ gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/8_multiple_locations) (revision 4751)
@@ -128,11 +128,11 @@ gdb_test "info break" \
"Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location6.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker1$marker1_proto at .*$srcfile1:($bp_location15|$bp_location16).*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).*
-\[\t \]+stop only if a == 43.*" \
+\[\t \]+stop only if \\(a==43\\).*" \
"breakpoint info"
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-07 22:49 [8/9] multiple locations Vladimir Prus
@ 2007-09-07 22:51 ` Vladimir Prus
2007-09-08 11:46 ` Eli Zaretskii
2007-09-08 13:17 ` Mark Kettenis
2 siblings, 0 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-09-07 22:51 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 554 bytes --]
Vladimir Prus wrote:
>
> This patch allows a breakpoint to have several breakpoint locations.
> There's lot of mechanical changes -- from iteration over breakpoints
> to iteration over locations. Also, this splits breakpoint enable/disable
> state, changeable by user, from 'shlib_disabled' state, maintained by
> gdb and stored inside location. The breakpoint printing code is modified
> to print locations of breakpoint. OK?
Doh. This version of patch lacks some testsuite updates. This one is
what I've last tested without regressions.
- Volodya
[-- Attachment #2: mainline_8_multiple_locations.ChangeLog --]
[-- Type: text/plain, Size: 3226 bytes --]
gdb/
* breakpoint.h (enum enable_state): Remove the
bp_shlib_disabled enumerator.
(struct bp_location): New members shlib_disabled,
global_next, enabled and function_name.
Rename pending to condition_not_parsed.
* breakpoint.c (ALL_BP_LOCATIONS): Iterate over global_next.
(ALL_BP_LOCATIONS_SAFE): Likewise.
(breakpoint_enabled): Don't check for pending.
(condition_command): Free and update all locations of
a breakpoint.
(insert_bp_location): Adjust.
(software_breakpoint_inserted_here_p): Don't care
if breakpoint is enabled, as soon as it's inserted.
(print_it_typical): Print bpstat's location, not
bpstat's breakpoint's location.
(bpstat_stop_status): Iterate over all locations, not
all breakpoints.
(print_breakpoint_location): New.
(print_one_breakpoint): Renamed to
(print_one_breakpoint_location): ...this. Take
parameters to describe which location is being
printed. Modify code to properly print header
for several locations and individual locations.
(print_one_breakpoint): Print all locations.
(breakpoint_has_pc): New.
(describe_other_breakpoints): Use the above.
(check_duplicates): Renamed to...
(check_duplicates_for): .. this.
(check_duplicates): Use check_duplicates_for.
(allocate_bp_location): Adjust.
(set_raw_breakpoint_without_location): New,
extracted from set_raw_breakpoint.
(set_breakpoint_location_function): New.
(set_raw_breakpoint): Use
set_raw_breakpoint_without_location.
(make_breakpoint_permanent): Mark all locations
as inserted.
(disable_breakpoints_in_shlibs): Iterate over
locations.
(disable_breakpoints_in_unloaded_shlib): Likewise.
(re_enable_breakpoints_in_shlibs): Likewise.
(mention): Say "pending" when breakpoint has
zero locations. If breakpoint has more than one
location, say so.
(add_location_to_breakpoint): New.
(create_breakpoint): Accept symtabs_and_lines, not
symtab_and_line. Pass extra sals to
add_location_to_breakpoint.
(create_breakpoints): Pass symtabs_and_lines to
create_breakpoints.
(break_command_1): Make pending breakpoints
have zero locations.
(do_captured_breakpoint): Remove wrong allocation.
(clear_command): Iterate over all locations.
(unlink_locations_from_global_list): Renamed
from unlink_location_from_global_list. Remove
all locations.
(delete_breakpoint): Remove all locations.
Iterate over all locations when deciding which
other location to re-enable.
(all_locations_are_pending): New.
(update_breakpoint_locations): Renamed from
update_breakpoint_location. Try to match old
and new locations using names of containing
functions.
(breakpoint_re_set_one): Adjust.
(find_location_by_number): New.
(disable_command): Allow disabling individual location.
(enable_command): Allow enabling individual location.
* breakpoint.c: Adjust all uses of breakpoint's
enable state to for bp_shlib_disabled change.
gdb/testsuite/
* gdb.base/condbreak.exp: Adjust.
* gdb.base/annota1.exp: Adjust for 'info break'
format changes.
* gdb.base/annota3.exp: Likewise.
* gdb.base/break.exp: Likewise.
* gdb.base/condbreak.exp: Likewise.
* gdb.base/pending.exp: Likewise.
* gdb.base/sepdebug.exp: Likewise.
* gdb.base/unload.exp: Likewise.
* gdb.base/ovldbreak.exp: Likewise.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: mainline_8_multiple_locations.diff --]
[-- Type: text/x-diff; name="mainline_8_multiple_locations.diff", Size: 69022 bytes --]
--- gdb/breakpoint.c (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/breakpoint.c (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -275,11 +275,11 @@ static int overlay_events_enabled;
/* Similar iterators for the low-level breakpoints. */
-#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->next)
+#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->global_next)
#define ALL_BP_LOCATIONS_SAFE(B,TMP) \
for (B = bp_location_chain; \
- B ? (TMP=B->next, 1): 0; \
+ B ? (TMP=B->global_next, 1): 0; \
B = TMP)
/* True if breakpoint hit counts should be displayed in breakpoint info. */
@@ -356,7 +356,7 @@ static struct exception_event_record *cu
static int
breakpoint_enabled (struct breakpoint *b)
{
- return (b->enable_state == bp_enabled && !b->pending);
+ return (b->enable_state == bp_enabled);
}
/* Set breakpoint count to NUM. */
@@ -572,10 +572,13 @@ condition_command (char *arg, int from_t
if (b->number == bnum)
{
struct bp_location *loc = b->loc;
- if (loc->cond)
+ for (; loc; loc = loc->next)
{
- xfree (loc->cond);
- loc->cond = 0;
+ if (loc->cond)
+ {
+ xfree (loc->cond);
+ loc->cond = 0;
+ }
}
if (b->cond_string != NULL)
xfree (b->cond_string);
@@ -592,10 +595,11 @@ condition_command (char *arg, int from_t
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = savestring (arg, strlen (arg));
- if (!b->pending)
+ b->condition_not_parsed = 0;
+ for (loc = b->loc; loc; loc = loc->next)
{
- b->loc->cond = parse_exp_1 (&arg,
- block_for_pc (b->loc->address), 0);
+ arg = p;
+ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
@@ -846,7 +850,7 @@ insert_bp_location (struct bp_location *
if (!breakpoint_enabled (bpt->owner))
return 0;
- if (bpt->inserted || bpt->duplicate)
+ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
return 0;
/* Initialize the target-specific information. */
@@ -969,7 +973,7 @@ Note: automatically using hardware break
{
/* See also: disable_breakpoints_in_shlibs. */
val = 0;
- bpt->owner->enable_state = bp_shlib_disabled;
+ bpt->shlib_disabled = 1;
if (!*disabled_breaks)
{
fprintf_unfiltered (tmp_error_stream,
@@ -1808,9 +1812,7 @@ software_breakpoint_inserted_here_p (COR
if (bpt->loc_type != bp_loc_software_breakpoint)
continue;
- if ((breakpoint_enabled (bpt->owner)
- || bpt->owner->enable_state == bp_permanent)
- && bpt->inserted
+ if (bpt->inserted
&& bpt->address == pc) /* bp is enabled and matches pc */
{
if (overlay_debugging
@@ -2160,6 +2162,7 @@ print_it_typical (bpstat bs)
{
struct cleanup *old_chain, *ui_out_chain;
struct breakpoint *b;
+ struct bp_location *bl;
struct ui_stream *stb;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2167,15 +2170,16 @@ print_it_typical (bpstat bs)
which has since been deleted. */
if (bs->breakpoint_at == NULL)
return PRINT_UNKNOWN;
- b = bs->breakpoint_at->owner;
+ bl = bs->breakpoint_at;
+ b = bl->owner;
switch (b->type)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
- if (b->loc->address != b->loc->requested_address)
- breakpoint_adjustment_warning (b->loc->requested_address,
- b->loc->address,
+ if (bl->address != bl->requested_address)
+ breakpoint_adjustment_warning (bl->requested_address,
+ bl->address,
b->number, 1);
annotate_breakpoint (b->number);
ui_out_text (uiout, "\nBreakpoint ");
@@ -2672,7 +2676,8 @@ which its expression is valid.\n");
bpstat
bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint)
{
- struct breakpoint *b, *temp;
+ struct breakpoint *b = NULL;
+ struct bp_location *bl;
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
int real_breakpoint = 0;
/* Root of the chain of bpstat's */
@@ -2681,8 +2686,10 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
bpstat bs = root_bs;
int thread_id = pid_to_thread_id (ptid);
- ALL_BREAKPOINTS_SAFE (b, temp)
+ ALL_BP_LOCATIONS (bl)
{
+ b = bl->owner;
+ gdb_assert (b);
if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
continue;
@@ -2697,11 +2704,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw) /* a non-watchpoint bp */
{
- if (b->loc->address != bp_addr) /* address doesn't match */
+ if (bl->address != bp_addr) /* address doesn't match */
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2719,11 +2726,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
if (b->type == bp_hardware_breakpoint)
{
- if (b->loc->address != bp_addr)
+ if (bl->address != bp_addr)
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2774,7 +2781,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* Come here if it's a watchpoint, or if the break address matches */
- bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */
+ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */
/* Watchpoints may change this, if not found to have triggered. */
bs->stop = 1;
@@ -2926,19 +2933,19 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
{
int value_is_zero = 0;
- if (b->loc->cond)
+ if (bl->cond)
{
/* Need to select the frame, with all that implies
so that the conditions will have the right context. */
select_frame (get_current_frame ());
value_is_zero
- = catch_errors (breakpoint_cond_eval, (b->loc->cond),
+ = catch_errors (breakpoint_cond_eval, (bl->cond),
"Error in testing breakpoint condition:\n",
RETURN_MASK_ALL);
/* FIXME-someday, should give breakpoint # */
free_all_values ();
}
- if (b->loc->cond && value_is_zero)
+ if (bl->cond && value_is_zero)
{
bs->stop = 0;
/* Don't consider this a hit. */
@@ -2985,9 +2992,9 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* The value of a hardware watchpoint hasn't changed, but the
intermediate memory locations we are watching may have. */
if (bs && !bs->stop &&
- (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
- bs->breakpoint_at->owner->type == bp_read_watchpoint ||
- bs->breakpoint_at->owner->type == bp_access_watchpoint))
+ (b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint))
{
remove_breakpoints ();
insert_breakpoints ();
@@ -3349,10 +3356,54 @@ bpstat_get_triggered_catchpoints (bpstat
*cp_list = bs;
}
+static void print_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ char *wrap_indent,
+ struct ui_stream *stb)
+{
+ if (b->source_file)
+ {
+ struct symbol *sym
+ = find_pc_sect_function (loc->address, loc->section);
+ if (sym)
+ {
+ ui_out_text (uiout, "in ");
+ ui_out_field_string (uiout, "func",
+ SYMBOL_PRINT_NAME (sym));
+ ui_out_wrap_hint (uiout, wrap_indent);
+ ui_out_text (uiout, " at ");
+ }
+ ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_text (uiout, ":");
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ struct symtab_and_line sal = find_pc_line (loc->address, 0);
+ char *fullname = symtab_to_fullname (sal.symtab);
+
+ if (fullname)
+ ui_out_field_string (uiout, "fullname", fullname);
+ }
+
+ ui_out_field_int (uiout, "line", b->line_number);
+ }
+ else if (!b->loc)
+ {
+ ui_out_field_string (uiout, "pending", b->addr_string);
+ }
+ else
+ {
+ print_address_symbolic (loc->address, stb->stream, demangle, "");
+ ui_out_field_stream (uiout, "at", stb);
+ }
+}
+
/* Print B to gdb_stdout. */
static void
-print_one_breakpoint (struct breakpoint *b,
- CORE_ADDR *last_addr)
+print_one_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ int loc_number,
+ CORE_ADDR *last_addr)
{
struct command_line *l;
struct symbol *sym;
@@ -3397,30 +3448,79 @@ print_one_breakpoint (struct breakpoint
struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
struct cleanup *bkpt_chain;
+ int header_of_multiple = 0;
+ int part_of_multiple = (loc != NULL);
+
+ gdb_assert (!loc || loc_number != 0);
+ /* See comment in print_one_breakpoint concerning
+ treatment of breakpoints with single disabled
+ location. */
+ if (loc == NULL
+ && (b->loc != NULL
+ && (b->loc->next != NULL || !b->loc->enabled)))
+ header_of_multiple = 1;
+ if (loc == NULL)
+ loc = b->loc;
+
annotate_record ();
bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
/* 1 */
annotate_field (0);
- ui_out_field_int (uiout, "number", b->number);
+ if (part_of_multiple)
+ {
+ char buf[30];
+ sprintf (buf, "%d.%d", b->number, loc_number);
+ ui_out_field_string (uiout, "number", buf);
+ }
+ else
+ {
+ ui_out_field_int (uiout, "number", b->number);
+ }
/* 2 */
annotate_field (1);
- if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
- || ((int) b->type != bptypes[(int) b->type].type))
- internal_error (__FILE__, __LINE__,
- _("bptypes table does not describe type #%d."),
- (int) b->type);
- ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "type");
+ else
+ {
+ if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
+ || ((int) b->type != bptypes[(int) b->type].type))
+ internal_error (__FILE__, __LINE__,
+ _("bptypes table does not describe type #%d."),
+ (int) b->type);
+ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ }
/* 3 */
annotate_field (2);
- ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "disp");
+ else
+ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+
/* 4 */
annotate_field (3);
- ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
- ui_out_spaces (uiout, 2);
+ if (part_of_multiple)
+ ui_out_field_string (uiout, "enabled",
+ loc->shlib_disabled
+ ? (loc->enabled ? "y(p)" : "n(p)")
+ : (loc->enabled ? "y" : "n"));
+ else
+ {
+ int pending = (b->loc == NULL || b->loc->shlib_disabled);
+ /* For header of multiple, there's no point showing pending
+ state -- it will be apparent from the locations. */
+ if (header_of_multiple)
+ pending = 0;
+ ui_out_field_fmt (uiout, "enabled", "%c%s",
+ bpenables[(int) b->enable_state],
+ pending ? "(p)" : "");
+ if (!pending)
+ ui_out_spaces (uiout, 3);
+ }
+
/* 5 and 6 */
strcpy (wrap_indent, " ");
@@ -3433,7 +3533,14 @@ print_one_breakpoint (struct breakpoint
}
if (b->ops != NULL && b->ops->print_one != NULL)
- b->ops->print_one (b, last_addr);
+ {
+ /* Although the print_one can possibly print
+ all locations, calling it here is not likely
+ to get any nice result. So, make sure there's
+ just one location. */
+ gdb_assert (b->loc == NULL || b->loc->next == NULL);
+ b->ops->print_one (b, last_addr);
+ }
else
switch (b->type)
{
@@ -3545,51 +3652,22 @@ print_one_breakpoint (struct breakpoint
if (addressprint)
{
annotate_field (4);
- if (b->pending)
+ if (b->loc == NULL)
ui_out_field_string (uiout, "addr", "<PENDING>");
+ else if (header_of_multiple)
+ ui_out_field_string (uiout, "addr", "<MULTIPLE>");
else
- ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ ui_out_field_core_addr (uiout, "addr", loc->address);
}
annotate_field (5);
- *last_addr = b->loc->address;
- if (b->source_file)
- {
- sym = find_pc_sect_function (b->loc->address, b->loc->section);
- if (sym)
- {
- ui_out_text (uiout, "in ");
- ui_out_field_string (uiout, "func",
- SYMBOL_PRINT_NAME (sym));
- ui_out_wrap_hint (uiout, wrap_indent);
- ui_out_text (uiout, " at ");
- }
- ui_out_field_string (uiout, "file", b->source_file);
- ui_out_text (uiout, ":");
-
- if (ui_out_is_mi_like_p (uiout))
- {
- struct symtab_and_line sal = find_pc_line (b->loc->address, 0);
- char *fullname = symtab_to_fullname (sal.symtab);
-
- if (fullname)
- ui_out_field_string (uiout, "fullname", fullname);
- }
-
- ui_out_field_int (uiout, "line", b->line_number);
- }
- else if (b->pending)
- {
- ui_out_field_string (uiout, "pending", b->addr_string);
- }
- else
- {
- print_address_symbolic (b->loc->address, stb->stream, demangle, "");
- ui_out_field_stream (uiout, "at", stb);
- }
+ if (!header_of_multiple)
+ print_breakpoint_location (b, loc, wrap_indent, stb);
+ if (b->loc)
+ *last_addr = b->loc->address;
break;
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME: This seems to be redundant and lost here; see the
"stop only in" line a little further down. */
@@ -3599,7 +3677,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
- if (frame_id_p (b->frame_id))
+ if (part_of_multiple && frame_id_p (b->frame_id))
{
annotate_field (6);
ui_out_text (uiout, "\tstop only in stack frame at ");
@@ -3609,27 +3687,18 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (b->loc->cond && !ada_exception_catchpoint_p (b))
+ if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
{
/* We do not print the condition for Ada exception catchpoints
because the condition is an internal implementation detail
that we do not want to expose to the user. */
annotate_field (7);
ui_out_text (uiout, "\tstop only if ");
- print_expression (b->loc->cond, stb->stream);
- ui_out_field_stream (uiout, "cond", stb);
- ui_out_text (uiout, "\n");
- }
-
- if (b->pending && b->cond_string)
- {
- annotate_field (7);
- ui_out_text (uiout, "\tstop only if ");
ui_out_field_string (uiout, "cond", b->cond_string);
ui_out_text (uiout, "\n");
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME should make an annotation for this */
ui_out_text (uiout, "\tstop only in thread ");
@@ -3637,7 +3706,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (show_breakpoint_hit_counts && b->hit_count)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
{
/* FIXME should make an annotation for this */
if (ep_is_catchpoint (b))
@@ -3655,10 +3724,10 @@ print_one_breakpoint (struct breakpoint
/* Output the count also if it is zero, but only if this is
mi. FIXME: Should have a better test for this. */
if (ui_out_is_mi_like_p (uiout))
- if (show_breakpoint_hit_counts && b->hit_count == 0)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
ui_out_field_int (uiout, "times", b->hit_count);
- if (b->ignore_count)
+ if (!part_of_multiple && b->ignore_count)
{
annotate_field (8);
ui_out_text (uiout, "\tignore next ");
@@ -3666,7 +3735,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, " hits\n");
}
- if ((l = b->commands))
+ if (!part_of_multiple && (l = b->commands))
{
struct cleanup *script_chain;
@@ -3679,6 +3748,35 @@ print_one_breakpoint (struct breakpoint
do_cleanups (old_chain);
}
+static void
+print_one_breakpoint (struct breakpoint *b,
+ CORE_ADDR *last_addr)
+{
+ print_one_breakpoint_location (b, NULL, 0, last_addr);
+
+ /* If this breakpoint has custom print function,
+ it's already printed. Otherwise, print individual
+ locations, if any. */
+ if (b->ops == NULL || b->ops->print_one == NULL)
+ {
+ /* If breakpoint has a single location that is
+ disabled, we print it as if it had
+ several locations, since otherwise it's hard to
+ represent "breakpoint enabled, location disabled"
+ situation. */
+ if (b->loc
+ && (b->loc->next || !b->loc->enabled)
+ && !ui_out_is_mi_like_p (uiout))
+ {
+ struct bp_location *loc;
+ int n = 1;
+ for (loc = b->loc; loc; loc = loc->next, ++n)
+ print_one_breakpoint_location (b, loc, n, last_addr);
+ }
+ }
+}
+
+
struct captured_breakpoint_query_args
{
int bnum;
@@ -3780,7 +3878,7 @@ breakpoint_1 (int bnum, int allflag)
ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
if (nr_printable_breakpoints > 0)
annotate_field (3);
- ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
+ ui_out_table_header (uiout, 4, ui_left, "enabled", "Enb"); /* 4 */
if (addressprint)
{
if (nr_printable_breakpoints > 0)
@@ -3852,6 +3950,19 @@ maintenance_info_breakpoints (char *bnum
breakpoint_1 (bnum, 1);
}
+static int
+breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
+{
+ struct bp_location *bl = b->loc;
+ for (; bl; bl = bl->next)
+ {
+ if (bl->address == pc
+ && (!overlay_debugging || bl->section == section))
+ return 1;
+ }
+ return 0;
+}
+
/* Print a message describing any breakpoints set at PC. */
static void
@@ -3861,9 +3972,7 @@ describe_other_breakpoints (CORE_ADDR pc
struct breakpoint *b;
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- others++;
+ others += breakpoint_has_pc (b, pc, section);
if (others > 0)
{
if (others == 1)
@@ -3871,26 +3980,24 @@ describe_other_breakpoints (CORE_ADDR pc
else /* if (others == ???) */
printf_filtered (_("Note: breakpoints "));
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- {
- others--;
- printf_filtered ("%d", b->number);
- if (b->thread == -1 && thread != -1)
- printf_filtered (" (all threads)");
- else if (b->thread != -1)
- printf_filtered (" (thread %d)", b->thread);
- printf_filtered ("%s%s ",
- ((b->enable_state == bp_disabled ||
- b->enable_state == bp_shlib_disabled ||
- b->enable_state == bp_call_disabled)
- ? " (disabled)"
- : b->enable_state == bp_permanent
- ? " (permanent)"
- : ""),
- (others > 1) ? ","
- : ((others == 1) ? " and" : ""));
- }
+ if (breakpoint_has_pc (b, pc, section))
+ {
+ others--;
+ printf_filtered ("%d", b->number);
+ if (b->thread == -1 && thread != -1)
+ printf_filtered (" (all threads)");
+ else if (b->thread != -1)
+ printf_filtered (" (thread %d)", b->thread);
+ printf_filtered ("%s%s ",
+ ((b->enable_state == bp_disabled ||
+ b->enable_state == bp_call_disabled)
+ ? " (disabled)"
+ : b->enable_state == bp_permanent
+ ? " (permanent)"
+ : ""),
+ (others > 1) ? ","
+ : ((others == 1) ? " and" : ""));
+ }
printf_filtered (_("also set at pc "));
deprecated_print_address_numeric (pc, 1, gdb_stdout);
printf_filtered (".\n");
@@ -3951,22 +4058,17 @@ breakpoint_address_is_meaningful (struct
that one the official one, and the rest as duplicates. */
static void
-check_duplicates (struct breakpoint *bpt)
+check_duplicates_for (CORE_ADDR address, asection *section)
{
struct bp_location *b;
int count = 0;
struct bp_location *perm_bp = 0;
- CORE_ADDR address = bpt->loc->address;
- asection *section = bpt->loc->section;
-
- if (! breakpoint_address_is_meaningful (bpt))
- return;
ALL_BP_LOCATIONS (b)
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled
+ && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -3999,9 +4101,8 @@ check_duplicates (struct breakpoint *bpt
if (b != perm_bp)
{
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -4018,6 +4119,18 @@ check_duplicates (struct breakpoint *bpt
}
static void
+check_duplicates (struct breakpoint *bpt)
+{
+ struct bp_location *bl = bpt->loc;
+
+ if (! breakpoint_address_is_meaningful (bpt))
+ return;
+
+ for (; bl; bl = bl->next)
+ check_duplicates_for (bl->address, bl->section);
+}
+
+static void
breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
int bnum, int have_bnum)
{
@@ -4089,6 +4202,8 @@ allocate_bp_location (struct breakpoint
loc->owner = bpt;
loc->cond = NULL;
+ loc->shlib_disabled = 0;
+ loc->enabled = 1;
switch (bp_type)
{
@@ -4134,9 +4249,9 @@ allocate_bp_location (struct breakpoint
bp_location_chain = loc;
else
{
- while (loc_p->next)
- loc_p = loc_p->next;
- loc_p->next = loc;
+ while (loc_p->global_next)
+ loc_p = loc_p->global_next;
+ loc_p->global_next = loc;
}
return loc;
@@ -4165,37 +4280,17 @@ static void free_bp_location (struct bp_
should happen, a bogus breakpoint will be left on the chain. */
struct breakpoint *
-set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+set_raw_breakpoint_without_location (enum bptype bptype)
{
struct breakpoint *b, *b1;
- CORE_ADDR adjusted_address;
b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
memset (b, 0, sizeof (*b));
- /* Adjust the breakpoint's address prior to allocating a location.
- Once we call allocate_bp_location(), that mostly uninitialized
- location will be placed on the location chain. Adjustment of the
- breakpoint may cause read_memory_nobpt() to be called and we do
- not want its scan of the location chain to find a breakpoint and
- location that's only been partially initialized. */
- adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
-
- b->loc = allocate_bp_location (b, bptype);
- b->loc->requested_address = sal.pc;
- b->loc->address = adjusted_address;
-
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
- b->loc->section = sal.section;
b->type = bptype;
b->language = current_language->la_language;
b->input_radix = input_radix;
b->thread = -1;
- b->line_number = sal.line;
b->enable_state = bp_enabled;
b->next = 0;
b->silent = 0;
@@ -4207,7 +4302,7 @@ set_raw_breakpoint (struct symtab_and_li
b->forked_inferior_pid = 0;
b->exec_pathname = NULL;
b->ops = NULL;
- b->pending = 0;
+ b->condition_not_parsed = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
@@ -4222,6 +4317,65 @@ set_raw_breakpoint (struct symtab_and_li
b1 = b1->next;
b1->next = b;
}
+ return b;
+}
+
+/* Initialize loc->function_name. */
+static void
+set_breakpoint_location_function (struct bp_location *loc)
+{
+ if (loc->owner->type == bp_breakpoint
+ || loc->owner->type == bp_hardware_breakpoint)
+ {
+ find_pc_partial_function (loc->address, &(loc->function_name),
+ NULL, NULL);
+ if (loc->function_name)
+ loc->function_name = xstrdup (loc->function_name);
+ }
+}
+
+/* set_raw_breakpoint() is a low level routine for allocating and
+ partially initializing a breakpoint of type BPTYPE. The newly
+ created breakpoint's address, section, source file name, and line
+ number are provided by SAL. The newly created and partially
+ initialized breakpoint is added to the breakpoint chain and
+ is also returned as the value of this function.
+
+ It is expected that the caller will complete the initialization of
+ the newly created breakpoint struct as well as output any status
+ information regarding the creation of a new breakpoint. In
+ particular, set_raw_breakpoint() does NOT set the breakpoint
+ number! Care should be taken to not allow an error() to occur
+ prior to completing the initialization of the breakpoint. If this
+ should happen, a bogus breakpoint will be left on the chain. */
+
+struct breakpoint *
+set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+{
+ struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
+ CORE_ADDR adjusted_address;
+
+ /* Adjust the breakpoint's address prior to allocating a location.
+ Once we call allocate_bp_location(), that mostly uninitialized
+ location will be placed on the location chain. Adjustment of the
+ breakpoint may cause read_memory_nobpt() to be called and we do
+ not want its scan of the location chain to find a breakpoint and
+ location that's only been partially initialized. */
+ adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+
+ b->loc = allocate_bp_location (b, bptype);
+ b->loc->requested_address = sal.pc;
+ b->loc->address = adjusted_address;
+
+ if (sal.symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+ b->loc->section = sal.section;
+ b->line_number = sal.line;
+
+ set_breakpoint_location_function (b->loc);
check_duplicates (b);
breakpoints_changed ();
@@ -4235,10 +4389,16 @@ set_raw_breakpoint (struct symtab_and_li
void
make_breakpoint_permanent (struct breakpoint *b)
{
+ struct bp_location *bl;
b->enable_state = bp_permanent;
- /* By definition, permanent breakpoints are already present in the code. */
- b->loc->inserted = 1;
+ /* By definition, permanent breakpoints are already present in the code.
+ Mark all locations as inserted. For now, make_breakpoint_permanent
+ is called in just one place, so it's hard to say if it's reasonable
+ to have permanent breakpoint with multiple locations or not,
+ but it's easy to implmement. */
+ for (bl = b->loc; bl; bl = bl->next)
+ bl->inserted = 1;
}
static struct breakpoint *
@@ -4431,20 +4591,28 @@ create_solib_event_breakpoint (CORE_ADDR
void
disable_breakpoints_in_shlibs (void)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
+ struct breakpoint *b = loc->owner;
+ /* We apply the check to all breakpoints, including disabled
+ for those with loc->duplicate set. This is so that when breakpoint
+ becomes enabled, or the duplicate is removed, gdb will try to insert
+ all breakpoints. If we don't set shlib_disabled here, we'll try
+ to insert those breakpoints and fail. */
if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
- && breakpoint_enabled (b) && !b->loc->duplicate
+ && !loc->shlib_disabled
#ifdef PC_SOLIB
- && PC_SOLIB (b->loc->address)
+ && PC_SOLIB (loc->address)
#else
- && solib_address (b->loc->address)
+ && solib_address (loc->address)
#endif
)
- b->enable_state = bp_shlib_disabled;
+ {
+ loc->shlib_disabled = 1;
+ }
}
}
@@ -4454,27 +4622,28 @@ disable_breakpoints_in_shlibs (void)
void
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
- if ((b->loc->loc_type == bp_loc_hardware_breakpoint
- || b->loc->loc_type == bp_loc_software_breakpoint)
- && breakpoint_enabled (b) && !b->loc->duplicate)
+ struct breakpoint *b = loc->owner;
+ if ((loc->loc_type == bp_loc_hardware_breakpoint
+ || loc->loc_type == bp_loc_software_breakpoint)
+ && !loc->shlib_disabled)
{
#ifdef PC_SOLIB
- char *so_name = PC_SOLIB (b->loc->address);
+ char *so_name = PC_SOLIB (loc->address);
#else
- char *so_name = solib_address (b->loc->address);
+ char *so_name = solib_address (loc->address);
#endif
if (so_name && !strcmp (so_name, solib->so_name))
{
- b->enable_state = bp_shlib_disabled;
+ loc->shlib_disabled = 1;
/* At this point, we cannot rely on remove_breakpoint
succeeding so we must mark the breakpoint as not inserted
to prevent future errors occurring in remove_breakpoints. */
- b->loc->inserted = 0;
+ loc->inserted = 0;
if (!disabled_shlib_breaks)
{
target_terminal_ours_for_output ();
@@ -4894,7 +5063,7 @@ mention (struct breakpoint *b)
{
/* i18n: cagney/2005-02-11: Below needs to be merged into a
single string. */
- if (b->pending)
+ if (b->loc == NULL)
{
printf_filtered (_(" (%s) pending."), b->addr_string);
}
@@ -4908,6 +5077,16 @@ mention (struct breakpoint *b)
if (b->source_file)
printf_filtered (": file %s, line %d.",
b->source_file, b->line_number);
+
+ if (b->loc->next)
+ {
+ struct bp_location *loc = b->loc;
+ int n = 0;
+ for (; loc; loc = loc->next)
+ ++n;
+ printf_filtered (" (%d locations)", n);
+ }
+
}
}
do_cleanups (old_chain);
@@ -4917,6 +5096,24 @@ mention (struct breakpoint *b)
}
\f
+static struct bp_location *
+add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+ const struct symtab_and_line *sal)
+{
+ struct bp_location *loc, **tmp;
+
+ loc = allocate_bp_location (b, bptype);
+ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
+ ;
+ *tmp = loc;
+ loc->requested_address = sal->pc;
+ loc->address = adjust_breakpoint_address (loc->requested_address,
+ bptype);
+ loc->section = sal->section;
+
+ set_breakpoint_location_function (loc);
+ return loc;
+}
/* Create a breakpoint with SAL as location. Use ADDR_STRING
as textual description of the location, and COND_STRING
@@ -4926,13 +5123,14 @@ mention (struct breakpoint *b)
create_breakpoints function. */
static void
-create_breakpoint (struct symtab_and_line sal, char *addr_string,
+create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count, int from_tty,
struct breakpoint *pending_bp)
{
- struct breakpoint *b;
+ struct breakpoint *b = NULL;
+ int i;
if (type == bp_hardware_breakpoint)
{
@@ -4946,50 +5144,46 @@ create_breakpoint (struct symtab_and_lin
error (_("Hardware breakpoints used exceeds limit."));
}
- if (from_tty)
- describe_other_breakpoints (sal.pc, sal.section, thread);
-
- b = set_raw_breakpoint (sal, type);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->thread = thread;
+ for (i = 0; i < sals.nelts; ++i)
+ {
+ struct symtab_and_line sal = sals.sals[i];
+ struct bp_location *loc;
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc, sal.section, thread);
+
+ if (i == 0)
+ {
+ b = set_raw_breakpoint (sal, type);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->thread = thread;
- b->cond_string = cond_string;
- b->ignore_count = ignore_count;
- b->enable_state = bp_enabled;
- b->disposition = disposition;
- /* If resolving a pending breakpoint, a check must be made to see if
- the user has specified a new condition or commands for the
- breakpoint. A new condition will override any condition that was
- initially specified with the initial breakpoint command. */
- if (pending_bp)
- {
- if (pending_bp->cond_string)
- b->cond_string = savestring (pending_bp->cond_string,
- strlen (pending_bp->cond_string));
-
- /* If there are commands associated with the breakpoint, they should
- be copied too. */
- if (pending_bp->commands)
- b->commands = copy_command_lines (pending_bp->commands);
-
- /* We have to copy over the ignore_count and thread as well. */
- b->ignore_count = pending_bp->ignore_count;
- b->thread = pending_bp->thread;
- }
+ b->cond_string = cond_string;
+ b->ignore_count = ignore_count;
+ b->enable_state = bp_enabled;
+ b->disposition = disposition;
- if (b->cond_string)
- {
- char *arg = b->cond_string;
- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
- if (*arg)
+ loc = b->loc;
+ }
+ else
{
- if (pending_bp)
- error (_("Junk at end of pending breakpoint condition expression"));
- else
- error (_("Garbage %s follows condition"), arg);
+ loc = add_location_to_breakpoint (b, type, &sal);
+ }
+
+ if (b->cond_string)
+ {
+ char *arg = b->cond_string;
+ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ {
+ if (pending_bp)
+ error (_("Junk at end of pending breakpoint condition expression"));
+ else
+ error (_("Garbage %s follows condition"), arg);
+ }
}
- }
+ }
if (addr_string)
b->addr_string = addr_string;
@@ -5031,7 +5225,11 @@ create_breakpoints (struct symtabs_and_l
int i;
for (i = 0; i < sals.nelts; ++i)
{
- create_breakpoint (sals.sals[i], addr_string[i],
+ struct symtabs_and_lines sals2;
+ sals2.sals = sals.sals + i;
+ sals2.nelts = 1;
+
+ create_breakpoint (sals2, addr_string[i],
cond_string, type, disposition,
thread, ignore_count, from_tty,
pending_bp);
@@ -5360,19 +5558,19 @@ break_command_1 (char *arg, int flag, in
make_cleanup (xfree, copy_arg);
- b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
- : bp_breakpoint);
+ b = set_raw_breakpoint_without_location (hardwareflag
+ ? bp_hardware_breakpoint
+ : bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->loc->cond = NULL;
b->thread = thread;
b->addr_string = addr_string[0];
b->cond_string = cond_string;
b->ignore_count = ignore_count;
- b->pending = 1;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->from_tty = from_tty;
b->flag = flag;
+ b->condition_not_parsed = 1;
mention (b);
}
@@ -5411,7 +5609,7 @@ do_captured_breakpoint (struct ui_out *u
struct cleanup *breakpoint_chain = NULL;
int i;
char **addr_string;
- char *cond_string;
+ char *cond_string = 0;
char *address_end;
@@ -5440,10 +5638,6 @@ do_captured_breakpoint (struct ui_out *u
cond = xcalloc (sals.nelts, sizeof (struct expression *));
make_cleanup (xfree, cond);
- /* Allocate space for all the cond strings. */
- cond_string = xcalloc (sals.nelts, sizeof (char **));
- make_cleanup (xfree, cond_string);
-
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
to be part of a breakpoint. If the breakpoint create goes
@@ -6733,23 +6927,35 @@ clear_command (char *arg, int from_tty)
breakpoint chain, and add them to the 'found' chain. */
ALL_BREAKPOINTS_SAFE (b, tmp)
{
+ int match = 0;
/* Are we going to delete b? */
if (b->type != bp_none
&& b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- /* Not if b is a watchpoint of any sort... */
- && (((sal.pc && (b->loc->address == sal.pc))
- && (!section_is_overlay (b->loc->section)
- || b->loc->section == sal.section))
- /* Yes, if sal.pc matches b (modulo overlays). */
- || ((default_match || (0 == sal.pc))
- && b->source_file != NULL
- && sal.symtab != NULL
- && strcmp (b->source_file, sal.symtab->filename) == 0
- && b->line_number == sal.line)))
- /* Yes, if sal source file and line matches b. */
+ && b->type != bp_access_watchpoint)
+ {
+ struct bp_location *loc = b->loc;
+ for (; loc; loc = loc->next)
+ {
+ int pc_match = sal.pc
+ && (loc->address == sal.pc)
+ && (!section_is_overlay (loc->section)
+ || loc->section == sal.section);
+ int line_match = ((default_match || (0 == sal.pc))
+ && b->source_file != NULL
+ && sal.symtab != NULL
+ && strcmp (b->source_file, sal.symtab->filename) == 0
+ && b->line_number == sal.line);
+ if (pc_match || line_match)
+ {
+ match = 1;
+ break;
+ }
+ }
+ }
+
+ if (match)
{
/* Remove it from breakpoint_chain... */
if (b == breakpoint_chain)
@@ -6824,6 +7030,35 @@ breakpoint_auto_delete (bpstat bs)
}
}
+/* Remove locations of breakpoint BPT from
+ the global list of breakpoint locations. */
+
+static void
+unlink_locations_from_global_list (struct breakpoint *bpt)
+{
+ /* This code assumes that the locations
+ of a breakpoint are found in the global list
+ in the same order, but not necessary adjacent. */
+ struct bp_location **tmp = &bp_location_chain;
+ struct bp_location *here = bpt->loc;
+
+ if (here == NULL)
+ return;
+
+ for (; *tmp && here;)
+ {
+ if (*tmp == here)
+ {
+ *tmp = here->global_next;
+ here = here->next;
+ }
+ else
+ {
+ tmp = &((*tmp)->global_next);
+ }
+ }
+}
+
/* Delete a breakpoint and clean up all traces of it in the data
structures. */
@@ -6856,17 +7091,23 @@ delete_breakpoint (struct breakpoint *bp
deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
- if (bpt->loc->inserted)
- remove_breakpoint (bpt->loc, mark_inserted);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ if (loc->inserted)
+ remove_breakpoint (loc, mark_inserted);
- free_valchain (bpt->loc);
+ free_valchain (loc);
+
+ if (loc->cond)
+ xfree (loc->cond);
+
+ if (loc->function_name)
+ xfree (loc->function_name);
+ }
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
- if (bp_location_chain == bpt->loc)
- bp_location_chain = bpt->loc->next;
-
/* If we have callback-style exception catchpoints, don't go through
the adjustments to the C++ runtime library etc. if the inferior
isn't actually running. target_enable_exception_callback for a
@@ -6896,82 +7137,83 @@ delete_breakpoint (struct breakpoint *bp
break;
}
- ALL_BP_LOCATIONS (loc)
- if (loc->next == bpt->loc)
- {
- loc->next = bpt->loc->next;
- break;
- }
+ unlink_locations_from_global_list (bpt);
check_duplicates (bpt);
- /* If this breakpoint was inserted, and there is another breakpoint
- at the same address, we need to insert the other breakpoint. */
- if (bpt->loc->inserted
- && bpt->type != bp_hardware_watchpoint
+
+ if (bpt->type != bp_hardware_watchpoint
&& bpt->type != bp_read_watchpoint
&& bpt->type != bp_access_watchpoint
&& bpt->type != bp_catch_fork
&& bpt->type != bp_catch_vfork
&& bpt->type != bp_catch_exec)
- {
- ALL_BREAKPOINTS (b)
- if (b->loc->address == bpt->loc->address
- && b->loc->section == bpt->loc->section
- && !b->loc->duplicate
- && b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && !b->pending
- && b->enable_state != bp_call_disabled)
- {
- int val;
-
- /* We should never reach this point if there is a permanent
- breakpoint at the same address as the one being deleted.
- If there is a permanent breakpoint somewhere, it should
- always be the only one inserted. */
- if (b->enable_state == bp_permanent)
- internal_error (__FILE__, __LINE__,
- _("another breakpoint was inserted on top of "
- "a permanent breakpoint"));
-
- memset (&b->loc->target_info, 0, sizeof (b->loc->target_info));
- b->loc->target_info.placed_address = b->loc->address;
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (&b->loc->target_info);
- else
- val = target_insert_breakpoint (&b->loc->target_info);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ /* If this breakpoint location was inserted, and there is
+ another breakpoint at the same address, we need to
+ insert the other breakpoint. */
+ if (loc->inserted)
+ {
+ struct bp_location *loc2;
+ ALL_BP_LOCATIONS (loc2)
+ if (loc2->address == loc->address
+ && loc2->section == loc->section
+ && !loc->duplicate
+ && loc2->owner->enable_state != bp_disabled
+ && loc2->enabled
+ && !loc2->shlib_disabled
+ && loc2->owner->enable_state != bp_call_disabled)
+ {
+ int val;
- /* If there was an error in the insert, print a message, then stop execution. */
- if (val != 0)
- {
- struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
-
+ /* We should never reach this point if there is a permanent
+ breakpoint at the same address as the one being deleted.
+ If there is a permanent breakpoint somewhere, it should
+ always be the only one inserted. */
+ if (loc2->owner->enable_state == bp_permanent)
+ internal_error (__FILE__, __LINE__,
+ _("another breakpoint was inserted on top of "
+ "a permanent breakpoint"));
+
+ memset (&loc2->target_info, 0, sizeof (loc2->target_info));
+ loc2->target_info.placed_address = loc2->address;
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (&loc2->target_info);
+ else
+ val = target_insert_breakpoint (&loc2->target_info);
- if (b->type == bp_hardware_breakpoint)
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d.\n"
- "You may have requested too many hardware breakpoints.\n",
- b->number);
- }
- else
- {
- fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
- fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
- deprecated_print_address_numeric (b->loc->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- }
-
- fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
- target_terminal_ours_for_output ();
- error_stream(tmp_error_stream);
- }
- else
- b->loc->inserted = 1;
- }
- }
+ /* If there was an error in the insert, print a message, then stop execution. */
+ if (val != 0)
+ {
+ struct ui_file *tmp_error_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_error_stream);
+
+
+ if (b->type == bp_hardware_breakpoint)
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert hardware breakpoint %d.\n"
+ "You may have requested too many hardware breakpoints.\n",
+ b->number);
+ }
+ else
+ {
+ fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
+ fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
+ deprecated_print_address_numeric (loc2->address, 1, tmp_error_stream);
+ fprintf_filtered (tmp_error_stream, ": %s.\n",
+ safe_strerror (val));
+ }
+
+ fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
+ target_terminal_ours_for_output ();
+ error_stream(tmp_error_stream);
+ }
+ else
+ loc2->inserted = 1;
+ }
+ }
+ }
free_command_lines (&bpt->commands);
if (bpt->cond_string != NULL)
@@ -7013,9 +7255,12 @@ delete_breakpoint (struct breakpoint *bp
bp, we mark it as deleted before freeing its storage. */
bpt->type = bp_none;
- if (bpt->loc->cond)
- xfree (bpt->loc->cond);
- xfree (bpt->loc);
+ for (loc = bpt->loc; loc;)
+ {
+ struct bp_location *loc_next = loc->next;
+ xfree (loc);
+ loc = loc_next;
+ }
xfree (bpt);
}
@@ -7083,94 +7328,95 @@ delete_command (char *arg, int from_tty)
map_breakpoint_numbers (arg, delete_breakpoint);
}
-static void
-unlink_locations_from_global_list (struct breakpoint *bpt)
- /* Remove locations of this breakpoint from the list of
- all breakpoint locations. */
+static int
+all_locations_are_pending (struct bp_location *loc)
{
- struct bp_location **tmp = &bp_location_chain;
- struct bp_location *here = bpt->loc;
-
- if (here == NULL)
- return;
-
- for (; *tmp && *tmp != here; tmp = &((*tmp)->next));
- gdb_assert (*tmp);
-
- *tmp = here->next;
+ for (; loc; loc = loc->next)
+ if (!loc->shlib_disabled)
+ return 0;
+ return 1;
}
-
static void
-update_breakpoint_location (struct breakpoint *b,
- struct symtabs_and_lines sals)
+update_breakpoint_locations (struct breakpoint *b,
+ struct symtabs_and_lines sals)
{
int i;
char *s;
- /* FIXME: memleak. */
- struct bp_location *existing = b->loc;
- struct bp_location *loc;
- struct symtab_and_line sal;
-
- if (b->enable_state == bp_shlib_disabled && sals.nelts == 0)
+ struct bp_location *existing_locations = b->loc;
+
+ /* If there's no new locations, and all existing locations
+ are pending, don't do anything. This optimizes
+ the common case where all locations are in the same
+ shared library, that was unloaded. We'd like to
+ retain the location, so that when the library
+ is loaded again, we don't loose the enabled/disabled
+ status of the individual locations. */
+ if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
return;
unlink_locations_from_global_list (b);
b->loc = NULL;
- gdb_assert (sals.nelts == 0 || sals.nelts == 1);
- if (sals.nelts == 0)
- return;
- sal = sals.sals[0];
-
- loc = allocate_bp_location (b, b->type);
- loc->requested_address = sal.pc;
- loc->address = adjust_breakpoint_address (loc->requested_address,
- b->type);
- loc->section = sal.section;
- b->loc = loc;
-
- /* Reparse conditions, they might contain references to the
- old symtab. */
- if (b->cond_string != NULL)
+ for (i = 0; i < sals.nelts; ++i)
{
- struct gdb_exception e;
-
- s = b->cond_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc),
- 0);
- }
- if (e.reason < 0)
- {
- warning (_("failed to reevaluate condition for breakpoint %d: %s"),
- b->number, e.message);
- b->enable_state = bp_disabled;
- }
- }
+ struct bp_location *new_loc =
+ add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
- if (b->source_file != NULL)
- xfree (b->source_file);
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file =
- savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
+ /* Reparse conditions, they might contain references to the
+ old symtab. */
+ if (b->cond_string != NULL)
+ {
+ struct gdb_exception e;
- if (b->line_number == 0)
- b->line_number = sal.line;
+ s = b->cond_string;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc),
+ 0);
+ }
+ if (e.reason < 0)
+ {
+ warning (_("failed to reevaluate condition for breakpoint %d: %s"),
+ b->number, e.message);
+ new_loc->enabled = 0;
+ }
+ }
- if (b->enable_state == bp_shlib_disabled)
- b->enable_state = bp_enabled;
+ if (b->source_file != NULL)
+ xfree (b->source_file);
+ if (sals.sals[i].symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file =
+ savestring (sals.sals[i].symtab->filename,
+ strlen (sals.sals[i].symtab->filename));
- b->pending = 0;
+ if (b->line_number == 0)
+ b->line_number = sals.sals[i].line;
+ }
- check_duplicates (b);
+ /* If possible, carry over 'disable' status from existing breakpoints. */
+ {
+ struct bp_location *e = existing_locations;
+ for (; e; e = e->next)
+ {
+ if (!e->enabled && e->function_name)
+ {
+ struct bp_location *l = b->loc;
+ for (; l; l = l->next)
+ if (l->function_name
+ && strcmp (e->function_name, l->function_name) == 0)
+ {
+ l->enabled = 0;
+ break;
+ }
+ }
+ }
+ }
- if (existing)
- free_bp_location (existing);
+ if (existing_locations)
+ free_bp_location (existing_locations);
}
@@ -7227,8 +7473,10 @@ breakpoint_re_set_one (void *bint)
don't need extra messages. If breakpoint is in bp_shlib_disabled
state, then user already saw the message about that breakpoint
being disabled, and don't want to see more errors. */
- if (not_found && (b->pending || b->enable_state == bp_shlib_disabled
- || b->enable_state == bp_disabled))
+ if (not_found
+ && (b->condition_not_parsed
+ || (b->loc && b->loc->shlib_disabled)
+ || b->enable_state == bp_disabled))
not_found_and_ok = 1;
if (!not_found_and_ok)
@@ -7249,7 +7497,7 @@ breakpoint_re_set_one (void *bint)
gdb_assert (sals.nelts == 1);
resolve_sal_pc (&sals.sals[0]);
- if (b->pending && s && s[0])
+ if (b->condition_not_parsed && s && s[0])
{
char *cond_string = 0;
int thread = -1;
@@ -7258,9 +7506,14 @@ breakpoint_re_set_one (void *bint)
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
+ b->condition_not_parsed = 0;
}
- update_breakpoint_location (b, sals);
+ update_breakpoint_locations (b, sals);
+
+ /* Now that this is re-enabled, check_duplicates
+ can be used. */
+ check_duplicates (b);
xfree (sals.sals);
break;
@@ -7524,6 +7777,48 @@ map_breakpoint_numbers (char *args, void
}
}
+static struct bp_location *
+find_location_by_number (char *number)
+{
+ char *dot = strchr (number, '.');
+ char *p1;
+ int bp_num;
+ int loc_num;
+ struct breakpoint *b;
+ struct bp_location *loc;
+
+ *dot = '\0';
+
+ p1 = number;
+ bp_num = get_number_or_range (&p1);
+ if (bp_num == 0)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bp_num)
+ {
+ break;
+ }
+
+ if (!b || b->number != bp_num)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ p1 = dot+1;
+ loc_num = get_number_or_range (&p1);
+ if (loc_num == 0)
+ error (_("Bad breakpoint location number '%s'"), number);
+
+ --loc_num;
+ loc = b->loc;
+ for (;loc_num && loc; --loc_num, loc = loc->next)
+ ;
+ if (!loc)
+ error (_("Bad breakpoint location number '%s'"), dot+1);
+
+ return loc;
+}
+
+
/* Set ignore-count of breakpoint number BPTNUM to COUNT.
If from_tty is nonzero, it prints a message to that effect,
which ends with a period (no newline). */
@@ -7579,6 +7874,13 @@ disable_command (char *args, int from_tt
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 0;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, disable_breakpoint);
}
@@ -7711,6 +8013,13 @@ enable_command (char *args, int from_tty
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 1;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, enable_breakpoint);
}
--- gdb/breakpoint.h (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/breakpoint.h (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -143,9 +143,6 @@ enum enable_state
{
bp_disabled, /* The eventpoint is inactive, and cannot trigger. */
bp_enabled, /* The eventpoint is active, and can trigger. */
- bp_shlib_disabled, /* The eventpoint's address is in an unloaded solib.
- The eventpoint will be automatically enabled
- and reset when that solib is loaded. */
bp_call_disabled, /* The eventpoint has been disabled while a call
into the inferior is "in flight", because some
eventpoints interfere with the implementation of
@@ -232,9 +229,14 @@ enum bp_loc_type
struct bp_location
{
- /* Chain pointer to the next breakpoint location. */
+ /* Chain pointer to the next breakpoint location for
+ the same parent breakpoint. */
struct bp_location *next;
+ /* Pointer to the next breakpoint location, in a global
+ list of all breakpoint locations. */
+ struct bp_location *global_next;
+
/* Type of this breakpoint location. */
enum bp_loc_type loc_type;
@@ -249,6 +251,14 @@ struct bp_location
PC locations, the evaluation of expression can be different for
different PCs. */
struct expression *cond;
+
+ /* This location's address is in an unloaded solib, and so this
+ location should not be inserted. It will be automatically
+ enabled when that solib is loaded. */
+ char shlib_disabled;
+
+ /* Is this particular location enabled. */
+ char enabled;
/* Nonzero if this breakpoint is now inserted. */
char inserted;
@@ -281,6 +291,8 @@ struct bp_location
processor's architectual constraints. */
CORE_ADDR requested_address;
+ char *function_name;
+
/* Details of the placed breakpoint, when inserted. */
struct bp_target_info target_info;
@@ -423,8 +435,10 @@ struct breakpoint
second bit : 0 normal breakpoint, 1 hardware breakpoint. */
int flag;
- /* Is breakpoint pending on shlib loads? */
- int pending;
+ /* Is breakpoint's condition not yet parsed because we found
+ no location initially so had no context to parse
+ the condition in. */
+ int condition_not_parsed;
};
\f
/* The following stuff is an abstract data type "bpstat" ("breakpoint
--- gdb/testsuite/gdb.cp/ovldbreak.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.cp/ovldbreak.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -153,7 +153,7 @@ set_bp_overloaded "foo::overload1arg" "$
# Verify the breakpoints.
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
\[\t \]+breakpoint already hit 1 time\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -211,7 +211,7 @@ gdb_expect {
}
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
\[\t \]+breakpoint already hit 1 time\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -290,7 +290,7 @@ gdb_expect {
}
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
--- gdb/testsuite/gdb.base/pending.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/pending.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -71,8 +71,8 @@ gdb_test_multiple "break pendfunc1" "set
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*" \
"single pending breakpoint info"
#
@@ -86,8 +86,8 @@ gdb_test "break main" \
"breakpoint function"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending plus real breakpoint info"
@@ -108,8 +108,8 @@ gdb_test_multiple "break pendfunc2" "Don
gdb_test "condition 1 k == 1" ""
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending plus condition"
@@ -121,8 +121,8 @@ gdb_test "info break" \
gdb_test "disable 1" ""
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending disabled"
@@ -134,8 +134,8 @@ gdb_test "commands 1\nprint k\nend" "" \
"Set commands for pending breakpoint"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
@@ -154,12 +154,12 @@ gdb_test_multiple "break pendshr.c:$bp2_
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
"multiple pending breakpoints"
@@ -179,13 +179,13 @@ gdb_test {ignore $bpnum 2} "Will ignore
"set ignore count on pending breakpoint 3"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
"multiple pending breakpoints 2"
#
@@ -253,7 +253,7 @@ gdb_test_multiple "break imaginary" "set
rerun_to_main
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*imaginary.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*imaginary.*" \
"verify pending breakpoint after restart"
--- gdb/testsuite/gdb.base/break.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/break.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -179,7 +179,7 @@ set bp_location8 [gdb_get_line_number "s
set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1]
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).*
\[0-9\]+\[\t \]+breakpoint keep y.* in factorial$proto at .*$srcfile:$bp_location7.*
@@ -309,7 +309,7 @@ gdb_test "tbreak $srcfile:$bp_location1
#
# check to see what breakpoints are set (temporary this time)
#
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
--- gdb/testsuite/gdb.base/annota3.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/annota3.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -127,8 +127,8 @@ gdb_expect {
send_gdb "info break\n"
gdb_expect_list "breakpoint info" "$gdb_prompt$" {
"\r\n\032\032post-prompt\r\n"
- "Num Type Disp Enb Address +What\r\n"
- "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
+ "Num Type Disp Enb Address +What\r\n"
+ "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
}
--- gdb/testsuite/gdb.base/sepdebug.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/sepdebug.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -179,7 +179,7 @@ set bp_location8 [gdb_get_line_number "s
set bp_location9 [gdb_get_line_number "set breakpoint 9 here"]
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile:($bp_location8|$bp_location9).*
\[0-9\]+\[\t \]+breakpoint keep y.* in factorial at .*$srcfile:$bp_location7.*
@@ -298,7 +298,7 @@ gdb_test "tbreak $srcfile:$bp_location1
#
# check to see what breakpoints are set (temporary this time)
#
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial at .*$srcfile:$bp_location7.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
--- gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -125,14 +125,14 @@ if {$hp_aCC_compiler} {
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location6.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker1$marker1_proto at .*$srcfile1:($bp_location15|$bp_location16).*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).*
-\[\t \]+stop only if a == 43.*" \
+\[\t \]+stop only if \\(a==43\\).*" \
"breakpoint info"
--- gdb/testsuite/gdb.base/unload.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/unload.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -81,8 +81,8 @@ gdb_test_multiple "break shrfunc1" "set
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*shrfunc1.*" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*shrfunc1.*" \
"single pending breakpoint info"
set unloadshr_line [gdb_get_line_number "unloadshr break" ${libsrcfile}]
--- gdb/testsuite/gdb.base/annota1.exp (/work/mb_mainline/7_pending) (revision 4752)
+++ gdb/testsuite/gdb.base/annota1.exp (/work/mb_mainline/8_multiple_locations) (revision 4752)
@@ -117,9 +117,9 @@ gdb_expect {
#
send_gdb "info break\n"
gdb_expect {
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
{pass "breakpoint info"}
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
{ setup_xfail "*-*-*" 1270
fail "breakpoint info"}
-re ".*$gdb_prompt$" { fail "breakpoint info" }
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-07 22:49 [8/9] multiple locations Vladimir Prus
2007-09-07 22:51 ` Vladimir Prus
@ 2007-09-08 11:46 ` Eli Zaretskii
2007-09-08 11:55 ` Vladimir Prus
2007-09-22 19:53 ` Vladimir Prus
2007-09-08 13:17 ` Mark Kettenis
2 siblings, 2 replies; 29+ messages in thread
From: Eli Zaretskii @ 2007-09-08 11:46 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> From: Vladimir Prus <vladimir@codesourcery.com>
> Date: Sat, 8 Sep 2007 02:48:52 +0400
>
> @@ -3397,30 +3448,79 @@ print_one_breakpoint (struct breakpoint
> struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
> struct cleanup *bkpt_chain;
> [...]
> - ui_out_field_int (uiout, "number", b->number);
> + if (part_of_multiple)
> + {
> + char buf[30];
Why 30? GNU coding standards frown on arbitrary constant sizes.
> + sprintf (buf, "%d.%d", b->number, loc_number);
> + ui_out_field_string (uiout, "number", buf);
I'm worried about this N.M thing: when the number of locations takes
2 or 3 digits, won't it disrupt the display alignment?
> - ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
> - ui_out_spaces (uiout, 2);
> + if (part_of_multiple)
> + ui_out_field_string (uiout, "enabled",
> + loc->shlib_disabled
> + ? (loc->enabled ? "y(p)" : "n(p)")
> + : (loc->enabled ? "y" : "n"));
These changes in the breakpoint display should be documented in the
user manual.
> + else if (header_of_multiple)
> + ui_out_field_string (uiout, "addr", "<MULTIPLE>");
And this.
> +/* set_raw_breakpoint() is a low level routine for allocating and
Another GNU coding standards thing: foo() should not be used as an
indication that `foo' is a function. Just say `foo' instead; foo()
looks like a call to `foo' with no arguments, which is not what you
mean.
> @@ -7579,6 +7874,13 @@ disable_command (char *args, int from_tt
> default:
> continue;
> }
> + else if (strchr (args, '.'))
> + {
> + struct bp_location *loc = find_location_by_number (args);
> + if (loc)
> + loc->enabled = 0;
> + check_duplicates (loc->owner);
> + }
This new feature needs documentation.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-08 11:46 ` Eli Zaretskii
@ 2007-09-08 11:55 ` Vladimir Prus
2007-09-08 12:28 ` Eli Zaretskii
2007-09-22 19:53 ` Vladimir Prus
1 sibling, 1 reply; 29+ messages in thread
From: Vladimir Prus @ 2007-09-08 11:55 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Saturday 08 September 2007 15:46:48 Eli Zaretskii wrote:
> > From: Vladimir Prus <vladimir@codesourcery.com>
> > Date: Sat, 8 Sep 2007 02:48:52 +0400
> >
> > @@ -3397,30 +3448,79 @@ print_one_breakpoint (struct breakpoint
> > struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
> > struct cleanup *bkpt_chain;
> > [...]
> > - ui_out_field_int (uiout, "number", b->number);
> > + if (part_of_multiple)
> > + {
> > + char buf[30];
>
> Why 30? GNU coding standards frown on arbitrary constant sizes.
>
> > + sprintf (buf, "%d.%d", b->number, loc_number);
Clearly, '30' is sufficient for 2^32 breakpoints, each having 2^32 locations.
I don't think using variable-size buffer is going to have any difference.
> > + ui_out_field_string (uiout, "number", buf);
>
> I'm worried about this N.M thing: when the number of locations takes
> 2 or 3 digits, won't it disrupt the display alignment?
This is valid concern. Now the column width for number is 3, which is easy to
overflow. I think increasing that is in order.
>
> > - ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
> > - ui_out_spaces (uiout, 2);
> > + if (part_of_multiple)
> > + ui_out_field_string (uiout, "enabled",
> > + loc->shlib_disabled
> > + ? (loc->enabled ? "y(p)" : "n(p)")
> > + : (loc->enabled ? "y" : "n"));
>
> These changes in the breakpoint display should be documented in the
> user manual.
As usual, I'll only send doc changes when the code is reviewed. My overview
email talks about those changes, so should be sufficient for review.
>
> > +/* set_raw_breakpoint() is a low level routine for allocating and
>
> Another GNU coding standards thing: foo() should not be used as an
> indication that `foo' is a function. Just say `foo' instead; foo()
> looks like a call to `foo' with no arguments, which is not what you
> mean.
Well, in fact this comment existed before my changes.
> > @@ -7579,6 +7874,13 @@ disable_command (char *args, int from_tt
> > default:
> > continue;
> > }
> > + else if (strchr (args, '.'))
> > + {
> > + struct bp_location *loc = find_location_by_number (args);
> > + if (loc)
> > + loc->enabled = 0;
> > + check_duplicates (loc->owner);
> > + }
>
> This new feature needs documentation.
Yes, see above.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-08 11:55 ` Vladimir Prus
@ 2007-09-08 12:28 ` Eli Zaretskii
0 siblings, 0 replies; 29+ messages in thread
From: Eli Zaretskii @ 2007-09-08 12:28 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> From: Vladimir Prus <vladimir@codesourcery.com>
> Date: Sat, 8 Sep 2007 15:55:00 +0400
> Cc: gdb-patches@sources.redhat.com
>
> > > + if (part_of_multiple)
> > > + {
> > > + char buf[30];
> >
> > Why 30? GNU coding standards frown on arbitrary constant sizes.
> >
> > > + sprintf (buf, "%d.%d", b->number, loc_number);
>
> Clearly, '30' is sufficient for 2^32 breakpoints, each having 2^32 locations.
Are we talking only about 32-bit machines?
> I don't think using variable-size buffer is going to have any difference.
I thought more about the lines of xsnprintf or some similar function,
which removes the need to worry about these issues.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-07 22:49 [8/9] multiple locations Vladimir Prus
2007-09-07 22:51 ` Vladimir Prus
2007-09-08 11:46 ` Eli Zaretskii
@ 2007-09-08 13:17 ` Mark Kettenis
2 siblings, 0 replies; 29+ messages in thread
From: Mark Kettenis @ 2007-09-08 13:17 UTC (permalink / raw)
To: vladimir; +Cc: gdb-patches
> From: Vladimir Prus <vladimir@codesourcery.com>
> Date: Sat, 8 Sep 2007 02:48:52 +0400
>
> This patch allows a breakpoint to have several breakpoint locations.
> There's lot of mechanical changes -- from iteration over breakpoints
> to iteration over locations. Also, this splits breakpoint enable/disable
> state, changeable by user, from 'shlib_disabled' state, maintained by
> gdb and stored inside location. The breakpoint printing code is modified
> to print locations of breakpoint. OK?
>
> - Volodya
>
> /* 1 */
> annotate_field (0);
> - ui_out_field_int (uiout, "number", b->number);
> + if (part_of_multiple)
> + {
> + char buf[30];
> + sprintf (buf, "%d.%d", b->number, loc_number);
Please don't use sprintf(); it's an evil function since it doesn't
check for buffer overflows. And even when you can prove that the
buffer is large enough, it's better not to use it, to make auditing
the code easier. So please use xsnprintf() (or snprintf() outside of
GDB).
Or if you want to address Eli's concerns, you could use xasprintf, but
make sure you xfree() the memory allocated by it.
Mark
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-08 11:46 ` Eli Zaretskii
2007-09-08 11:55 ` Vladimir Prus
@ 2007-09-22 19:53 ` Vladimir Prus
2007-09-23 4:13 ` Eli Zaretskii
1 sibling, 1 reply; 29+ messages in thread
From: Vladimir Prus @ 2007-09-22 19:53 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1775 bytes --]
On Saturday 08 September 2007 15:46:48 Eli Zaretskii wrote:
> > From: Vladimir Prus <vladimir@codesourcery.com>
> > Date: Sat, 8 Sep 2007 02:48:52 +0400
> >
> > @@ -3397,30 +3448,79 @@ print_one_breakpoint (struct breakpoint
> > struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
> > struct cleanup *bkpt_chain;
> > [...]
> > - ui_out_field_int (uiout, "number", b->number);
> > + if (part_of_multiple)
> > + {
> > + char buf[30];
>
> Why 30? GNU coding standards frown on arbitrary constant sizes.
> > Clearly, '30' is sufficient for 2^32 breakpoints, each having 2^32
> > locations.
>
> Are we talking only about 32-bit machines?
The address size is not important -- we only care about the *number*
of breakpoints and locations. And having 2^32 breakpoints each with
2^32 locations is seriously beyond reasonable number.
Anyway, to avoid further discussion, I've changed code to use
asprintf.
> > + sprintf (buf, "%d.%d", b->number, loc_number);
> > + ui_out_field_string (uiout, "number", buf);
>
> I'm worried about this N.M thing: when the number of locations takes
> 2 or 3 digits, won't it disrupt the display alignment?
I've increased the field width from 3 to 7 -- which will tolerate
3 digits of breakpoint number, dot, and 3 digits of breakpoint location
number. Clearly, this still can overflow, but we can get overflow in
the current gdb, too.
> > +/* set_raw_breakpoint() is a low level routine for allocating and
>
> Another GNU coding standards thing: foo() should not be used as an
> indication that `foo' is a function. Just say `foo' instead; foo()
> looks like a call to `foo' with no arguments, which is not what you
> mean.
Changed.
I attach revised patch. Does it look OK?
Thanks,
Volodya
[-- Attachment #2: mainline_8_multiple_locations.ChangeLog --]
[-- Type: text/plain, Size: 3190 bytes --]
gdb/
* breakpoint.h (enum enable_state): Remove the
bp_shlib_disabled enumerator.
(struct bp_location): New members shlib_disabled,
global_next, enabled and function_name.
Rename pending to condition_not_parsed.
* breakpoint.c (ALL_BP_LOCATIONS): Iterate over global_next.
(ALL_BP_LOCATIONS_SAFE): Likewise.
(breakpoint_enabled): Don't check for pending.
(condition_command): Free and update all locations of
a breakpoint.
(insert_bp_location): Adjust.
(software_breakpoint_inserted_here_p): Don't care
if breakpoint is enabled, as soon as it's inserted.
(print_it_typical): Print bpstat's location, not
bpstat's breakpoint's location.
(bpstat_stop_status): Iterate over all locations, not
all breakpoints.
(print_breakpoint_location): New.
(print_one_breakpoint): Renamed to
(print_one_breakpoint_location): ...this. Take
parameters to describe which location is being
printed. Modify code to properly print header
for several locations and individual locations.
(print_one_breakpoint): Print all locations.
(breakpoint_has_pc): New.
(describe_other_breakpoints): Use the above.
(check_duplicates): Renamed to...
(check_duplicates_for): .. this.
(check_duplicates): Use check_duplicates_for.
(allocate_bp_location): Adjust.
(set_raw_breakpoint_without_location): New,
extracted from set_raw_breakpoint.
(set_breakpoint_location_function): New.
(set_raw_breakpoint): Use
set_raw_breakpoint_without_location.
(make_breakpoint_permanent): Mark all locations
as inserted.
(disable_breakpoints_in_shlibs): Iterate over
locations.
(disable_breakpoints_in_unloaded_shlib): Likewise.
(re_enable_breakpoints_in_shlibs): Likewise.
(mention): Say "pending" when breakpoint has
zero locations. If breakpoint has more than one
location, say so.
(add_location_to_breakpoint): New.
(create_breakpoint): Accept symtabs_and_lines, not
symtab_and_line. Pass extra sals to
add_location_to_breakpoint.
(create_breakpoints): Pass symtabs_and_lines to
create_breakpoints.
(break_command_1): Make pending breakpoints
have zero locations.
(do_captured_breakpoint): Remove wrong allocation.
(clear_command): Iterate over all locations.
(unlink_locations_from_global_list): Renamed
from unlink_location_from_global_list. Remove
all locations.
(delete_breakpoint): Remove all locations.
Iterate over all locations when deciding which
other location to re-enable.
(all_locations_are_pending): New.
(update_breakpoint_locations): Renamed from
update_breakpoint_location. Try to match old
and new locations using names of containing
functions.
(breakpoint_re_set_one): Adjust.
(find_location_by_number): New.
(disable_command): Allow disabling individual location.
(enable_command): Allow enabling individual location.
* breakpoint.c: Adjust all uses of breakpoint's
enable state to for bp_shlib_disabled change.
gdb/testsuite/
* gdb.base/annota1.exp: Adjust for 'info break'
format changes.
* gdb.base/annota3.exp: Likewise.
* gdb.base/break.exp: Likewise.
* gdb.base/condbreak.exp: Likewise.
* gdb.base/pending.exp: Likewise.
* gdb.base/sepdebug.exp: Likewise.
* gdb.base/unload.exp: Likewise.
* gdb.base/ovldbreak.exp: Likewise.
[-- Attachment #3: mainline_8_multiple_locations.diff --]
[-- Type: text/x-diff, Size: 71014 bytes --]
--- gdb/breakpoint.c (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/breakpoint.c (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -275,11 +275,11 @@ static int overlay_events_enabled;
/* Similar iterators for the low-level breakpoints. */
-#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->next)
+#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->global_next)
#define ALL_BP_LOCATIONS_SAFE(B,TMP) \
for (B = bp_location_chain; \
- B ? (TMP=B->next, 1): 0; \
+ B ? (TMP=B->global_next, 1): 0; \
B = TMP)
/* True if breakpoint hit counts should be displayed in breakpoint info. */
@@ -356,7 +356,7 @@ static struct exception_event_record *cu
static int
breakpoint_enabled (struct breakpoint *b)
{
- return (b->enable_state == bp_enabled && !b->pending);
+ return (b->enable_state == bp_enabled);
}
/* Set breakpoint count to NUM. */
@@ -572,10 +572,13 @@ condition_command (char *arg, int from_t
if (b->number == bnum)
{
struct bp_location *loc = b->loc;
- if (loc->cond)
+ for (; loc; loc = loc->next)
{
- xfree (loc->cond);
- loc->cond = 0;
+ if (loc->cond)
+ {
+ xfree (loc->cond);
+ loc->cond = 0;
+ }
}
if (b->cond_string != NULL)
xfree (b->cond_string);
@@ -592,10 +595,11 @@ condition_command (char *arg, int from_t
/* I don't know if it matters whether this is the string the user
typed in or the decompiled expression. */
b->cond_string = savestring (arg, strlen (arg));
- if (!b->pending)
+ b->condition_not_parsed = 0;
+ for (loc = b->loc; loc; loc = loc->next)
{
- b->loc->cond = parse_exp_1 (&arg,
- block_for_pc (b->loc->address), 0);
+ arg = p;
+ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
@@ -846,7 +850,7 @@ insert_bp_location (struct bp_location *
if (!breakpoint_enabled (bpt->owner))
return 0;
- if (bpt->inserted || bpt->duplicate)
+ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate)
return 0;
/* Initialize the target-specific information. */
@@ -969,7 +973,7 @@ Note: automatically using hardware break
{
/* See also: disable_breakpoints_in_shlibs. */
val = 0;
- bpt->owner->enable_state = bp_shlib_disabled;
+ bpt->shlib_disabled = 1;
if (!*disabled_breaks)
{
fprintf_unfiltered (tmp_error_stream,
@@ -1808,9 +1812,7 @@ software_breakpoint_inserted_here_p (COR
if (bpt->loc_type != bp_loc_software_breakpoint)
continue;
- if ((breakpoint_enabled (bpt->owner)
- || bpt->owner->enable_state == bp_permanent)
- && bpt->inserted
+ if (bpt->inserted
&& bpt->address == pc) /* bp is enabled and matches pc */
{
if (overlay_debugging
@@ -2160,6 +2162,7 @@ print_it_typical (bpstat bs)
{
struct cleanup *old_chain, *ui_out_chain;
struct breakpoint *b;
+ struct bp_location *bl;
struct ui_stream *stb;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2167,15 +2170,16 @@ print_it_typical (bpstat bs)
which has since been deleted. */
if (bs->breakpoint_at == NULL)
return PRINT_UNKNOWN;
- b = bs->breakpoint_at->owner;
+ bl = bs->breakpoint_at;
+ b = bl->owner;
switch (b->type)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
- if (b->loc->address != b->loc->requested_address)
- breakpoint_adjustment_warning (b->loc->requested_address,
- b->loc->address,
+ if (bl->address != bl->requested_address)
+ breakpoint_adjustment_warning (bl->requested_address,
+ bl->address,
b->number, 1);
annotate_breakpoint (b->number);
ui_out_text (uiout, "\nBreakpoint ");
@@ -2672,7 +2676,8 @@ which its expression is valid.\n");
bpstat
bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint)
{
- struct breakpoint *b, *temp;
+ struct breakpoint *b = NULL;
+ struct bp_location *bl;
/* True if we've hit a breakpoint (as opposed to a watchpoint). */
int real_breakpoint = 0;
/* Root of the chain of bpstat's */
@@ -2681,8 +2686,10 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
bpstat bs = root_bs;
int thread_id = pid_to_thread_id (ptid);
- ALL_BREAKPOINTS_SAFE (b, temp)
+ ALL_BP_LOCATIONS (bl)
{
+ b = bl->owner;
+ gdb_assert (b);
if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
continue;
@@ -2697,11 +2704,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw) /* a non-watchpoint bp */
{
- if (b->loc->address != bp_addr) /* address doesn't match */
+ if (bl->address != bp_addr) /* address doesn't match */
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2719,11 +2726,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
if (b->type == bp_hardware_breakpoint)
{
- if (b->loc->address != bp_addr)
+ if (bl->address != bp_addr)
continue;
if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (b->loc->section)
- && !section_is_mapped (b->loc->section))
+ && section_is_overlay (bl->section)
+ && !section_is_mapped (bl->section))
continue;
}
@@ -2774,7 +2781,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* Come here if it's a watchpoint, or if the break address matches */
- bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */
+ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */
/* Watchpoints may change this, if not found to have triggered. */
bs->stop = 1;
@@ -2926,19 +2933,19 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
{
int value_is_zero = 0;
- if (b->loc->cond)
+ if (bl->cond)
{
/* Need to select the frame, with all that implies
so that the conditions will have the right context. */
select_frame (get_current_frame ());
value_is_zero
- = catch_errors (breakpoint_cond_eval, (b->loc->cond),
+ = catch_errors (breakpoint_cond_eval, (bl->cond),
"Error in testing breakpoint condition:\n",
RETURN_MASK_ALL);
/* FIXME-someday, should give breakpoint # */
free_all_values ();
}
- if (b->loc->cond && value_is_zero)
+ if (bl->cond && value_is_zero)
{
bs->stop = 0;
/* Don't consider this a hit. */
@@ -2985,9 +2992,9 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
/* The value of a hardware watchpoint hasn't changed, but the
intermediate memory locations we are watching may have. */
if (bs && !bs->stop &&
- (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
- bs->breakpoint_at->owner->type == bp_read_watchpoint ||
- bs->breakpoint_at->owner->type == bp_access_watchpoint))
+ (b->type == bp_hardware_watchpoint ||
+ b->type == bp_read_watchpoint ||
+ b->type == bp_access_watchpoint))
{
remove_breakpoints ();
insert_breakpoints ();
@@ -3349,10 +3356,54 @@ bpstat_get_triggered_catchpoints (bpstat
*cp_list = bs;
}
+static void print_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ char *wrap_indent,
+ struct ui_stream *stb)
+{
+ if (b->source_file)
+ {
+ struct symbol *sym
+ = find_pc_sect_function (loc->address, loc->section);
+ if (sym)
+ {
+ ui_out_text (uiout, "in ");
+ ui_out_field_string (uiout, "func",
+ SYMBOL_PRINT_NAME (sym));
+ ui_out_wrap_hint (uiout, wrap_indent);
+ ui_out_text (uiout, " at ");
+ }
+ ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_text (uiout, ":");
+
+ if (ui_out_is_mi_like_p (uiout))
+ {
+ struct symtab_and_line sal = find_pc_line (loc->address, 0);
+ char *fullname = symtab_to_fullname (sal.symtab);
+
+ if (fullname)
+ ui_out_field_string (uiout, "fullname", fullname);
+ }
+
+ ui_out_field_int (uiout, "line", b->line_number);
+ }
+ else if (!b->loc)
+ {
+ ui_out_field_string (uiout, "pending", b->addr_string);
+ }
+ else
+ {
+ print_address_symbolic (loc->address, stb->stream, demangle, "");
+ ui_out_field_stream (uiout, "at", stb);
+ }
+}
+
/* Print B to gdb_stdout. */
static void
-print_one_breakpoint (struct breakpoint *b,
- CORE_ADDR *last_addr)
+print_one_breakpoint_location (struct breakpoint *b,
+ struct bp_location *loc,
+ int loc_number,
+ CORE_ADDR *last_addr)
{
struct command_line *l;
struct symbol *sym;
@@ -3397,30 +3448,80 @@ print_one_breakpoint (struct breakpoint
struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb);
struct cleanup *bkpt_chain;
+ int header_of_multiple = 0;
+ int part_of_multiple = (loc != NULL);
+
+ gdb_assert (!loc || loc_number != 0);
+ /* See comment in print_one_breakpoint concerning
+ treatment of breakpoints with single disabled
+ location. */
+ if (loc == NULL
+ && (b->loc != NULL
+ && (b->loc->next != NULL || !b->loc->enabled)))
+ header_of_multiple = 1;
+ if (loc == NULL)
+ loc = b->loc;
+
annotate_record ();
bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
/* 1 */
annotate_field (0);
- ui_out_field_int (uiout, "number", b->number);
+ if (part_of_multiple)
+ {
+ char *formatted;
+ asprintf (&formatted, "%d.%d", b->number, loc_number);
+ ui_out_field_string (uiout, "number", formatted);
+ xfree (formatted);
+ }
+ else
+ {
+ ui_out_field_int (uiout, "number", b->number);
+ }
/* 2 */
annotate_field (1);
- if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
- || ((int) b->type != bptypes[(int) b->type].type))
- internal_error (__FILE__, __LINE__,
- _("bptypes table does not describe type #%d."),
- (int) b->type);
- ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "type");
+ else
+ {
+ if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0])))
+ || ((int) b->type != bptypes[(int) b->type].type))
+ internal_error (__FILE__, __LINE__,
+ _("bptypes table does not describe type #%d."),
+ (int) b->type);
+ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description);
+ }
/* 3 */
annotate_field (2);
- ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+ if (part_of_multiple)
+ ui_out_field_skip (uiout, "disp");
+ else
+ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]);
+
/* 4 */
annotate_field (3);
- ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
- ui_out_spaces (uiout, 2);
+ if (part_of_multiple)
+ ui_out_field_string (uiout, "enabled",
+ loc->shlib_disabled
+ ? (loc->enabled ? "y(p)" : "n(p)")
+ : (loc->enabled ? "y" : "n"));
+ else
+ {
+ int pending = (b->loc == NULL || b->loc->shlib_disabled);
+ /* For header of multiple, there's no point showing pending
+ state -- it will be apparent from the locations. */
+ if (header_of_multiple)
+ pending = 0;
+ ui_out_field_fmt (uiout, "enabled", "%c%s",
+ bpenables[(int) b->enable_state],
+ pending ? "(p)" : "");
+ if (!pending)
+ ui_out_spaces (uiout, 3);
+ }
+
/* 5 and 6 */
strcpy (wrap_indent, " ");
@@ -3433,7 +3534,14 @@ print_one_breakpoint (struct breakpoint
}
if (b->ops != NULL && b->ops->print_one != NULL)
- b->ops->print_one (b, last_addr);
+ {
+ /* Although the print_one can possibly print
+ all locations, calling it here is not likely
+ to get any nice result. So, make sure there's
+ just one location. */
+ gdb_assert (b->loc == NULL || b->loc->next == NULL);
+ b->ops->print_one (b, last_addr);
+ }
else
switch (b->type)
{
@@ -3545,51 +3653,22 @@ print_one_breakpoint (struct breakpoint
if (addressprint)
{
annotate_field (4);
- if (b->pending)
+ if (b->loc == NULL)
ui_out_field_string (uiout, "addr", "<PENDING>");
+ else if (header_of_multiple)
+ ui_out_field_string (uiout, "addr", "<MULTIPLE>");
else
- ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ ui_out_field_core_addr (uiout, "addr", loc->address);
}
annotate_field (5);
- *last_addr = b->loc->address;
- if (b->source_file)
- {
- sym = find_pc_sect_function (b->loc->address, b->loc->section);
- if (sym)
- {
- ui_out_text (uiout, "in ");
- ui_out_field_string (uiout, "func",
- SYMBOL_PRINT_NAME (sym));
- ui_out_wrap_hint (uiout, wrap_indent);
- ui_out_text (uiout, " at ");
- }
- ui_out_field_string (uiout, "file", b->source_file);
- ui_out_text (uiout, ":");
-
- if (ui_out_is_mi_like_p (uiout))
- {
- struct symtab_and_line sal = find_pc_line (b->loc->address, 0);
- char *fullname = symtab_to_fullname (sal.symtab);
-
- if (fullname)
- ui_out_field_string (uiout, "fullname", fullname);
- }
-
- ui_out_field_int (uiout, "line", b->line_number);
- }
- else if (b->pending)
- {
- ui_out_field_string (uiout, "pending", b->addr_string);
- }
- else
- {
- print_address_symbolic (b->loc->address, stb->stream, demangle, "");
- ui_out_field_stream (uiout, "at", stb);
- }
+ if (!header_of_multiple)
+ print_breakpoint_location (b, loc, wrap_indent, stb);
+ if (b->loc)
+ *last_addr = b->loc->address;
break;
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME: This seems to be redundant and lost here; see the
"stop only in" line a little further down. */
@@ -3599,7 +3678,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
- if (frame_id_p (b->frame_id))
+ if (part_of_multiple && frame_id_p (b->frame_id))
{
annotate_field (6);
ui_out_text (uiout, "\tstop only in stack frame at ");
@@ -3609,27 +3688,18 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (b->loc->cond && !ada_exception_catchpoint_p (b))
+ if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b))
{
/* We do not print the condition for Ada exception catchpoints
because the condition is an internal implementation detail
that we do not want to expose to the user. */
annotate_field (7);
ui_out_text (uiout, "\tstop only if ");
- print_expression (b->loc->cond, stb->stream);
- ui_out_field_stream (uiout, "cond", stb);
- ui_out_text (uiout, "\n");
- }
-
- if (b->pending && b->cond_string)
- {
- annotate_field (7);
- ui_out_text (uiout, "\tstop only if ");
ui_out_field_string (uiout, "cond", b->cond_string);
ui_out_text (uiout, "\n");
}
- if (b->thread != -1)
+ if (!part_of_multiple && b->thread != -1)
{
/* FIXME should make an annotation for this */
ui_out_text (uiout, "\tstop only in thread ");
@@ -3637,7 +3707,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, "\n");
}
- if (show_breakpoint_hit_counts && b->hit_count)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count)
{
/* FIXME should make an annotation for this */
if (ep_is_catchpoint (b))
@@ -3655,10 +3725,10 @@ print_one_breakpoint (struct breakpoint
/* Output the count also if it is zero, but only if this is
mi. FIXME: Should have a better test for this. */
if (ui_out_is_mi_like_p (uiout))
- if (show_breakpoint_hit_counts && b->hit_count == 0)
+ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0)
ui_out_field_int (uiout, "times", b->hit_count);
- if (b->ignore_count)
+ if (!part_of_multiple && b->ignore_count)
{
annotate_field (8);
ui_out_text (uiout, "\tignore next ");
@@ -3666,7 +3736,7 @@ print_one_breakpoint (struct breakpoint
ui_out_text (uiout, " hits\n");
}
- if ((l = b->commands))
+ if (!part_of_multiple && (l = b->commands))
{
struct cleanup *script_chain;
@@ -3679,6 +3749,35 @@ print_one_breakpoint (struct breakpoint
do_cleanups (old_chain);
}
+static void
+print_one_breakpoint (struct breakpoint *b,
+ CORE_ADDR *last_addr)
+{
+ print_one_breakpoint_location (b, NULL, 0, last_addr);
+
+ /* If this breakpoint has custom print function,
+ it's already printed. Otherwise, print individual
+ locations, if any. */
+ if (b->ops == NULL || b->ops->print_one == NULL)
+ {
+ /* If breakpoint has a single location that is
+ disabled, we print it as if it had
+ several locations, since otherwise it's hard to
+ represent "breakpoint enabled, location disabled"
+ situation. */
+ if (b->loc
+ && (b->loc->next || !b->loc->enabled)
+ && !ui_out_is_mi_like_p (uiout))
+ {
+ struct bp_location *loc;
+ int n = 1;
+ for (loc = b->loc; loc; loc = loc->next, ++n)
+ print_one_breakpoint_location (b, loc, n, last_addr);
+ }
+ }
+}
+
+
struct captured_breakpoint_query_args
{
int bnum;
@@ -3771,7 +3870,7 @@ breakpoint_1 (int bnum, int allflag)
annotate_breakpoints_headers ();
if (nr_printable_breakpoints > 0)
annotate_field (0);
- ui_out_table_header (uiout, 3, ui_left, "number", "Num"); /* 1 */
+ ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */
if (nr_printable_breakpoints > 0)
annotate_field (1);
ui_out_table_header (uiout, 14, ui_left, "type", "Type"); /* 2 */
@@ -3780,7 +3879,7 @@ breakpoint_1 (int bnum, int allflag)
ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */
if (nr_printable_breakpoints > 0)
annotate_field (3);
- ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */
+ ui_out_table_header (uiout, 4, ui_left, "enabled", "Enb"); /* 4 */
if (addressprint)
{
if (nr_printable_breakpoints > 0)
@@ -3852,6 +3951,19 @@ maintenance_info_breakpoints (char *bnum
breakpoint_1 (bnum, 1);
}
+static int
+breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section)
+{
+ struct bp_location *bl = b->loc;
+ for (; bl; bl = bl->next)
+ {
+ if (bl->address == pc
+ && (!overlay_debugging || bl->section == section))
+ return 1;
+ }
+ return 0;
+}
+
/* Print a message describing any breakpoints set at PC. */
static void
@@ -3861,9 +3973,7 @@ describe_other_breakpoints (CORE_ADDR pc
struct breakpoint *b;
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- others++;
+ others += breakpoint_has_pc (b, pc, section);
if (others > 0)
{
if (others == 1)
@@ -3871,26 +3981,24 @@ describe_other_breakpoints (CORE_ADDR pc
else /* if (others == ???) */
printf_filtered (_("Note: breakpoints "));
ALL_BREAKPOINTS (b)
- if (b->loc->address == pc) /* address match / overlay match */
- if (!b->pending && (!overlay_debugging || b->loc->section == section))
- {
- others--;
- printf_filtered ("%d", b->number);
- if (b->thread == -1 && thread != -1)
- printf_filtered (" (all threads)");
- else if (b->thread != -1)
- printf_filtered (" (thread %d)", b->thread);
- printf_filtered ("%s%s ",
- ((b->enable_state == bp_disabled ||
- b->enable_state == bp_shlib_disabled ||
- b->enable_state == bp_call_disabled)
- ? " (disabled)"
- : b->enable_state == bp_permanent
- ? " (permanent)"
- : ""),
- (others > 1) ? ","
- : ((others == 1) ? " and" : ""));
- }
+ if (breakpoint_has_pc (b, pc, section))
+ {
+ others--;
+ printf_filtered ("%d", b->number);
+ if (b->thread == -1 && thread != -1)
+ printf_filtered (" (all threads)");
+ else if (b->thread != -1)
+ printf_filtered (" (thread %d)", b->thread);
+ printf_filtered ("%s%s ",
+ ((b->enable_state == bp_disabled ||
+ b->enable_state == bp_call_disabled)
+ ? " (disabled)"
+ : b->enable_state == bp_permanent
+ ? " (permanent)"
+ : ""),
+ (others > 1) ? ","
+ : ((others == 1) ? " and" : ""));
+ }
printf_filtered (_("also set at pc "));
deprecated_print_address_numeric (pc, 1, gdb_stdout);
printf_filtered (".\n");
@@ -3951,22 +4059,17 @@ breakpoint_address_is_meaningful (struct
that one the official one, and the rest as duplicates. */
static void
-check_duplicates (struct breakpoint *bpt)
+check_duplicates_for (CORE_ADDR address, asection *section)
{
struct bp_location *b;
int count = 0;
struct bp_location *perm_bp = 0;
- CORE_ADDR address = bpt->loc->address;
- asection *section = bpt->loc->section;
-
- if (! breakpoint_address_is_meaningful (bpt))
- return;
ALL_BP_LOCATIONS (b)
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled
+ && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -3999,9 +4102,8 @@ check_duplicates (struct breakpoint *bpt
if (b != perm_bp)
{
if (b->owner->enable_state != bp_disabled
- && b->owner->enable_state != bp_shlib_disabled
- && !b->owner->pending
&& b->owner->enable_state != bp_call_disabled
+ && b->enabled && !b->shlib_disabled
&& b->address == address /* address / overlay match */
&& (!overlay_debugging || b->section == section)
&& breakpoint_address_is_meaningful (b->owner))
@@ -4018,6 +4120,18 @@ check_duplicates (struct breakpoint *bpt
}
static void
+check_duplicates (struct breakpoint *bpt)
+{
+ struct bp_location *bl = bpt->loc;
+
+ if (! breakpoint_address_is_meaningful (bpt))
+ return;
+
+ for (; bl; bl = bl->next)
+ check_duplicates_for (bl->address, bl->section);
+}
+
+static void
breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
int bnum, int have_bnum)
{
@@ -4089,6 +4203,8 @@ allocate_bp_location (struct breakpoint
loc->owner = bpt;
loc->cond = NULL;
+ loc->shlib_disabled = 0;
+ loc->enabled = 1;
switch (bp_type)
{
@@ -4134,9 +4250,9 @@ allocate_bp_location (struct breakpoint
bp_location_chain = loc;
else
{
- while (loc_p->next)
- loc_p = loc_p->next;
- loc_p->next = loc;
+ while (loc_p->global_next)
+ loc_p = loc_p->global_next;
+ loc_p->global_next = loc;
}
return loc;
@@ -4149,53 +4265,21 @@ static void free_bp_location (struct bp_
xfree (loc);
}
-/* set_raw_breakpoint() is a low level routine for allocating and
- partially initializing a breakpoint of type BPTYPE. The newly
- created breakpoint's address, section, source file name, and line
- number are provided by SAL. The newly created and partially
- initialized breakpoint is added to the breakpoint chain and
- is also returned as the value of this function.
-
- It is expected that the caller will complete the initialization of
- the newly created breakpoint struct as well as output any status
- information regarding the creation of a new breakpoint. In
- particular, set_raw_breakpoint() does NOT set the breakpoint
- number! Care should be taken to not allow an error() to occur
- prior to completing the initialization of the breakpoint. If this
- should happen, a bogus breakpoint will be left on the chain. */
+/* Helper to set_raw_breakpoint below. Creates a breakpoint
+ that has type BPTYPE and has no locations as yet. */
struct breakpoint *
-set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+set_raw_breakpoint_without_location (enum bptype bptype)
{
struct breakpoint *b, *b1;
- CORE_ADDR adjusted_address;
b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
memset (b, 0, sizeof (*b));
- /* Adjust the breakpoint's address prior to allocating a location.
- Once we call allocate_bp_location(), that mostly uninitialized
- location will be placed on the location chain. Adjustment of the
- breakpoint may cause read_memory_nobpt() to be called and we do
- not want its scan of the location chain to find a breakpoint and
- location that's only been partially initialized. */
- adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
-
- b->loc = allocate_bp_location (b, bptype);
- b->loc->requested_address = sal.pc;
- b->loc->address = adjusted_address;
-
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
- b->loc->section = sal.section;
b->type = bptype;
b->language = current_language->la_language;
b->input_radix = input_radix;
b->thread = -1;
- b->line_number = sal.line;
b->enable_state = bp_enabled;
b->next = 0;
b->silent = 0;
@@ -4207,7 +4291,7 @@ set_raw_breakpoint (struct symtab_and_li
b->forked_inferior_pid = 0;
b->exec_pathname = NULL;
b->ops = NULL;
- b->pending = 0;
+ b->condition_not_parsed = 0;
/* Add this breakpoint to the end of the chain
so that a list of breakpoints will come out in order
@@ -4222,6 +4306,65 @@ set_raw_breakpoint (struct symtab_and_li
b1 = b1->next;
b1->next = b;
}
+ return b;
+}
+
+/* Initialize loc->function_name. */
+static void
+set_breakpoint_location_function (struct bp_location *loc)
+{
+ if (loc->owner->type == bp_breakpoint
+ || loc->owner->type == bp_hardware_breakpoint)
+ {
+ find_pc_partial_function (loc->address, &(loc->function_name),
+ NULL, NULL);
+ if (loc->function_name)
+ loc->function_name = xstrdup (loc->function_name);
+ }
+}
+
+/* set_raw_breakpoint is a low level routine for allocating and
+ partially initializing a breakpoint of type BPTYPE. The newly
+ created breakpoint's address, section, source file name, and line
+ number are provided by SAL. The newly created and partially
+ initialized breakpoint is added to the breakpoint chain and
+ is also returned as the value of this function.
+
+ It is expected that the caller will complete the initialization of
+ the newly created breakpoint struct as well as output any status
+ information regarding the creation of a new breakpoint. In
+ particular, set_raw_breakpoint does NOT set the breakpoint
+ number! Care should be taken to not allow an error to occur
+ prior to completing the initialization of the breakpoint. If this
+ should happen, a bogus breakpoint will be left on the chain. */
+
+struct breakpoint *
+set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype)
+{
+ struct breakpoint *b = set_raw_breakpoint_without_location (bptype);
+ CORE_ADDR adjusted_address;
+
+ /* Adjust the breakpoint's address prior to allocating a location.
+ Once we call allocate_bp_location(), that mostly uninitialized
+ location will be placed on the location chain. Adjustment of the
+ breakpoint may cause read_memory_nobpt() to be called and we do
+ not want its scan of the location chain to find a breakpoint and
+ location that's only been partially initialized. */
+ adjusted_address = adjust_breakpoint_address (sal.pc, bptype);
+
+ b->loc = allocate_bp_location (b, bptype);
+ b->loc->requested_address = sal.pc;
+ b->loc->address = adjusted_address;
+
+ if (sal.symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+ b->loc->section = sal.section;
+ b->line_number = sal.line;
+
+ set_breakpoint_location_function (b->loc);
check_duplicates (b);
breakpoints_changed ();
@@ -4235,10 +4378,16 @@ set_raw_breakpoint (struct symtab_and_li
void
make_breakpoint_permanent (struct breakpoint *b)
{
+ struct bp_location *bl;
b->enable_state = bp_permanent;
- /* By definition, permanent breakpoints are already present in the code. */
- b->loc->inserted = 1;
+ /* By definition, permanent breakpoints are already present in the code.
+ Mark all locations as inserted. For now, make_breakpoint_permanent
+ is called in just one place, so it's hard to say if it's reasonable
+ to have permanent breakpoint with multiple locations or not,
+ but it's easy to implmement. */
+ for (bl = b->loc; bl; bl = bl->next)
+ bl->inserted = 1;
}
static struct breakpoint *
@@ -4431,20 +4580,28 @@ create_solib_event_breakpoint (CORE_ADDR
void
disable_breakpoints_in_shlibs (void)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
+ struct breakpoint *b = loc->owner;
+ /* We apply the check to all breakpoints, including disabled
+ for those with loc->duplicate set. This is so that when breakpoint
+ becomes enabled, or the duplicate is removed, gdb will try to insert
+ all breakpoints. If we don't set shlib_disabled here, we'll try
+ to insert those breakpoints and fail. */
if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint))
- && breakpoint_enabled (b) && !b->loc->duplicate
+ && !loc->shlib_disabled
#ifdef PC_SOLIB
- && PC_SOLIB (b->loc->address)
+ && PC_SOLIB (loc->address)
#else
- && solib_address (b->loc->address)
+ && solib_address (loc->address)
#endif
)
- b->enable_state = bp_shlib_disabled;
+ {
+ loc->shlib_disabled = 1;
+ }
}
}
@@ -4454,27 +4611,28 @@ disable_breakpoints_in_shlibs (void)
void
disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
{
- struct breakpoint *b;
+ struct bp_location *loc;
int disabled_shlib_breaks = 0;
- ALL_BREAKPOINTS (b)
+ ALL_BP_LOCATIONS (loc)
{
- if ((b->loc->loc_type == bp_loc_hardware_breakpoint
- || b->loc->loc_type == bp_loc_software_breakpoint)
- && breakpoint_enabled (b) && !b->loc->duplicate)
+ struct breakpoint *b = loc->owner;
+ if ((loc->loc_type == bp_loc_hardware_breakpoint
+ || loc->loc_type == bp_loc_software_breakpoint)
+ && !loc->shlib_disabled)
{
#ifdef PC_SOLIB
- char *so_name = PC_SOLIB (b->loc->address);
+ char *so_name = PC_SOLIB (loc->address);
#else
- char *so_name = solib_address (b->loc->address);
+ char *so_name = solib_address (loc->address);
#endif
if (so_name && !strcmp (so_name, solib->so_name))
{
- b->enable_state = bp_shlib_disabled;
+ loc->shlib_disabled = 1;
/* At this point, we cannot rely on remove_breakpoint
succeeding so we must mark the breakpoint as not inserted
to prevent future errors occurring in remove_breakpoints. */
- b->loc->inserted = 0;
+ loc->inserted = 0;
if (!disabled_shlib_breaks)
{
target_terminal_ours_for_output ();
@@ -4894,7 +5052,7 @@ mention (struct breakpoint *b)
{
/* i18n: cagney/2005-02-11: Below needs to be merged into a
single string. */
- if (b->pending)
+ if (b->loc == NULL)
{
printf_filtered (_(" (%s) pending."), b->addr_string);
}
@@ -4908,6 +5066,16 @@ mention (struct breakpoint *b)
if (b->source_file)
printf_filtered (": file %s, line %d.",
b->source_file, b->line_number);
+
+ if (b->loc->next)
+ {
+ struct bp_location *loc = b->loc;
+ int n = 0;
+ for (; loc; loc = loc->next)
+ ++n;
+ printf_filtered (" (%d locations)", n);
+ }
+
}
}
do_cleanups (old_chain);
@@ -4917,6 +5085,24 @@ mention (struct breakpoint *b)
}
\f
+static struct bp_location *
+add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype,
+ const struct symtab_and_line *sal)
+{
+ struct bp_location *loc, **tmp;
+
+ loc = allocate_bp_location (b, bptype);
+ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
+ ;
+ *tmp = loc;
+ loc->requested_address = sal->pc;
+ loc->address = adjust_breakpoint_address (loc->requested_address,
+ bptype);
+ loc->section = sal->section;
+
+ set_breakpoint_location_function (loc);
+ return loc;
+}
/* Create a breakpoint with SAL as location. Use ADDR_STRING
as textual description of the location, and COND_STRING
@@ -4926,13 +5112,14 @@ mention (struct breakpoint *b)
create_breakpoints function. */
static void
-create_breakpoint (struct symtab_and_line sal, char *addr_string,
+create_breakpoint (struct symtabs_and_lines sals, char *addr_string,
char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count, int from_tty,
struct breakpoint *pending_bp)
{
- struct breakpoint *b;
+ struct breakpoint *b = NULL;
+ int i;
if (type == bp_hardware_breakpoint)
{
@@ -4946,50 +5133,46 @@ create_breakpoint (struct symtab_and_lin
error (_("Hardware breakpoints used exceeds limit."));
}
- if (from_tty)
- describe_other_breakpoints (sal.pc, sal.section, thread);
-
- b = set_raw_breakpoint (sal, type);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->thread = thread;
+ for (i = 0; i < sals.nelts; ++i)
+ {
+ struct symtab_and_line sal = sals.sals[i];
+ struct bp_location *loc;
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc, sal.section, thread);
+
+ if (i == 0)
+ {
+ b = set_raw_breakpoint (sal, type);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->thread = thread;
- b->cond_string = cond_string;
- b->ignore_count = ignore_count;
- b->enable_state = bp_enabled;
- b->disposition = disposition;
- /* If resolving a pending breakpoint, a check must be made to see if
- the user has specified a new condition or commands for the
- breakpoint. A new condition will override any condition that was
- initially specified with the initial breakpoint command. */
- if (pending_bp)
- {
- if (pending_bp->cond_string)
- b->cond_string = savestring (pending_bp->cond_string,
- strlen (pending_bp->cond_string));
-
- /* If there are commands associated with the breakpoint, they should
- be copied too. */
- if (pending_bp->commands)
- b->commands = copy_command_lines (pending_bp->commands);
-
- /* We have to copy over the ignore_count and thread as well. */
- b->ignore_count = pending_bp->ignore_count;
- b->thread = pending_bp->thread;
- }
+ b->cond_string = cond_string;
+ b->ignore_count = ignore_count;
+ b->enable_state = bp_enabled;
+ b->disposition = disposition;
- if (b->cond_string)
- {
- char *arg = b->cond_string;
- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
- if (*arg)
+ loc = b->loc;
+ }
+ else
{
- if (pending_bp)
- error (_("Junk at end of pending breakpoint condition expression"));
- else
- error (_("Garbage %s follows condition"), arg);
+ loc = add_location_to_breakpoint (b, type, &sal);
}
- }
+
+ if (b->cond_string)
+ {
+ char *arg = b->cond_string;
+ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ if (*arg)
+ {
+ if (pending_bp)
+ error (_("Junk at end of pending breakpoint condition expression"));
+ else
+ error (_("Garbage %s follows condition"), arg);
+ }
+ }
+ }
if (addr_string)
b->addr_string = addr_string;
@@ -5031,7 +5214,11 @@ create_breakpoints (struct symtabs_and_l
int i;
for (i = 0; i < sals.nelts; ++i)
{
- create_breakpoint (sals.sals[i], addr_string[i],
+ struct symtabs_and_lines sals2;
+ sals2.sals = sals.sals + i;
+ sals2.nelts = 1;
+
+ create_breakpoint (sals2, addr_string[i],
cond_string, type, disposition,
thread, ignore_count, from_tty,
pending_bp);
@@ -5360,19 +5547,19 @@ break_command_1 (char *arg, int flag, in
make_cleanup (xfree, copy_arg);
- b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
- : bp_breakpoint);
+ b = set_raw_breakpoint_without_location (hardwareflag
+ ? bp_hardware_breakpoint
+ : bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->loc->cond = NULL;
b->thread = thread;
b->addr_string = addr_string[0];
b->cond_string = cond_string;
b->ignore_count = ignore_count;
- b->pending = 1;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->from_tty = from_tty;
b->flag = flag;
+ b->condition_not_parsed = 1;
mention (b);
}
@@ -5411,7 +5598,7 @@ do_captured_breakpoint (struct ui_out *u
struct cleanup *breakpoint_chain = NULL;
int i;
char **addr_string;
- char *cond_string;
+ char *cond_string = 0;
char *address_end;
@@ -5440,10 +5627,6 @@ do_captured_breakpoint (struct ui_out *u
cond = xcalloc (sals.nelts, sizeof (struct expression *));
make_cleanup (xfree, cond);
- /* Allocate space for all the cond strings. */
- cond_string = xcalloc (sals.nelts, sizeof (char **));
- make_cleanup (xfree, cond_string);
-
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
to be part of a breakpoint. If the breakpoint create goes
@@ -6733,23 +6916,35 @@ clear_command (char *arg, int from_tty)
breakpoint chain, and add them to the 'found' chain. */
ALL_BREAKPOINTS_SAFE (b, tmp)
{
+ int match = 0;
/* Are we going to delete b? */
if (b->type != bp_none
&& b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
- && b->type != bp_access_watchpoint
- /* Not if b is a watchpoint of any sort... */
- && (((sal.pc && (b->loc->address == sal.pc))
- && (!section_is_overlay (b->loc->section)
- || b->loc->section == sal.section))
- /* Yes, if sal.pc matches b (modulo overlays). */
- || ((default_match || (0 == sal.pc))
- && b->source_file != NULL
- && sal.symtab != NULL
- && strcmp (b->source_file, sal.symtab->filename) == 0
- && b->line_number == sal.line)))
- /* Yes, if sal source file and line matches b. */
+ && b->type != bp_access_watchpoint)
+ {
+ struct bp_location *loc = b->loc;
+ for (; loc; loc = loc->next)
+ {
+ int pc_match = sal.pc
+ && (loc->address == sal.pc)
+ && (!section_is_overlay (loc->section)
+ || loc->section == sal.section);
+ int line_match = ((default_match || (0 == sal.pc))
+ && b->source_file != NULL
+ && sal.symtab != NULL
+ && strcmp (b->source_file, sal.symtab->filename) == 0
+ && b->line_number == sal.line);
+ if (pc_match || line_match)
+ {
+ match = 1;
+ break;
+ }
+ }
+ }
+
+ if (match)
{
/* Remove it from breakpoint_chain... */
if (b == breakpoint_chain)
@@ -6824,6 +7019,35 @@ breakpoint_auto_delete (bpstat bs)
}
}
+/* Remove locations of breakpoint BPT from
+ the global list of breakpoint locations. */
+
+static void
+unlink_locations_from_global_list (struct breakpoint *bpt)
+{
+ /* This code assumes that the locations
+ of a breakpoint are found in the global list
+ in the same order, but not necessary adjacent. */
+ struct bp_location **tmp = &bp_location_chain;
+ struct bp_location *here = bpt->loc;
+
+ if (here == NULL)
+ return;
+
+ for (; *tmp && here;)
+ {
+ if (*tmp == here)
+ {
+ *tmp = here->global_next;
+ here = here->next;
+ }
+ else
+ {
+ tmp = &((*tmp)->global_next);
+ }
+ }
+}
+
/* Delete a breakpoint and clean up all traces of it in the data
structures. */
@@ -6856,17 +7080,23 @@ delete_breakpoint (struct breakpoint *bp
deprecated_delete_breakpoint_hook (bpt);
breakpoint_delete_event (bpt->number);
- if (bpt->loc->inserted)
- remove_breakpoint (bpt->loc, mark_inserted);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ if (loc->inserted)
+ remove_breakpoint (loc, mark_inserted);
+
+ free_valchain (loc);
- free_valchain (bpt->loc);
+ if (loc->cond)
+ xfree (loc->cond);
+
+ if (loc->function_name)
+ xfree (loc->function_name);
+ }
if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next;
- if (bp_location_chain == bpt->loc)
- bp_location_chain = bpt->loc->next;
-
/* If we have callback-style exception catchpoints, don't go through
the adjustments to the C++ runtime library etc. if the inferior
isn't actually running. target_enable_exception_callback for a
@@ -6896,82 +7126,83 @@ delete_breakpoint (struct breakpoint *bp
break;
}
- ALL_BP_LOCATIONS (loc)
- if (loc->next == bpt->loc)
- {
- loc->next = bpt->loc->next;
- break;
- }
+ unlink_locations_from_global_list (bpt);
check_duplicates (bpt);
- /* If this breakpoint was inserted, and there is another breakpoint
- at the same address, we need to insert the other breakpoint. */
- if (bpt->loc->inserted
- && bpt->type != bp_hardware_watchpoint
+
+ if (bpt->type != bp_hardware_watchpoint
&& bpt->type != bp_read_watchpoint
&& bpt->type != bp_access_watchpoint
&& bpt->type != bp_catch_fork
&& bpt->type != bp_catch_vfork
&& bpt->type != bp_catch_exec)
- {
- ALL_BREAKPOINTS (b)
- if (b->loc->address == bpt->loc->address
- && b->loc->section == bpt->loc->section
- && !b->loc->duplicate
- && b->enable_state != bp_disabled
- && b->enable_state != bp_shlib_disabled
- && !b->pending
- && b->enable_state != bp_call_disabled)
- {
- int val;
-
- /* We should never reach this point if there is a permanent
- breakpoint at the same address as the one being deleted.
- If there is a permanent breakpoint somewhere, it should
- always be the only one inserted. */
- if (b->enable_state == bp_permanent)
- internal_error (__FILE__, __LINE__,
- _("another breakpoint was inserted on top of "
- "a permanent breakpoint"));
-
- memset (&b->loc->target_info, 0, sizeof (b->loc->target_info));
- b->loc->target_info.placed_address = b->loc->address;
- if (b->type == bp_hardware_breakpoint)
- val = target_insert_hw_breakpoint (&b->loc->target_info);
- else
- val = target_insert_breakpoint (&b->loc->target_info);
+ for (loc = bpt->loc; loc; loc = loc->next)
+ {
+ /* If this breakpoint location was inserted, and there is
+ another breakpoint at the same address, we need to
+ insert the other breakpoint. */
+ if (loc->inserted)
+ {
+ struct bp_location *loc2;
+ ALL_BP_LOCATIONS (loc2)
+ if (loc2->address == loc->address
+ && loc2->section == loc->section
+ && !loc->duplicate
+ && loc2->owner->enable_state != bp_disabled
+ && loc2->enabled
+ && !loc2->shlib_disabled
+ && loc2->owner->enable_state != bp_call_disabled)
+ {
+ int val;
- /* If there was an error in the insert, print a message, then stop execution. */
- if (val != 0)
- {
- struct ui_file *tmp_error_stream = mem_fileopen ();
- make_cleanup_ui_file_delete (tmp_error_stream);
-
+ /* We should never reach this point if there is a permanent
+ breakpoint at the same address as the one being deleted.
+ If there is a permanent breakpoint somewhere, it should
+ always be the only one inserted. */
+ if (loc2->owner->enable_state == bp_permanent)
+ internal_error (__FILE__, __LINE__,
+ _("another breakpoint was inserted on top of "
+ "a permanent breakpoint"));
+
+ memset (&loc2->target_info, 0, sizeof (loc2->target_info));
+ loc2->target_info.placed_address = loc2->address;
+ if (b->type == bp_hardware_breakpoint)
+ val = target_insert_hw_breakpoint (&loc2->target_info);
+ else
+ val = target_insert_breakpoint (&loc2->target_info);
- if (b->type == bp_hardware_breakpoint)
- {
- fprintf_unfiltered (tmp_error_stream,
- "Cannot insert hardware breakpoint %d.\n"
- "You may have requested too many hardware breakpoints.\n",
- b->number);
- }
- else
- {
- fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
- fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
- deprecated_print_address_numeric (b->loc->address, 1, tmp_error_stream);
- fprintf_filtered (tmp_error_stream, ": %s.\n",
- safe_strerror (val));
- }
-
- fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
- target_terminal_ours_for_output ();
- error_stream(tmp_error_stream);
- }
- else
- b->loc->inserted = 1;
- }
- }
+ /* If there was an error in the insert, print a message, then stop execution. */
+ if (val != 0)
+ {
+ struct ui_file *tmp_error_stream = mem_fileopen ();
+ make_cleanup_ui_file_delete (tmp_error_stream);
+
+
+ if (b->type == bp_hardware_breakpoint)
+ {
+ fprintf_unfiltered (tmp_error_stream,
+ "Cannot insert hardware breakpoint %d.\n"
+ "You may have requested too many hardware breakpoints.\n",
+ b->number);
+ }
+ else
+ {
+ fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number);
+ fprintf_filtered (tmp_error_stream, "Error accessing memory address ");
+ deprecated_print_address_numeric (loc2->address, 1, tmp_error_stream);
+ fprintf_filtered (tmp_error_stream, ": %s.\n",
+ safe_strerror (val));
+ }
+
+ fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process.");
+ target_terminal_ours_for_output ();
+ error_stream(tmp_error_stream);
+ }
+ else
+ loc2->inserted = 1;
+ }
+ }
+ }
free_command_lines (&bpt->commands);
if (bpt->cond_string != NULL)
@@ -7013,9 +7244,12 @@ delete_breakpoint (struct breakpoint *bp
bp, we mark it as deleted before freeing its storage. */
bpt->type = bp_none;
- if (bpt->loc->cond)
- xfree (bpt->loc->cond);
- xfree (bpt->loc);
+ for (loc = bpt->loc; loc;)
+ {
+ struct bp_location *loc_next = loc->next;
+ xfree (loc);
+ loc = loc_next;
+ }
xfree (bpt);
}
@@ -7083,94 +7317,95 @@ delete_command (char *arg, int from_tty)
map_breakpoint_numbers (arg, delete_breakpoint);
}
-static void
-unlink_locations_from_global_list (struct breakpoint *bpt)
- /* Remove locations of this breakpoint from the list of
- all breakpoint locations. */
+static int
+all_locations_are_pending (struct bp_location *loc)
{
- struct bp_location **tmp = &bp_location_chain;
- struct bp_location *here = bpt->loc;
-
- if (here == NULL)
- return;
-
- for (; *tmp && *tmp != here; tmp = &((*tmp)->next));
- gdb_assert (*tmp);
-
- *tmp = here->next;
+ for (; loc; loc = loc->next)
+ if (!loc->shlib_disabled)
+ return 0;
+ return 1;
}
-
static void
-update_breakpoint_location (struct breakpoint *b,
- struct symtabs_and_lines sals)
+update_breakpoint_locations (struct breakpoint *b,
+ struct symtabs_and_lines sals)
{
int i;
char *s;
- /* FIXME: memleak. */
- struct bp_location *existing = b->loc;
- struct bp_location *loc;
- struct symtab_and_line sal;
-
- if (b->enable_state == bp_shlib_disabled && sals.nelts == 0)
+ struct bp_location *existing_locations = b->loc;
+
+ /* If there's no new locations, and all existing locations
+ are pending, don't do anything. This optimizes
+ the common case where all locations are in the same
+ shared library, that was unloaded. We'd like to
+ retain the location, so that when the library
+ is loaded again, we don't loose the enabled/disabled
+ status of the individual locations. */
+ if (all_locations_are_pending (existing_locations) && sals.nelts == 0)
return;
unlink_locations_from_global_list (b);
b->loc = NULL;
- gdb_assert (sals.nelts == 0 || sals.nelts == 1);
- if (sals.nelts == 0)
- return;
- sal = sals.sals[0];
-
- loc = allocate_bp_location (b, b->type);
- loc->requested_address = sal.pc;
- loc->address = adjust_breakpoint_address (loc->requested_address,
- b->type);
- loc->section = sal.section;
- b->loc = loc;
-
- /* Reparse conditions, they might contain references to the
- old symtab. */
- if (b->cond_string != NULL)
+ for (i = 0; i < sals.nelts; ++i)
{
- struct gdb_exception e;
-
- s = b->cond_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
- {
- loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc),
- 0);
- }
- if (e.reason < 0)
- {
- warning (_("failed to reevaluate condition for breakpoint %d: %s"),
- b->number, e.message);
- b->enable_state = bp_disabled;
- }
- }
+ struct bp_location *new_loc =
+ add_location_to_breakpoint (b, b->type, &(sals.sals[i]));
- if (b->source_file != NULL)
- xfree (b->source_file);
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file =
- savestring (sal.symtab->filename,
- strlen (sal.symtab->filename));
+ /* Reparse conditions, they might contain references to the
+ old symtab. */
+ if (b->cond_string != NULL)
+ {
+ struct gdb_exception e;
- if (b->line_number == 0)
- b->line_number = sal.line;
+ s = b->cond_string;
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc),
+ 0);
+ }
+ if (e.reason < 0)
+ {
+ warning (_("failed to reevaluate condition for breakpoint %d: %s"),
+ b->number, e.message);
+ new_loc->enabled = 0;
+ }
+ }
- if (b->enable_state == bp_shlib_disabled)
- b->enable_state = bp_enabled;
+ if (b->source_file != NULL)
+ xfree (b->source_file);
+ if (sals.sals[i].symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file =
+ savestring (sals.sals[i].symtab->filename,
+ strlen (sals.sals[i].symtab->filename));
- b->pending = 0;
+ if (b->line_number == 0)
+ b->line_number = sals.sals[i].line;
+ }
- check_duplicates (b);
+ /* If possible, carry over 'disable' status from existing breakpoints. */
+ {
+ struct bp_location *e = existing_locations;
+ for (; e; e = e->next)
+ {
+ if (!e->enabled && e->function_name)
+ {
+ struct bp_location *l = b->loc;
+ for (; l; l = l->next)
+ if (l->function_name
+ && strcmp (e->function_name, l->function_name) == 0)
+ {
+ l->enabled = 0;
+ break;
+ }
+ }
+ }
+ }
- if (existing)
- free_bp_location (existing);
+ if (existing_locations)
+ free_bp_location (existing_locations);
}
@@ -7227,8 +7462,10 @@ breakpoint_re_set_one (void *bint)
don't need extra messages. If breakpoint is in bp_shlib_disabled
state, then user already saw the message about that breakpoint
being disabled, and don't want to see more errors. */
- if (not_found && (b->pending || b->enable_state == bp_shlib_disabled
- || b->enable_state == bp_disabled))
+ if (not_found
+ && (b->condition_not_parsed
+ || (b->loc && b->loc->shlib_disabled)
+ || b->enable_state == bp_disabled))
not_found_and_ok = 1;
if (!not_found_and_ok)
@@ -7249,7 +7486,7 @@ breakpoint_re_set_one (void *bint)
gdb_assert (sals.nelts == 1);
resolve_sal_pc (&sals.sals[0]);
- if (b->pending && s && s[0])
+ if (b->condition_not_parsed && s && s[0])
{
char *cond_string = 0;
int thread = -1;
@@ -7258,9 +7495,14 @@ breakpoint_re_set_one (void *bint)
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
+ b->condition_not_parsed = 0;
}
- update_breakpoint_location (b, sals);
+ update_breakpoint_locations (b, sals);
+
+ /* Now that this is re-enabled, check_duplicates
+ can be used. */
+ check_duplicates (b);
xfree (sals.sals);
break;
@@ -7524,6 +7766,48 @@ map_breakpoint_numbers (char *args, void
}
}
+static struct bp_location *
+find_location_by_number (char *number)
+{
+ char *dot = strchr (number, '.');
+ char *p1;
+ int bp_num;
+ int loc_num;
+ struct breakpoint *b;
+ struct bp_location *loc;
+
+ *dot = '\0';
+
+ p1 = number;
+ bp_num = get_number_or_range (&p1);
+ if (bp_num == 0)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bp_num)
+ {
+ break;
+ }
+
+ if (!b || b->number != bp_num)
+ error (_("Bad breakpoint number '%s'"), number);
+
+ p1 = dot+1;
+ loc_num = get_number_or_range (&p1);
+ if (loc_num == 0)
+ error (_("Bad breakpoint location number '%s'"), number);
+
+ --loc_num;
+ loc = b->loc;
+ for (;loc_num && loc; --loc_num, loc = loc->next)
+ ;
+ if (!loc)
+ error (_("Bad breakpoint location number '%s'"), dot+1);
+
+ return loc;
+}
+
+
/* Set ignore-count of breakpoint number BPTNUM to COUNT.
If from_tty is nonzero, it prints a message to that effect,
which ends with a period (no newline). */
@@ -7579,6 +7863,13 @@ disable_command (char *args, int from_tt
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 0;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, disable_breakpoint);
}
@@ -7711,6 +8002,13 @@ enable_command (char *args, int from_tty
default:
continue;
}
+ else if (strchr (args, '.'))
+ {
+ struct bp_location *loc = find_location_by_number (args);
+ if (loc)
+ loc->enabled = 1;
+ check_duplicates (loc->owner);
+ }
else
map_breakpoint_numbers (args, enable_breakpoint);
}
--- gdb/breakpoint.h (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/breakpoint.h (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -143,9 +143,6 @@ enum enable_state
{
bp_disabled, /* The eventpoint is inactive, and cannot trigger. */
bp_enabled, /* The eventpoint is active, and can trigger. */
- bp_shlib_disabled, /* The eventpoint's address is in an unloaded solib.
- The eventpoint will be automatically enabled
- and reset when that solib is loaded. */
bp_call_disabled, /* The eventpoint has been disabled while a call
into the inferior is "in flight", because some
eventpoints interfere with the implementation of
@@ -232,9 +229,14 @@ enum bp_loc_type
struct bp_location
{
- /* Chain pointer to the next breakpoint location. */
+ /* Chain pointer to the next breakpoint location for
+ the same parent breakpoint. */
struct bp_location *next;
+ /* Pointer to the next breakpoint location, in a global
+ list of all breakpoint locations. */
+ struct bp_location *global_next;
+
/* Type of this breakpoint location. */
enum bp_loc_type loc_type;
@@ -249,6 +251,14 @@ struct bp_location
locations, the evaluation of expression can be different for
different locations. */
struct expression *cond;
+
+ /* This location's address is in an unloaded solib, and so this
+ location should not be inserted. It will be automatically
+ enabled when that solib is loaded. */
+ char shlib_disabled;
+
+ /* Is this particular location enabled. */
+ char enabled;
/* Nonzero if this breakpoint is now inserted. */
char inserted;
@@ -281,6 +291,8 @@ struct bp_location
processor's architectual constraints. */
CORE_ADDR requested_address;
+ char *function_name;
+
/* Details of the placed breakpoint, when inserted. */
struct bp_target_info target_info;
@@ -423,8 +435,10 @@ struct breakpoint
second bit : 0 normal breakpoint, 1 hardware breakpoint. */
int flag;
- /* Is breakpoint pending on shlib loads? */
- int pending;
+ /* Is breakpoint's condition not yet parsed because we found
+ no location initially so had no context to parse
+ the condition in. */
+ int condition_not_parsed;
};
\f
/* The following stuff is an abstract data type "bpstat" ("breakpoint
--- gdb/testsuite/gdb.cp/ovldbreak.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.cp/ovldbreak.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -153,7 +153,7 @@ set_bp_overloaded "foo::overload1arg" "$
# Verify the breakpoints.
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
\[\t \]+breakpoint already hit 1 time\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -211,7 +211,7 @@ gdb_expect {
}
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
\[\t \]+breakpoint already hit 1 time\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
@@ -290,7 +290,7 @@ gdb_expect {
}
gdb_test "info break" \
- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
+ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
--- gdb/testsuite/gdb.base/pending.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/pending.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -71,8 +71,8 @@ gdb_test_multiple "break pendfunc1" "set
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*" \
"single pending breakpoint info"
#
@@ -86,8 +86,8 @@ gdb_test "break main" \
"breakpoint function"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending plus real breakpoint info"
@@ -108,8 +108,8 @@ gdb_test_multiple "break pendfunc2" "Don
gdb_test "condition 1 k == 1" ""
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending plus condition"
@@ -121,8 +121,8 @@ gdb_test "info break" \
gdb_test "disable 1" ""
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
"pending disabled"
@@ -134,8 +134,8 @@ gdb_test "commands 1\nprint k\nend" "" \
"Set commands for pending breakpoint"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \
@@ -154,12 +154,12 @@ gdb_test_multiple "break pendshr.c:$bp2_
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \
"multiple pending breakpoints"
@@ -179,13 +179,13 @@ gdb_test {ignore $bpnum 2} "Will ignore
"set ignore count on pending breakpoint 3"
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.*
\[\t \]+stop only if k == 1.*
\[\t \]+print k.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \
"multiple pending breakpoints 2"
#
@@ -253,7 +253,7 @@ gdb_test_multiple "break imaginary" "set
rerun_to_main
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*imaginary.*" \
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*imaginary.*" \
"verify pending breakpoint after restart"
--- gdb/testsuite/gdb.base/break.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/break.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -179,7 +179,7 @@ set bp_location8 [gdb_get_line_number "s
set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1]
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).*
\[0-9\]+\[\t \]+breakpoint keep y.* in factorial$proto at .*$srcfile:$bp_location7.*
@@ -309,7 +309,7 @@ gdb_test "tbreak $srcfile:$bp_location1
#
# check to see what breakpoints are set (temporary this time)
#
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
--- gdb/testsuite/gdb.base/annota3.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/annota3.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -127,8 +127,8 @@ gdb_expect {
send_gdb "info break\n"
gdb_expect_list "breakpoint info" "$gdb_prompt$" {
"\r\n\032\032post-prompt\r\n"
- "Num Type Disp Enb Address +What\r\n"
- "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
+ "Num Type Disp Enb Address +What\r\n"
+ "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n"
}
--- gdb/testsuite/gdb.base/sepdebug.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/sepdebug.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -179,7 +179,7 @@ set bp_location8 [gdb_get_line_number "s
set bp_location9 [gdb_get_line_number "set breakpoint 9 here"]
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile:($bp_location8|$bp_location9).*
\[0-9\]+\[\t \]+breakpoint keep y.* in factorial at .*$srcfile:$bp_location7.*
@@ -298,7 +298,7 @@ gdb_test "tbreak $srcfile:$bp_location1
#
# check to see what breakpoints are set (temporary this time)
#
-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial at .*$srcfile:$bp_location7.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
--- gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/condbreak.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -125,14 +125,14 @@ if {$hp_aCC_compiler} {
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location6.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker1$marker1_proto at .*$srcfile1:($bp_location15|$bp_location16).*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
-\[\t \]+stop only if 1 == 1.*
+\[\t \]+stop only if \\(1==1\\).*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).*
-\[\t \]+stop only if a == 43.*" \
+\[\t \]+stop only if \\(a==43\\).*" \
"breakpoint info"
--- gdb/testsuite/gdb.base/unload.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/unload.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -81,8 +81,8 @@ gdb_test_multiple "break shrfunc1" "set
}
gdb_test "info break" \
- "Num Type\[ \]+Disp Enb Address\[ \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*shrfunc1.*" \
+ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
+\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*shrfunc1.*" \
"single pending breakpoint info"
set unloadshr_line [gdb_get_line_number "unloadshr break" ${libsrcfile}]
--- gdb/testsuite/gdb.base/annota1.exp (/work/mb_mainline/7_pending) (revision 4831)
+++ gdb/testsuite/gdb.base/annota1.exp (/work/mb_mainline/8_multiple_locations) (revision 4831)
@@ -117,9 +117,9 @@ gdb_expect {
#
send_gdb "info break\n"
gdb_expect {
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
{pass "breakpoint info"}
- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
+ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \
{ setup_xfail "*-*-*" 1270
fail "breakpoint info"}
-re ".*$gdb_prompt$" { fail "breakpoint info" }
Property changes on:
___________________________________________________________________
Name: svk:merge
d48a11ec-ee1c-0410-b3f5-c20844f99675:/work/mb_mainline/4_bpstat_owner:4823
d48a11ec-ee1c-0410-b3f5-c20844f99675:/work/mb_mainline/5_per_loc_cond:4824
d48a11ec-ee1c-0410-b3f5-c20844f99675:/work/mb_mainline/6_create_breakpoints_refactoring:4825
+d48a11ec-ee1c-0410-b3f5-c20844f99675:/work/mb_mainline/7_pending:4829
e7755896-6108-0410-9592-8049d3e74e28:/mirrors/gdb/trunk:182811
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-09-22 19:53 ` Vladimir Prus
@ 2007-09-23 4:13 ` Eli Zaretskii
0 siblings, 0 replies; 29+ messages in thread
From: Eli Zaretskii @ 2007-09-23 4:13 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> From: Vladimir Prus <vladimir@codesourcery.com>
> Date: Sat, 22 Sep 2007 23:52:28 +0400
> Cc: gdb-patches@sources.redhat.com
>
> I attach revised patch. Does it look OK?
Yes, thanks.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 19:38 ` Vladimir Prus
2007-11-14 20:42 ` Nick Roberts
2007-11-16 20:37 ` Nick Roberts
@ 2007-11-19 2:42 ` Nick Roberts
2 siblings, 0 replies; 29+ messages in thread
From: Nick Roberts @ 2007-11-19 2:42 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> Is there a way to package MI support separately, so that every existing Emacs
> user can try it?
There is now. Tom Tromey has kindly installed a package called gdb-mi in his
Emacs Lisp Package ArchiveEmacs Lisp Package Archive
(http://tromey.com/elpa/)
It comprises of modified gud.el and a file called gdb-mi.el which replaces
gdb-ui.el.
When installed, this overrides the current files and invoking M-x gdb will
use GDB/MI directly (starts with "gdb -i=mi"). When deleted ('d' followed
by 'x' in Package Menu mode) the files are deleted and old functionality
restored.
So this provides a convenient way to review the current status/contribute
to its improvement. For someone who just wants to use GDB, however, the
current mode in Emacs 22 is a much better option.
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 19:38 ` Vladimir Prus
2007-11-14 20:42 ` Nick Roberts
@ 2007-11-16 20:37 ` Nick Roberts
2007-11-19 2:42 ` Nick Roberts
2 siblings, 0 replies; 29+ messages in thread
From: Nick Roberts @ 2007-11-16 20:37 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> Is there a way to package MI support separately, so that every existing Emacs
> user can try it?
I was forgetting. There is gdb-mi.el, which is in the GDB CVS repository, in
the mi directory) that piggybacks on the files used in Emacs 22.1 (gud.el and
gdb-ui.el).
If you load this file, or put something like:
(autoload 'gdbmi "~/src/gdb/mi/gdb-mi" "MI version of M-x gdb." t)
(setq gud-gdbmi-command-name "~/src/build/gdb/gdb -interp=mi")
in your .emacs, then do:
M-x gdbmi
GDB starts up using MI:
Run gdbmi (like this): ~/src/build/gdb/gdb -interp=mi ~/myprog
I doubt that gdb-mi.el has been distributed with binary RPMs for GDB, so it
probably requires GDB in CVS. It's only really of relevant to someone
interested in developing the mode, and the only correspondence I've had about
it so far has been from someone wanting to write a frontend for D!
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 20:42 ` Nick Roberts
2007-11-14 21:17 ` Joel Brobecker
@ 2007-11-15 20:39 ` Vladimir Prus
1 sibling, 0 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-11-15 20:39 UTC (permalink / raw)
To: Nick Roberts, gdb-patches
Nick Roberts wrote:
> > Heh, you probably know what's going on here yourself. Even though MI
> > was advertised as the right interface for frontend for some years, it
> > does not have a maintainer, or a particular development plan, and
> > misses some bits. And probably the only way to change the situation is
> > to decide that MI is the future, and actively discourage use of CLI for
> > anything, to the degree of immediately refusing any request mentioning
> > CLI in relation to any frontend.
>
> I don't know why you insist on being so confrontational, or how the above
> lack of support for MI is solved in any way by refusing requests for CLI,
> but I find it quite unhelpful.
Let try to put it in more constructive way. In order to suggest MI
as the recommended interface for frontends with a straight face, it should
become better. While making CLI really deprecated for frontends sounds
drastic, it is very likely to accelerate transition to MI, which will increase
the number of comments about MI and hopefully the number of patches for MI.
Do you have any other approaches?
- Volodya
> > As for multiple breakpoints -- I would have being happy to provide MI
> > interface, and not provide CLI at all -- but I doubt that would have
> > being acceptable, and MI has fallen out. Again, a policy that new
> > advanced functionality is allowed to be available via MI only might
> > have helped.
>
> Presumably CLI is still needed by those who use GDB from the command line.
> Or are you proposing to `help' them by forcing them to use a frontend?
At the certain degree, CLI does not scale. Say, 5 breakpoint locations might be
OK. But how can we expect CLI to show 100 locations? It's gonna be unsuable
anyway.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 20:42 ` Nick Roberts
@ 2007-11-14 21:17 ` Joel Brobecker
2007-11-15 20:39 ` Vladimir Prus
1 sibling, 0 replies; 29+ messages in thread
From: Joel Brobecker @ 2007-11-14 21:17 UTC (permalink / raw)
To: Nick Roberts; +Cc: Vladimir Prus, gdb-patches
> There's no hurry. It could be added to the Wiki as a TODO item for
> GDB 6.8 Release.
>
> Joel,
>
> Can I do that just by creating an account? Shall I delete the GDB 6.7
> Release page too?
Yes, I think you should be able to create a new page if you have an
account there (you shouldn't need any other priviledge). But, please,
do not delete the GDB 6.7 release page, at least for now. I don't know
yet whether we'll need to make a GDB 6.7.2 release or not.
--
Joel
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 19:38 ` Vladimir Prus
@ 2007-11-14 20:42 ` Nick Roberts
2007-11-14 21:17 ` Joel Brobecker
2007-11-15 20:39 ` Vladimir Prus
2007-11-16 20:37 ` Nick Roberts
2007-11-19 2:42 ` Nick Roberts
2 siblings, 2 replies; 29+ messages in thread
From: Nick Roberts @ 2007-11-14 20:42 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
>...
> > OK, but it looks much a smaller/simpler patch than the one you've already
> > committed.
>
> Yes, but I have better luck getting huge patches approved, than for
> obvious patches, for whatever reasons.
>
> Basically, it boils down to:
> 1. Using <PENDING> like above seems a good idea to try.
> 2. There's a bit of time involved
> 3. I'm short of time, and probably won't spend it until all the
> patches I've sent already are reviewed ;-)
There's no hurry. It could be added to the Wiki as a TODO item for
GDB 6.8 Release.
Joel,
Can I do that just by creating an account? Shall I delete the GDB 6.7
Release page too?
> > Also MI is still evolving. It's interesting that you suggest all
> > frontends should use it as the changes you have just made for breakpoints
> > with multiple locations appear in the output of "info breakpoints" but not
> > in that of "-break-list". So I don't see how any front end could handle
> > this information through MI.
> Heh, you probably know what's going on here yourself. Even though MI was
> advertised as the right interface for frontend for some years, it does not
> have a maintainer, or a particular development plan, and misses some bits.
> And probably the only way to change the situation is to decide that MI is
> the future, and actively discourage use of CLI for anything, to the degree
> of immediately refusing any request mentioning CLI in relation to any
> frontend.
I don't know why you insist on being so confrontational, or how the above lack
of support for MI is solved in any way by refusing requests for CLI, but I find
it quite unhelpful.
> As for multiple breakpoints -- I would have being happy to provide MI
> interface, and not provide CLI at all -- but I doubt that would have being
> acceptable, and MI has fallen out. Again, a policy that new advanced
> functionality is allowed to be available via MI only might have helped.
Presumably CLI is still needed by those who use GDB from the command line.
Or are you proposing to `help' them by forcing them to use a frontend?
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 19:18 ` Nick Roberts
2007-11-14 19:37 ` Joel Brobecker
@ 2007-11-14 19:38 ` Vladimir Prus
2007-11-14 20:42 ` Nick Roberts
` (2 more replies)
1 sibling, 3 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-11-14 19:38 UTC (permalink / raw)
To: Nick Roberts; +Cc: gdb-patches
On Wednesday 14 November 2007 22:17:59 you wrote:
> >...
> > I think the right approach would be moving the check for loc->shlib_disabled
> > later, like this:
> >
> > if (b->loc == NULL)
> > ui_out_field_string (uiout, "addr", "<PENDING>");
> > else if (header_of_multiple)
> > ui_out_field_string (uiout, "addr", "<MULTIPLE>");
> > else if (loc->shlib_disabled)
> > ui_out_field_string (uiout, "addr", "<PENDING>");
> > else
> > ui_out_field_core_addr (uiout, "addr", loc->address);
> >
> > But there's also testsuite to be updated and getting somebody to
> > actually approve this patch.
>
> OK, but it looks much a smaller/simpler patch than the one you've already
> committed.
Yes, but I have better luck getting huge patches approved, than for
obvious patches, for whatever reasons.
Basically, it boils down to:
1. Using <PENDING> like above seems a good idea to try.
2. There's a bit of time involved
3. I'm short of time, and probably won't spend it until all the
patches I've sent already are reviewed ;-)
So, if you have the time now to adjust your current patch per my
comments, adjust testsuite and somebody's willing to approve
the patch -- go ahead.
> > > > But generally, trying to keeping CLI back compatible have to stop
> > > > at some time -- if we keep this "don't break CLI clients even if
> > > > CLI clients were deprecated from some time" attitude, it will result
> > > > in new features being available via MI only.
> > >
> > > Focussing on the issue at hand, we're just talking about making a minor
> > > adjustment to the format of "info breakpoints", for the case of pending
> > > breakpoints, to avoid breaking existing frontend(s).
> >
> > Not quite. We're trying to please frontend(s) using deprecated protocol.
> > However little time is spent on that, it's time not spent on other, better
> > things. Is there a reason Emacs website cannot say "Use MI support,
> > available at http://..."?
>
> The short answer is that, although I have a mode that works with MI, it is
> currently worse than the current one, which uses a mixture of MI and CLI
> commands. Even if it was as good, there would still be many people already
> using Emacs 22.1 who wouldn't be aware of the website, or willing/able to
> update Emacs from it.
Is there a way to package MI support separately, so that every existing Emacs
user can try it?
> Also MI is still evolving. It's interesting that you suggest all frontends
> should use it as the changes you have just made for breakpoints with
> multiple locations appear in the output of "info breakpoints" but not
> in that of "-break-list". So I don't see how any front end could handle
> this information through MI.
Heh, you probably know what's going on here yourself. Even though MI
was advertised as the right interface for frontend for some years, it does
not have a maintainer, or a particular development plan, and misses some bits.
And probably the only way to change the situation is to decide that MI is
the future, and actively discourage use of CLI for anything, to the degree
of immediately refusing any request mentioning CLI in relation to any frontend.
As for multiple breakpoints -- I would have being happy to provide MI
interface, and not provide CLI at all -- but I doubt that would have being
acceptable, and MI has fallen out. Again, a policy that new advanced
functionality is allowed to be available via MI only might have helped.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 19:18 ` Nick Roberts
@ 2007-11-14 19:37 ` Joel Brobecker
2007-11-14 19:38 ` Vladimir Prus
1 sibling, 0 replies; 29+ messages in thread
From: Joel Brobecker @ 2007-11-14 19:37 UTC (permalink / raw)
To: Nick Roberts; +Cc: Vladimir Prus, gdb-patches
> Unfortunately, the full transition to MI will be a slow one for Emacs.
And I suspect this will be the case for many front-ends, not just emacs.
I'm personnaly very grateful of the frontends that work on a full MI
approach, as this is the only way to determine what's missing in MI
as well as stabilizing the MI protocol. But I understand that it's
a challenge to make that transition.
Let's not fight over whether we should always accomodate front-ends
in CLI mode or not. Let's look instead of the issues on a case-by-case
basis. If we can support the front-end request with a reasonable amount
of effort, then let's do it.
--
Joel
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 19:58 ` Vladimir Prus
@ 2007-11-14 19:21 ` Jim Blandy
0 siblings, 0 replies; 29+ messages in thread
From: Jim Blandy @ 2007-11-14 19:21 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
Vladimir Prus <ghost at cs.msu.su> writes:
> Daniel Jacobowitz wrote:
>
>> On Tue, Nov 13, 2007 at 11:05:10AM +0300, Vladimir Prus wrote:
>>> >
>>> > Does the (p) add anything useful to the user? The manual says:
>>> >
>>> > An optional `(p)' suffix marks pending breakpoints
>>> >
>>> > Is that not clear from the word PENDING?
>>>
>>> No, because if you set breakpoint in a shared library, and that library
>>> is unloaded, you have some number in 'address' field, but the breakpoint
>>> won't actually fire, and the "(p)" indicates that fact.
>>
>> Can we just change it back to <PENDING> by discarding the address?
>
> This can actually work. I'll try to implement this idea.
Yeah, that's what I was going to suggest, too --- the number is
basically a dangling pointer once the library's been unloaded.
I agree with Vladimir that the priority of the CLI should be providing
a good command-line experience --- not stability for code trying to
parse the output. MI has been in GDB in some form or another since
2001.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 11:58 ` Vladimir Prus
@ 2007-11-14 19:18 ` Nick Roberts
2007-11-14 19:37 ` Joel Brobecker
2007-11-14 19:38 ` Vladimir Prus
0 siblings, 2 replies; 29+ messages in thread
From: Nick Roberts @ 2007-11-14 19:18 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
>...
> I think the right approach would be moving the check for loc->shlib_disabled
> later, like this:
>
> if (b->loc == NULL)
> ui_out_field_string (uiout, "addr", "<PENDING>");
> else if (header_of_multiple)
> ui_out_field_string (uiout, "addr", "<MULTIPLE>");
> else if (loc->shlib_disabled)
> ui_out_field_string (uiout, "addr", "<PENDING>");
> else
> ui_out_field_core_addr (uiout, "addr", loc->address);
>
> But there's also testsuite to be updated and getting somebody to
> actually approve this patch.
OK, but it looks much a smaller/simpler patch than the one you've already
committed.
> > > But generally, trying to keeping CLI back compatible have to stop
> > > at some time -- if we keep this "don't break CLI clients even if
> > > CLI clients were deprecated from some time" attitude, it will result
> > > in new features being available via MI only.
> >
> > Focussing on the issue at hand, we're just talking about making a minor
> > adjustment to the format of "info breakpoints", for the case of pending
> > breakpoints, to avoid breaking existing frontend(s).
>
> Not quite. We're trying to please frontend(s) using deprecated protocol.
> However little time is spent on that, it's time not spent on other, better
> things. Is there a reason Emacs website cannot say "Use MI support,
> available at http://..."?
The short answer is that, although I have a mode that works with MI, it is
currently worse than the current one, which uses a mixture of MI and CLI
commands. Even if it was as good, there would still be many people already
using Emacs 22.1 who wouldn't be aware of the website, or willing/able to
update Emacs from it.
Also MI is still evolving. It's interesting that you suggest all frontends
should use it as the changes you have just made for breakpoints with
multiple locations appear in the output of "info breakpoints" but not
in that of "-break-list". So I don't see how any front end could handle
this information through MI.
Unfortunately, the full transition to MI will be a slow one for Emacs.
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 6:29 ` Vladimir Prus
2007-11-14 7:06 ` Nick Roberts
@ 2007-11-14 18:56 ` Eli Zaretskii
1 sibling, 0 replies; 29+ messages in thread
From: Eli Zaretskii @ 2007-11-14 18:56 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> From: Vladimir Prus <ghost@cs.msu.su>
> Date: Wed, 14 Nov 2007 09:29:31 +0300
>
> But generally, trying to keeping CLI back compatible have to stop
> at some time
IMO, it can stop some time after an official Emacs is released that
uses the MI interface exclusively, but no earlier.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 7:06 ` Nick Roberts
@ 2007-11-14 11:58 ` Vladimir Prus
2007-11-14 19:18 ` Nick Roberts
0 siblings, 1 reply; 29+ messages in thread
From: Vladimir Prus @ 2007-11-14 11:58 UTC (permalink / raw)
To: Nick Roberts; +Cc: gdb-patches
On Wednesday 14 November 2007 10:06:02 you wrote:
> > As I say in another email, I might be able to implement using <PENDING>
> > as address in all cases.
>
> I don't pretend to understand the code but the patch below seems to work
> for me (probably not all cases).
I believe that in a case of breakpoint with multiple locations, where
the first location is shlib_disabled, the updated code will print <PENDING>
as address, not <MULTIPLE>.
I think the right approach would be moving the check for loc->shlib_disabled later, like this:
if (b->loc == NULL)
ui_out_field_string (uiout, "addr", "<PENDING>");
else if (header_of_multiple)
ui_out_field_string (uiout, "addr", "<MULTIPLE>");
else if (loc->shlib_disabled)
ui_out_field_string (uiout, "addr", "<PENDING>");
else
ui_out_field_core_addr (uiout, "addr", loc->address);
But there's also testsuite to be updated and getting somebody to
actually approve this patch.
> > But generally, trying to keeping CLI back compatible have to stop
> > at some time -- if we keep this "don't break CLI clients even if
> > CLI clients were deprecated from some time" attitude, it will result
> > in new features being available via MI only.
>
> Focussing on the issue at hand, we're just talking about making a minor
> adjustment to the format of "info breakpoints", for the case of pending
> breakpoints, to avoid breaking existing frontend(s).
Not quite. We're trying to please frontend(s) using deprecated protocol.
However little time is spent on that, it's time not spent on other, better things.
Is there a reason Emacs website cannot say "Use MI support, available at http://..."?
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-14 6:29 ` Vladimir Prus
@ 2007-11-14 7:06 ` Nick Roberts
2007-11-14 11:58 ` Vladimir Prus
2007-11-14 18:56 ` Eli Zaretskii
1 sibling, 1 reply; 29+ messages in thread
From: Nick Roberts @ 2007-11-14 7:06 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> As I say in another email, I might be able to implement using <PENDING>
> as address in all cases.
I don't pretend to understand the code but the patch below seems to work
for me (probably not all cases).
> But generally, trying to keeping CLI back compatible have to stop
> at some time -- if we keep this "don't break CLI clients even if
> CLI clients were deprecated from some time" attitude, it will result
> in new features being available via MI only.
Focussing on the issue at hand, we're just talking about making a minor
adjustment to the format of "info breakpoints", for the case of pending
breakpoints, to avoid breaking existing frontend(s). AFAIK no-one is talking
about making this or anything else a MI only feature.
--
Nick http://www.inet.net.nz/~nickrob
2007-11-14 Nick Roberts <nickrob@snap.net.nz>
* breakpoint.c (print_one_breakpoint_location): Revert Enb field
to old format. Discard breakpoint address if shared library is
unloaded.
*** breakpoint.c.~1.278.~ 2007-11-09 17:16:10.000000000 +1300
--- breakpoint.c 2007-11-14 19:52:35.000000000 +1300
*************** print_one_breakpoint_location (struct br
*** 3555,3564 ****
/* 4 */
annotate_field (3);
if (part_of_multiple)
! ui_out_field_string (uiout, "enabled",
! loc->shlib_disabled
! ? (loc->enabled ? "y(p)" : "n(p)")
! : (loc->enabled ? "y" : "n"));
else
{
int pending = (b->loc == NULL || b->loc->shlib_disabled);
--- 3555,3561 ----
/* 4 */
annotate_field (3);
if (part_of_multiple)
! ui_out_field_string (uiout, "enabled", loc->enabled ? "y" : "n");
else
{
int pending = (b->loc == NULL || b->loc->shlib_disabled);
*************** print_one_breakpoint_location (struct br
*** 3566,3576 ****
state -- it will be apparent from the locations. */
if (header_of_multiple)
pending = 0;
! ui_out_field_fmt (uiout, "enabled", "%c%s",
! bpenables[(int) b->enable_state],
! pending ? "(p)" : "");
! if (!pending)
! ui_out_spaces (uiout, 3);
}
--- 3563,3570 ----
state -- it will be apparent from the locations. */
if (header_of_multiple)
pending = 0;
! ui_out_field_fmt (uiout, "enabled", "%c",
! bpenables[(int) b->enable_state]);
}
*************** print_one_breakpoint_location (struct br
*** 3704,3710 ****
if (addressprint)
{
annotate_field (4);
! if (b->loc == NULL)
ui_out_field_string (uiout, "addr", "<PENDING>");
else if (header_of_multiple)
ui_out_field_string (uiout, "addr", "<MULTIPLE>");
--- 3698,3704 ----
if (addressprint)
{
annotate_field (4);
! if (b->loc == NULL || loc->shlib_disabled)
ui_out_field_string (uiout, "addr", "<PENDING>");
else if (header_of_multiple)
ui_out_field_string (uiout, "addr", "<MULTIPLE>");
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 22:47 ` Joel Brobecker
@ 2007-11-14 6:29 ` Vladimir Prus
2007-11-14 7:06 ` Nick Roberts
2007-11-14 18:56 ` Eli Zaretskii
0 siblings, 2 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-11-14 6:29 UTC (permalink / raw)
To: gdb-patches
Joel Brobecker wrote:
>> Nevertheless, it's well known that Emacs does that since time
>> immemoriam, so we should avoid breaking at least Emacs, IMO.
>
> I agree that we should avoid breaking existing tools as much as we can.
> This request in particular seems reasonable, we just have to find the
> right syntax (Daniel's suggestion looks good to me).
As I say in another email, I might be able to implement using <PENDING>
as address in all cases.
But generally, trying to keeping CLI back compatible have to stop
at some time -- if we keep this "don't break CLI clients even if
CLI clients were deprecated from some time" attitude, it will result
in new features being available via MI only.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 22:20 ` Eli Zaretskii
@ 2007-11-13 22:47 ` Joel Brobecker
2007-11-14 6:29 ` Vladimir Prus
0 siblings, 1 reply; 29+ messages in thread
From: Joel Brobecker @ 2007-11-13 22:47 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Vladimir Prus, nickrob, gdb-patches
> Nevertheless, it's well known that Emacs does that since time
> immemoriam, so we should avoid breaking at least Emacs, IMO.
I agree that we should avoid breaking existing tools as much as we can.
This request in particular seems reasonable, we just have to find the
right syntax (Daniel's suggestion looks good to me).
--
Joel
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 8:05 ` Vladimir Prus
2007-11-13 8:31 ` Nick Roberts
2007-11-13 12:38 ` Daniel Jacobowitz
@ 2007-11-13 22:20 ` Eli Zaretskii
2007-11-13 22:47 ` Joel Brobecker
2 siblings, 1 reply; 29+ messages in thread
From: Eli Zaretskii @ 2007-11-13 22:20 UTC (permalink / raw)
To: Vladimir Prus; +Cc: nickrob, gdb-patches
> From: Vladimir Prus <vladimir@codesourcery.com>
> Date: Tue, 13 Nov 2007 11:05:10 +0300
> Cc: gdb-patches@sources.redhat.com
>
> The CLI output was never documented as stable, and using it in frontend
> is prone to such breakage.
Nevertheless, it's well known that Emacs does that since time
immemoriam, so we should avoid breaking at least Emacs, IMO.
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 12:38 ` Daniel Jacobowitz
@ 2007-11-13 19:58 ` Vladimir Prus
2007-11-14 19:21 ` Jim Blandy
0 siblings, 1 reply; 29+ messages in thread
From: Vladimir Prus @ 2007-11-13 19:58 UTC (permalink / raw)
To: gdb-patches
Daniel Jacobowitz wrote:
> On Tue, Nov 13, 2007 at 11:05:10AM +0300, Vladimir Prus wrote:
>> >
>> > Does the (p) add anything useful to the user? The manual says:
>> >
>> > An optional `(p)' suffix marks pending breakpoints
>> >
>> > Is that not clear from the word PENDING?
>>
>> No, because if you set breakpoint in a shared library, and that library
>> is unloaded, you have some number in 'address' field, but the breakpoint
>> won't actually fire, and the "(p)" indicates that fact.
>
> Can we just change it back to <PENDING> by discarding the address?
This can actually work. I'll try to implement this idea.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 8:05 ` Vladimir Prus
2007-11-13 8:31 ` Nick Roberts
@ 2007-11-13 12:38 ` Daniel Jacobowitz
2007-11-13 19:58 ` Vladimir Prus
2007-11-13 22:20 ` Eli Zaretskii
2 siblings, 1 reply; 29+ messages in thread
From: Daniel Jacobowitz @ 2007-11-13 12:38 UTC (permalink / raw)
To: Vladimir Prus; +Cc: Nick Roberts, gdb-patches
On Tue, Nov 13, 2007 at 11:05:10AM +0300, Vladimir Prus wrote:
> >
> > Does the (p) add anything useful to the user? The manual says:
> >
> > An optional `(p)' suffix marks pending breakpoints
> >
> > Is that not clear from the word PENDING?
>
> No, because if you set breakpoint in a shared library, and that library
> is unloaded, you have some number in 'address' field, but the breakpoint won't
> actually fire, and the "(p)" indicates that fact.
Can we just change it back to <PENDING> by discarding the address?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 8:31 ` Nick Roberts
@ 2007-11-13 8:45 ` Vladimir Prus
0 siblings, 0 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-11-13 8:45 UTC (permalink / raw)
To: Nick Roberts; +Cc: gdb-patches
On Tuesday 13 November 2007 11:31:36 Nick Roberts wrote:
> > No, because if you set breakpoint in a shared library, and that library is
> > unloaded, you have some number in 'address' field, but the breakpoint won't
> > actually fire, and the "(p)" indicates that fact.
>
> OK, but the column you've added this to is "Enb" which refers to whether
> the breakpoint is enabled or not. That is really a yes/no question and
> not related to whether the breakpoint is pending.
This is closely tied. "y" and "n" represents user's intended enable state
of the breakpoint. However, sometimes GDB's internal state does not
match user's request, in which case gdb adds "(p)" to say "sorry, you've
enabled this breakpoint but I can't honour your request at this time".
> > > If it's not needed can we please revert it to the old format? If it is
> > > needed can we find a format that doesn't break existing parsing?
> >
> > I personally don't think we should cater for clients that try to use CLI
> > despite that being known as bad idea.
>
> I think we should generally try to cater for _all_ users of GDB and not
> impose requirements on their use of GDB.
>
> > That said -- do you have any
> > suggestions for an alternative format?
>
> Yes I do. Instead of:
>
> (gdb) inf bre
> Num Type Disp Enb Address What
> 1 breakpoint keep y(p) 0xb7f4ce40
>
> for an unloaded breakpoint, how about:
>
> (gdb) inf bre
> Num Type Disp Enb Address What
> 1 pending breakpoint keep y 0xb7f4ce40
>
> which seems the right place to put it, and Emacs will parse this properly
> because that's where other breakpoint variants are described, e.g.,
>
>
> 3 hw breakpoint keep y 0x080485bc in main at myprog.c:75
I think this is wrong, because "pending" state is generally speaking
orthogonal to any breakpoint type -- in particular, "hw breakpoint" can
be pending just as well. Pending is not the natural type of breakpoint -- it's
just the state of breakpoint at the current time. Furthermore,
in current GDB, breakpoint type never changes, and changing breakpoint types
dynamically is rather strange.
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 8:05 ` Vladimir Prus
@ 2007-11-13 8:31 ` Nick Roberts
2007-11-13 8:45 ` Vladimir Prus
2007-11-13 12:38 ` Daniel Jacobowitz
2007-11-13 22:20 ` Eli Zaretskii
2 siblings, 1 reply; 29+ messages in thread
From: Nick Roberts @ 2007-11-13 8:31 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> > This can break a front end which parses the old output, and this is indeed
> > the case for Emacs 22.1, which has already been released.
>
> The CLI output was never documented as stable, and using it in frontend
> is prone to such breakage.
It still presumably makes sense to avoid such breakage where possible.
> > Does the (p) add anything useful to the user? The manual says:
> >
> > An optional `(p)' suffix marks pending breakpoints
> >
> > Is that not clear from the word PENDING?
>
> No, because if you set breakpoint in a shared library, and that library is
> unloaded, you have some number in 'address' field, but the breakpoint won't
> actually fire, and the "(p)" indicates that fact.
OK, but the column you've added this to is "Enb" which refers to whether
the breakpoint is enabled or not. That is really a yes/no question and
not related to whether the breakpoint is pending.
> > If it's not needed can we please revert it to the old format? If it is
> > needed can we find a format that doesn't break existing parsing?
>
> I personally don't think we should cater for clients that try to use CLI
> despite that being known as bad idea.
I think we should generally try to cater for _all_ users of GDB and not
impose requirements on their use of GDB.
> That said -- do you have any
> suggestions for an alternative format?
Yes I do. Instead of:
(gdb) inf bre
Num Type Disp Enb Address What
1 breakpoint keep y(p) 0xb7f4ce40
for an unloaded breakpoint, how about:
(gdb) inf bre
Num Type Disp Enb Address What
1 pending breakpoint keep y 0xb7f4ce40
which seems the right place to put it, and Emacs will parse this properly
because that's where other breakpoint variants are described, e.g.,
3 hw breakpoint keep y 0x080485bc in main at myprog.c:75
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
2007-11-13 7:15 Nick Roberts
@ 2007-11-13 8:05 ` Vladimir Prus
2007-11-13 8:31 ` Nick Roberts
` (2 more replies)
0 siblings, 3 replies; 29+ messages in thread
From: Vladimir Prus @ 2007-11-13 8:05 UTC (permalink / raw)
To: Nick Roberts; +Cc: gdb-patches
On Tuesday 13 November 2007 10:15:16 Nick Roberts wrote:
>
> Formerly, pending breakpoints were reported as:
>
> (gdb) inf bre
> Num Type Disp Enb Address What
> 1 breakpoint keep y <PENDING> cos
>
>
> now they're reported as:
>
>
> (gdb) inf bre
> Num Type Disp Enb Address What
> 1 breakpoint keep y(p) <PENDING> cos
>
>
> This can break a front end which parses the old output, and this is indeed
> the case for Emacs 22.1, which has already been released.
The CLI output was never documented as stable, and using it in frontend
is prone to such breakage.
>
> Does the (p) add anything useful to the user? The manual says:
>
> An optional `(p)' suffix marks pending breakpoints
>
> Is that not clear from the word PENDING?
No, because if you set breakpoint in a shared library, and that library
is unloaded, you have some number in 'address' field, but the breakpoint won't
actually fire, and the "(p)" indicates that fact.
> If it's not needed can we please revert it to the old format? If it is needed
> can we find a format that doesn't break existing parsing?
I personally don't think we should cater for clients that try to use CLI
despite that being known as bad idea. That said -- do you have any suggestions
for an alternative format?
- Volodya
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [8/9] multiple locations
@ 2007-11-13 7:15 Nick Roberts
2007-11-13 8:05 ` Vladimir Prus
0 siblings, 1 reply; 29+ messages in thread
From: Nick Roberts @ 2007-11-13 7:15 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
Formerly, pending breakpoints were reported as:
(gdb) inf bre
Num Type Disp Enb Address What
1 breakpoint keep y <PENDING> cos
now they're reported as:
(gdb) inf bre
Num Type Disp Enb Address What
1 breakpoint keep y(p) <PENDING> cos
This can break a front end which parses the old output, and this is indeed
the case for Emacs 22.1, which has already been released.
Does the (p) add anything useful to the user? The manual says:
An optional `(p)' suffix marks pending breakpoints
Is that not clear from the word PENDING?
If it's not needed can we please revert it to the old format? If it is needed
can we find a format that doesn't break existing parsing?
--
Nick http://www.inet.net.nz/~nickrob
breakpoint.c:
> > - ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]);
> > - ui_out_spaces (uiout, 2);
> > + if (part_of_multiple)
> > + ui_out_field_string (uiout, "enabled",
> > + loc->shlib_disabled
> > + ? (loc->enabled ? "y(p)" : "n(p)")
> > + : (loc->enabled ? "y" : "n"));
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2007-11-19 2:42 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-09-07 22:49 [8/9] multiple locations Vladimir Prus
2007-09-07 22:51 ` Vladimir Prus
2007-09-08 11:46 ` Eli Zaretskii
2007-09-08 11:55 ` Vladimir Prus
2007-09-08 12:28 ` Eli Zaretskii
2007-09-22 19:53 ` Vladimir Prus
2007-09-23 4:13 ` Eli Zaretskii
2007-09-08 13:17 ` Mark Kettenis
2007-11-13 7:15 Nick Roberts
2007-11-13 8:05 ` Vladimir Prus
2007-11-13 8:31 ` Nick Roberts
2007-11-13 8:45 ` Vladimir Prus
2007-11-13 12:38 ` Daniel Jacobowitz
2007-11-13 19:58 ` Vladimir Prus
2007-11-14 19:21 ` Jim Blandy
2007-11-13 22:20 ` Eli Zaretskii
2007-11-13 22:47 ` Joel Brobecker
2007-11-14 6:29 ` Vladimir Prus
2007-11-14 7:06 ` Nick Roberts
2007-11-14 11:58 ` Vladimir Prus
2007-11-14 19:18 ` Nick Roberts
2007-11-14 19:37 ` Joel Brobecker
2007-11-14 19:38 ` Vladimir Prus
2007-11-14 20:42 ` Nick Roberts
2007-11-14 21:17 ` Joel Brobecker
2007-11-15 20:39 ` Vladimir Prus
2007-11-16 20:37 ` Nick Roberts
2007-11-19 2:42 ` Nick Roberts
2007-11-14 18:56 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox