gdb/gdb-6.7.1-upstream.patch

5153 lines
166 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Fix:
FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dsub
FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dmul
FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly ddiv
FAIL: gdb.arch/powerpc-power6.exp: Power6 disassembly dcmpu
2007-10-15 Peter Bergner <bergner@vnet.ibm.com>
* ppc-opc.c (powerpc_opcodes): Fix the first two operands of
dquaiq. to use the TE and FRT macros.
--- ./opcodes/ppc-opc.c 16 Oct 2007 02:26:30 -0000 1.100
+++ ./opcodes/ppc-opc.c 16 Oct 2007 02:55:30 -0000 1.101
@@ -4680,7 +4680,7 @@ const struct powerpc_opcode powerpc_opco
{ "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } },
{ "dquaiq", ZRC(63,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } },
-{ "dquaiq.", ZRC(63,67,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } },
+{ "dquaiq.", ZRC(63,67,1), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } },
{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } },
{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } },
2007-10-15 Peter Bergner <bergner@vnet.ibm.com>
* ppc-opc.c (TE): Correct signedness.
(powerpc_opcodes): Sort psq_st and psq_stu according to major
opcode number.
--- ./opcodes/ppc-opc.c 24 Aug 2007 00:56:30 -0000 1.99
+++ ./opcodes/ppc-opc.c 16 Oct 2007 02:26:30 -0000 1.100
@@ -492,13 +492,13 @@ const struct powerpc_operand powerpc_ope
#define VS VD
{ 0x1f, 21, NULL, NULL, PPC_OPERAND_VR },
- /* The SIMM field in a VX form instruction. */
+ /* The SIMM field in a VX form instruction, and TE in Z form. */
#define SIMM VD + 1
+#define TE SIMM
{ 0x1f, 16, NULL, NULL, PPC_OPERAND_SIGNED},
- /* The UIMM field in a VX form instruction, and TE in Z form. */
+ /* The UIMM field in a VX form instruction. */
#define UIMM SIMM + 1
-#define TE UIMM
{ 0x1f, 16, NULL, NULL, 0 },
/* The SHB field in a VA form instruction. */
@@ -4495,9 +4495,6 @@ const struct powerpc_opcode powerpc_opco
{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } },
-{ "psq_st", OP(60), OP_MASK, PPCPS, { FRS, PSD, RA, PSW, PSQ } },
-{ "psq_stu", OP(61), OP_MASK, PPCPS, { FRS, PSD, RA, PSW, PSQ } },
-
{ "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } },
{ "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } },
@@ -4561,6 +4558,9 @@ const struct powerpc_opcode powerpc_opco
{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } },
+{ "psq_st", OP(60), OP_MASK, PPCPS, { FRS, PSD, RA, PSW, PSQ } },
+{ "psq_stu", OP(61), OP_MASK, PPCPS, { FRS, PSD, RA, PSW, PSQ } },
+
{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } },
{ "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } },
2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
Associate bp_stat with bp_location, not breakpoint.
* breakpoint.h (breakpoint_at): Change type
to bp_location*.
* breakpoint.c (bpstat_alloc): Take bp_location,
not breakpoint.
(bpstat_find_breakpoint): Look at bpstat's location's
owner, not at bpstat->breakpoint_at.
(bpstat_find_step_resume_breakpoint): Likewise.
(bpstat_num): Likewise.
(print_it_typical): Likewise.
(print_bp_stop_message): Likewise.
(watchpoint_check): Likewise.
(bpstat_what): Likewise.
(bpstat_get_triggered_catchpoints): Likewise.
(breakpoint_auto_delete): Likewise.
(delete_breakpoint): Likewise.
(bpstat_stop_status): Pass location, not breakpoint,
to bpstat_alloc. Look at bpstat's location's
owner, not at bpstat->breakpoint_at.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.263
retrieving revision 1.264
diff -u -r1.263 -r1.264
--- src/gdb/breakpoint.c 2007/08/29 22:07:47 1.263
+++ src/gdb/breakpoint.c 2007/09/22 17:49:40 1.264
@@ -109,7 +109,7 @@
static void breakpoint_1 (int, int);
-static bpstat bpstat_alloc (struct breakpoint *, bpstat);
+static bpstat bpstat_alloc (struct bp_location *, bpstat);
static int breakpoint_cond_eval (void *);
@@ -1968,7 +1968,7 @@
for (; bsp != NULL; bsp = bsp->next)
{
- if (bsp->breakpoint_at == breakpoint)
+ if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint)
return bsp;
}
return NULL;
@@ -1994,10 +1994,10 @@
for (; bsp != NULL; bsp = bsp->next)
{
if ((bsp->breakpoint_at != NULL) &&
- (bsp->breakpoint_at->type == bp_step_resume) &&
- (bsp->breakpoint_at->thread == current_thread ||
- bsp->breakpoint_at->thread == -1))
- return bsp->breakpoint_at;
+ (bsp->breakpoint_at->owner->type == bp_step_resume) &&
+ (bsp->breakpoint_at->owner->thread == current_thread ||
+ bsp->breakpoint_at->owner->thread == -1))
+ return bsp->breakpoint_at->owner;
}
internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found."));
@@ -2021,7 +2021,11 @@
if ((*bsp) == NULL)
return 0; /* No more breakpoint values */
- b = (*bsp)->breakpoint_at;
+ /* We assume we'll never have several bpstats that
+ correspond to a single breakpoint -- otherwise,
+ this function might return the same number more
+ than once and this will look ugly. */
+ b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL;
*bsp = (*bsp)->next;
if (b == NULL)
return -1; /* breakpoint that's been deleted since */
@@ -2152,6 +2156,7 @@
print_it_typical (bpstat bs)
{
struct cleanup *old_chain, *ui_out_chain;
+ struct breakpoint *b;
struct ui_stream *stb;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -2159,21 +2164,22 @@
which has since been deleted. */
if (bs->breakpoint_at == NULL)
return PRINT_UNKNOWN;
+ b = bs->breakpoint_at->owner;
- switch (bs->breakpoint_at->type)
+ switch (b->type)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
- if (bs->breakpoint_at->loc->address != bs->breakpoint_at->loc->requested_address)
- breakpoint_adjustment_warning (bs->breakpoint_at->loc->requested_address,
- bs->breakpoint_at->loc->address,
- bs->breakpoint_at->number, 1);
- annotate_breakpoint (bs->breakpoint_at->number);
+ if (b->loc->address != b->loc->requested_address)
+ breakpoint_adjustment_warning (b->loc->requested_address,
+ b->loc->address,
+ b->number, 1);
+ annotate_breakpoint (b->number);
ui_out_text (uiout, "\nBreakpoint ");
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "reason",
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number);
+ ui_out_field_int (uiout, "bkptno", b->number);
ui_out_text (uiout, ", ");
return PRINT_SRC_AND_LOC;
break;
@@ -2200,42 +2206,42 @@
break;
case bp_catch_load:
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (loaded %s), "),
- bs->breakpoint_at->number,
- bs->breakpoint_at->triggered_dll_pathname);
+ b->number,
+ b->triggered_dll_pathname);
return PRINT_SRC_AND_LOC;
break;
case bp_catch_unload:
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (unloaded %s), "),
- bs->breakpoint_at->number,
- bs->breakpoint_at->triggered_dll_pathname);
+ b->number,
+ b->triggered_dll_pathname);
return PRINT_SRC_AND_LOC;
break;
case bp_catch_fork:
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (forked process %d), "),
- bs->breakpoint_at->number,
- bs->breakpoint_at->forked_inferior_pid);
+ b->number,
+ b->forked_inferior_pid);
return PRINT_SRC_AND_LOC;
break;
case bp_catch_vfork:
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
- bs->breakpoint_at->number,
- bs->breakpoint_at->forked_inferior_pid);
+ b->number,
+ b->forked_inferior_pid);
return PRINT_SRC_AND_LOC;
break;
case bp_catch_exec:
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (exec'd %s), "),
- bs->breakpoint_at->number,
- bs->breakpoint_at->exec_pathname);
+ b->number,
+ b->exec_pathname);
return PRINT_SRC_AND_LOC;
break;
@@ -2243,9 +2249,9 @@
if (current_exception_event &&
(CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH))
{
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (exception caught), "),
- bs->breakpoint_at->number);
+ b->number);
if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
printf_filtered (_("throw location %s:%d, "),
CURRENT_EXCEPTION_THROW_FILE,
@@ -2274,9 +2280,9 @@
if (current_exception_event &&
(CURRENT_EXCEPTION_KIND == EX_EVENT_THROW))
{
- annotate_catchpoint (bs->breakpoint_at->number);
+ annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (exception thrown), "),
- bs->breakpoint_at->number);
+ b->number);
if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE)
printf_filtered (_("throw location %s:%d, "),
CURRENT_EXCEPTION_THROW_FILE,
@@ -2305,18 +2311,18 @@
case bp_hardware_watchpoint:
if (bs->old_val != NULL)
{
- annotate_watchpoint (bs->breakpoint_at->number);
+ annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
- mention (bs->breakpoint_at);
+ mention (b);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
ui_out_field_stream (uiout, "old", stb);
ui_out_text (uiout, "\nNew value = ");
- value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+ value_print (b->val, stb->stream, 0, Val_pretty_default);
ui_out_field_stream (uiout, "new", stb);
do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
@@ -2332,10 +2338,10 @@
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
- mention (bs->breakpoint_at);
+ mention (b);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
- value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default);
+ value_print (b->val, stb->stream, 0, Val_pretty_default);
ui_out_field_stream (uiout, "value", stb);
do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
@@ -2345,12 +2351,12 @@
case bp_access_watchpoint:
if (bs->old_val != NULL)
{
- annotate_watchpoint (bs->breakpoint_at->number);
+ annotate_watchpoint (b->number);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
- mention (bs->breakpoint_at);
+ mention (b);
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nOld value = ");
value_print (bs->old_val, stb->stream, 0, Val_pretty_default);
@@ -2361,7 +2367,7 @@
}
else
{
- mention (bs->breakpoint_at);
+ mention (b);
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
@@ -2369,7 +2375,7 @@
ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value");
ui_out_text (uiout, "\nValue = ");
}
- value_print (bs->breakpoint_at->val, stb->stream, 0,Val_pretty_default);
+ value_print (b->val, stb->stream, 0,Val_pretty_default);
ui_out_field_stream (uiout, "new", stb);
do_cleanups (ui_out_chain);
ui_out_text (uiout, "\n");
@@ -2429,14 +2435,19 @@
break;
case print_it_normal:
- /* Normal case. Call the breakpoint's print_it method, or
- print_it_typical. */
- if (bs->breakpoint_at != NULL && bs->breakpoint_at->ops != NULL
- && bs->breakpoint_at->ops->print_it != NULL)
- return bs->breakpoint_at->ops->print_it (bs->breakpoint_at);
- else
- return print_it_typical (bs);
- break;
+ {
+ struct bp_location *bl = bs->breakpoint_at;
+ struct breakpoint *b = bl ? bl->owner : NULL;
+
+ /* Normal case. Call the breakpoint's print_it method, or
+ print_it_typical. */
+ /* FIXME: how breakpoint can ever be NULL here? */
+ if (b != NULL && b->ops != NULL && b->ops->print_it != NULL)
+ return b->ops->print_it (b);
+ else
+ return print_it_typical (bs);
+ }
+ break;
default:
internal_error (__FILE__, __LINE__,
@@ -2505,13 +2516,13 @@
/* Allocate a new bpstat and chain it to the current one. */
static bpstat
-bpstat_alloc (struct breakpoint *b, bpstat cbs /* Current "bs" value */ )
+bpstat_alloc (struct bp_location *bl, bpstat cbs /* Current "bs" value */ )
{
bpstat bs;
bs = (bpstat) xmalloc (sizeof (*bs));
cbs->next = bs;
- bs->breakpoint_at = b;
+ bs->breakpoint_at = bl;
/* If the condition is false, etc., don't do the commands. */
bs->commands = NULL;
bs->old_val = NULL;
@@ -2541,7 +2552,7 @@
struct frame_info *fr;
int within_current_scope;
- b = bs->breakpoint_at;
+ b = bs->breakpoint_at->owner;
if (b->exp_valid_block == NULL)
within_current_scope = 1;
@@ -2588,7 +2599,7 @@
we might be in the middle of evaluating a function call. */
struct value *mark = value_mark ();
- struct value *new_val = evaluate_expression (bs->breakpoint_at->exp);
+ struct value *new_val = evaluate_expression (b->exp);
if (!value_equal (b->val, new_val))
{
release_value (new_val);
@@ -2624,7 +2635,7 @@
ui_out_field_string
(uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
ui_out_text (uiout, "\nWatchpoint ");
- ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number);
+ ui_out_field_int (uiout, "wpnum", b->number);
ui_out_text (uiout, " deleted because the program has left the block in\n\
which its expression is valid.\n");
@@ -2760,7 +2771,7 @@
/* Come here if it's a watchpoint, or if the break address matches */
- bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */
+ bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */
/* Watchpoints may change this, if not found to have triggered. */
bs->stop = 1;
@@ -2971,9 +2982,9 @@
/* 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->type == bp_hardware_watchpoint ||
- bs->breakpoint_at->type == bp_read_watchpoint ||
- bs->breakpoint_at->type == bp_access_watchpoint))
+ (bs->breakpoint_at->owner->type == bp_hardware_watchpoint ||
+ bs->breakpoint_at->owner->type == bp_read_watchpoint ||
+ bs->breakpoint_at->owner->type == bp_access_watchpoint))
{
remove_breakpoints ();
insert_breakpoints ();
@@ -3134,7 +3145,7 @@
/* I suspect this can happen if it was a momentary breakpoint
which has since been deleted. */
continue;
- switch (bs->breakpoint_at->type)
+ switch (bs->breakpoint_at->owner->type)
{
case bp_none:
continue;
@@ -3289,7 +3300,7 @@
for (; ep_list != NULL; ep_list = ep_list->next)
{
/* Is this eventpoint a catchpoint? If not, ignore it. */
- ep = ep_list->breakpoint_at;
+ ep = ep_list->breakpoint_at->owner;
if (ep == NULL)
break;
if ((ep->type != bp_catch_load) &&
@@ -3300,7 +3311,7 @@
continue;
/* Yes; add it to the list. */
- bs = bpstat_alloc (ep, bs);
+ bs = bpstat_alloc (ep_list->breakpoint_at, bs);
*bs = *ep_list;
bs->next = NULL;
bs = root_bs->next;
@@ -6849,9 +6860,9 @@
struct breakpoint *b, *temp;
for (; bs; bs = bs->next)
- if (bs->breakpoint_at && bs->breakpoint_at->disposition == disp_del
+ if (bs->breakpoint_at && bs->breakpoint_at->owner->disposition == disp_del
&& bs->stop)
- delete_breakpoint (bs->breakpoint_at);
+ delete_breakpoint (bs->breakpoint_at->owner);
ALL_BREAKPOINTS_SAFE (b, temp)
{
@@ -7041,7 +7052,7 @@
in event-top.c won't do anything, and temporary breakpoints
with commands won't work. */
for (bs = stop_bpstat; bs; bs = bs->next)
- if (bs->breakpoint_at == bpt)
+ if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt)
{
bs->breakpoint_at = NULL;
bs->old_val = NULL;
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- src/gdb/breakpoint.h 2007/08/23 18:08:26 1.47
+++ src/gdb/breakpoint.h 2007/09/22 17:49:41 1.48
@@ -603,7 +603,7 @@
place, and a bpstat reflects the fact that both have been hit. */
bpstat next;
/* Breakpoint that we are at. */
- struct breakpoint *breakpoint_at;
+ struct bp_location *breakpoint_at;
/* Commands left to be done. */
struct command_line *commands;
/* Old value associated with a watchpoint. */
2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.h (struct breakpoint): Move the cond
field to...
(struct bp_location): Here.
* breakpoint.c (condition_command, bpstat_stop_status)
(print_one_breakpoint, allocate_bp_location)
(solib_load_unload_1, create_fork_vfork_event_catchpoint)
(create_exec_event_catchpoint, create_breakpoints)
(break_command_1, watch_command_1, handle_gnu_v3_exceptions)
(create_ada_exception_breakpoint, set_breakpoint_sal)
(delete_breakpoint, breakpoint_re_set_one): Adjust.
* tui/tui-winsource.c (tui_update_breakpoint_info): Adjust.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.264
retrieving revision 1.265
diff -u -r1.264 -r1.265
--- src/gdb/breakpoint.c 2007/09/22 17:49:40 1.264
+++ src/gdb/breakpoint.c 2007/09/22 19:06:59 1.265
@@ -569,17 +569,17 @@
ALL_BREAKPOINTS (b)
if (b->number == bnum)
{
- if (b->cond)
+ struct bp_location *loc = b->loc;
+ if (loc->cond)
{
- xfree (b->cond);
- b->cond = 0;
+ xfree (loc->cond);
+ loc->cond = 0;
}
if (b->cond_string != NULL)
xfree (b->cond_string);
if (*p == 0)
{
- b->cond = 0;
b->cond_string = NULL;
if (from_tty)
printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
@@ -592,7 +592,8 @@
b->cond_string = savestring (arg, strlen (arg));
if (!b->pending)
{
- b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ b->loc->cond = parse_exp_1 (&arg,
+ block_for_pc (b->loc->address), 0);
if (*arg)
error (_("Junk at end of expression"));
}
@@ -2923,19 +2924,19 @@
{
int value_is_zero = 0;
- if (b->cond)
+ if (b->loc->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->cond),
+ = catch_errors (breakpoint_cond_eval, (b->loc->cond),
"Error in testing breakpoint condition:\n",
RETURN_MASK_ALL);
/* FIXME-someday, should give breakpoint # */
free_all_values ();
}
- if (b->cond && value_is_zero)
+ if (b->loc->cond && value_is_zero)
{
bs->stop = 0;
/* Don't consider this a hit. */
@@ -3606,14 +3607,14 @@
ui_out_text (uiout, "\n");
}
- if (b->cond && !ada_exception_catchpoint_p (b))
+ if (b->loc->cond && !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->cond, stb->stream);
+ print_expression (b->loc->cond, stb->stream);
ui_out_field_stream (uiout, "cond", stb);
ui_out_text (uiout, "\n");
}
@@ -4085,6 +4086,7 @@
memset (loc, 0, sizeof (*loc));
loc->owner = bpt;
+ loc->cond = NULL;
switch (bp_type)
{
@@ -4604,7 +4606,6 @@
b = set_raw_breakpoint (sals.sals[0], bp_kind);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = NULL;
b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
@@ -4661,7 +4662,6 @@
b = set_raw_breakpoint (sal, bp_kind);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = NULL;
b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
@@ -4700,7 +4700,6 @@
b = set_raw_breakpoint (sal, bp_catch_exec);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = NULL;
b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
@@ -5033,7 +5032,7 @@
b = set_raw_breakpoint (sal, type);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = cond[i];
+ b->loc->cond = cond[i];
b->thread = thread;
if (addr_string[i])
b->addr_string = addr_string[i];
@@ -5056,7 +5055,7 @@
{
arg = pending_bp->cond_string;
b->cond_string = savestring (arg, strlen (arg));
- b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
if (*arg)
error (_("Junk at end of pending breakpoint condition expression"));
}
@@ -5399,7 +5398,7 @@
: bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = *cond;
+ b->loc->cond = *cond;
b->thread = thread;
b->addr_string = *addr_string;
b->cond_string = *cond_string;
@@ -5792,7 +5791,7 @@
b->exp_valid_block = exp_valid_block;
b->exp_string = savestring (exp_start, exp_end - exp_start);
b->val = val;
- b->cond = cond;
+ b->loc->cond = cond;
if (cond_start)
b->cond_string = savestring (cond_start, cond_end - cond_start);
else
@@ -6352,7 +6351,6 @@
b = set_raw_breakpoint (*sal, bptype);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = NULL;
b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
b->thread = thread;
@@ -6432,7 +6430,6 @@
b = set_raw_breakpoint (sals.sals[0], bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = NULL;
b->cond_string = (cond_string == NULL) ?
NULL : savestring (cond_string, strlen (cond_string));
b->thread = -1;
@@ -6519,7 +6516,7 @@
b->disposition = tempflag ? disp_del : disp_donttouch;
b->number = breakpoint_count;
b->ignore_count = 0;
- b->cond = cond;
+ b->loc->cond = cond;
b->addr_string = addr_string;
b->language = language_ada;
b->cond_string = cond_string;
@@ -6701,7 +6698,6 @@
b = set_raw_breakpoint (sal, bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->cond = 0;
b->thread = -1;
return b;
}
@@ -7021,8 +7017,6 @@
}
free_command_lines (&bpt->commands);
- if (bpt->cond)
- xfree (bpt->cond);
if (bpt->cond_string != NULL)
xfree (bpt->cond_string);
if (bpt->addr_string != NULL)
@@ -7062,6 +7056,8 @@
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);
xfree (bpt);
}
@@ -7215,14 +7211,14 @@
if (b->cond_string != NULL)
{
s = b->cond_string;
- if (b->cond)
+ if (b->loc->cond)
{
- xfree (b->cond);
+ xfree (b->loc->cond);
/* Avoid re-freeing b->exp if an error during the call
to parse_exp_1. */
- b->cond = NULL;
+ b->loc->cond = NULL;
}
- b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+ b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
}
/* We need to re-set the breakpoint if the address changes... */
@@ -7314,14 +7310,14 @@
if (b->cond_string != NULL)
{
s = b->cond_string;
- if (b->cond)
+ if (b->loc->cond)
{
- xfree (b->cond);
+ xfree (b->loc->cond);
/* Avoid re-freeing b->exp if an error during the call
to parse_exp_1. */
- b->cond = NULL;
+ b->loc->cond = NULL;
}
- b->cond = parse_exp_1 (&s, (struct block *) 0, 0);
+ b->loc->cond = parse_exp_1 (&s, (struct block *) 0, 0);
}
if (breakpoint_enabled (b))
mention (b);
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- src/gdb/breakpoint.h 2007/09/22 17:49:41 1.48
+++ src/gdb/breakpoint.h 2007/09/22 19:06:59 1.49
@@ -243,6 +243,13 @@
than reference counting. */
struct breakpoint *owner;
+ /* Conditional. Break only if this expression's value is nonzero.
+ Unlike string form of condition, which is associated with breakpoint,
+ this is associated with location, since if breakpoint has several
+ locations, the evaluation of expression can be different for
+ different locations. */
+ struct expression *cond;
+
/* Nonzero if this breakpoint is now inserted. */
char inserted;
@@ -341,8 +348,6 @@
/* Stack depth (address of frame). If nonzero, break only if fp
equals this. */
struct frame_id frame_id;
- /* Conditional. Break only if this expression's value is nonzero. */
- struct expression *cond;
/* String we used to set the breakpoint (malloc'd). */
char *addr_string;
===================================================================
RCS file: /cvs/src/src/gdb/tui/tui-winsource.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- src/gdb/tui/tui-winsource.c 2007/08/23 18:08:50 1.28
+++ src/gdb/tui/tui-winsource.c 2007/09/22 19:06:59 1.29
@@ -449,7 +449,7 @@
mode |= TUI_BP_ENABLED;
if (bp->hit_count)
mode |= TUI_BP_HIT;
- if (bp->cond)
+ if (bp->loc->cond)
mode |= TUI_BP_CONDITIONAL;
if (bp->type == bp_hardware_breakpoint)
mode |= TUI_BP_HARDWARE;
2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.c (create_breakpoint): Split from
create_breakpoints, implementing most of its logic.
Take just a single sal, single address string and
single condition. Do not take parsed condition at
all.
(create_breakpoints): Just call create_breakpoint
for each sal.
(find_condition_and_thread): New.
(break_command_1): Use find_condition_and_thread.
Do not keep parsed conditions.
(do_captured_breakpoint): Don't convert
condition string to struct expression.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.265
retrieving revision 1.266
diff -u -r1.265 -r1.266
--- src/gdb/breakpoint.c 2007/09/22 19:06:59 1.265
+++ src/gdb/breakpoint.c 2007/09/22 19:10:05 1.266
@@ -4984,93 +4984,125 @@
}
-/* Add SALS.nelts breakpoints to the breakpoint table. For each
- SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i],
- COND[i] and COND_STRING[i] values.
+/* Create a breakpoint with SAL as location. Use ADDR_STRING
+ as textual description of the location, and COND_STRING
+ as condition expression.
+
+ The paramter PENDING_BP is same as for the
+ create_breakpoints function. */
+
+static void
+create_breakpoint (struct symtab_and_line sal, 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;
+
+ if (type == bp_hardware_breakpoint)
+ {
+ int i = hw_breakpoint_used_count ();
+ int target_resources_ok =
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
+ i + 1, 0);
+ if (target_resources_ok == 0)
+ error (_("No hardware breakpoint support in the target."));
+ else if (target_resources_ok < 0)
+ 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;
+
+ 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;
+ }
+
+ 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;
+ else
+ /* addr_string has to be used or breakpoint_re_set will delete
+ me. */
+ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
+
+ mention (b);
+}
+
+/* Add SALS.nelts breakpoints to the breakpoint table. For each
+ SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
+ value. COND_STRING, if not NULL, specified the condition to be
+ used for all breakpoints. Essentially the only case where
+ SALS.nelts is not 1 is when we set a breakpoint on an overloaded
+ function. In that case, it's still not possible to specify
+ separate conditions for different overloaded functions, so
+ we take just a single condition string.
+
The parameter PENDING_BP points to a pending breakpoint that is
the basis of the breakpoints currently being created. The pending
breakpoint may contain a separate condition string or commands
that were added after the initial pending breakpoint was created.
NOTE: If the function succeeds, the caller is expected to cleanup
- the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the
+ the arrays ADDR_STRING, COND_STRING, and SALS (but not the
array contents). If the function fails (error() is called), the
caller is expected to cleanups both the ADDR_STRING, COND_STRING,
COND and SALS arrays and each of those arrays contents. */
static void
create_breakpoints (struct symtabs_and_lines sals, char **addr_string,
- struct expression **cond, char **cond_string,
+ char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int ignore_count, int from_tty,
struct breakpoint *pending_bp)
{
- if (type == bp_hardware_breakpoint)
+ int i;
+ for (i = 0; i < sals.nelts; ++i)
{
- int i = hw_breakpoint_used_count ();
- int target_resources_ok =
- TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint,
- i + sals.nelts, 0);
- if (target_resources_ok == 0)
- error (_("No hardware breakpoint support in the target."));
- else if (target_resources_ok < 0)
- error (_("Hardware breakpoints used exceeds limit."));
+ create_breakpoint (sals.sals[i], addr_string[i],
+ cond_string, type, disposition,
+ thread, ignore_count, from_tty,
+ pending_bp);
}
-
- /* Now set all the breakpoints. */
- {
- int i;
- for (i = 0; i < sals.nelts; i++)
- {
- struct breakpoint *b;
- struct symtab_and_line sal = sals.sals[i];
-
- 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->loc->cond = cond[i];
- b->thread = thread;
- if (addr_string[i])
- b->addr_string = addr_string[i];
- else
- /* addr_string has to be used or breakpoint_re_set will delete
- me. */
- b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address));
- b->cond_string = cond_string[i];
- 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)
- {
- char *arg;
- if (pending_bp->cond_string)
- {
- arg = pending_bp->cond_string;
- b->cond_string = savestring (arg, strlen (arg));
- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
- if (*arg)
- error (_("Junk at end of pending breakpoint condition expression"));
- }
- /* 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;
- }
- mention (b);
- }
- }
}
/* Parse ARG which is assumed to be a SAL specification possibly
@@ -5192,6 +5224,59 @@
args->not_found_ptr);
}
+/* Given TOK, a string specification of condition and thread, as
+ accepted by the 'break' command, extract the condition
+ string and thread number and set *COND_STRING and *THREAD.
+ PC identifies the context at which the condition should be parsed.
+ If no condition is found, *COND_STRING is set to NULL.
+ If no thread is found, *THREAD is set to -1. */
+static void
+find_condition_and_thread (char *tok, CORE_ADDR pc,
+ char **cond_string, int *thread)
+{
+ *cond_string = NULL;
+ *thread = -1;
+ while (tok && *tok)
+ {
+ char *end_tok;
+ int toklen;
+ char *cond_start = NULL;
+ char *cond_end = NULL;
+ while (*tok == ' ' || *tok == '\t')
+ tok++;
+
+ end_tok = tok;
+
+ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
+ end_tok++;
+
+ toklen = end_tok - tok;
+
+ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+ {
+ tok = cond_start = end_tok + 1;
+ parse_exp_1 (&tok, block_for_pc (pc), 0);
+ cond_end = tok;
+ *cond_string = savestring (cond_start,
+ cond_end - cond_start);
+ }
+ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+ {
+ char *tmptok;
+
+ tok = end_tok + 1;
+ tmptok = tok;
+ *thread = strtol (tok, &tok, 0);
+ if (tok == tmptok)
+ error (_("Junk after thread keyword."));
+ if (!valid_thread_id (*thread))
+ error (_("Unknown thread %d."), *thread);
+ }
+ else
+ error (_("Junk at end of arguments."));
+ }
+}
+
/* Set a breakpoint according to ARG (function, linenum or *address)
flag: first bit : 0 non-temporary, 1 temporary.
second bit : 0 normal breakpoint, 1 hardware breakpoint.
@@ -5205,9 +5290,8 @@
struct gdb_exception e;
int tempflag, hardwareflag;
struct symtabs_and_lines sals;
- struct expression **cond = 0;
struct symtab_and_line pending_sal;
- char **cond_string = (char **) NULL;
+ char *cond_string = NULL;
char *copy_arg;
char *err_msg;
char *addr_start = arg;
@@ -5297,14 +5381,6 @@
make_cleanup (xfree, addr_string);
}
- /* Allocate space for all the cond expressions. */
- 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 succeeds
@@ -5328,56 +5404,16 @@
/* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each
breakpoint. */
- thread = -1; /* No specific thread yet */
if (!pending)
{
- for (i = 0; i < sals.nelts; i++)
- {
- char *tok = arg;
- while (tok && *tok)
- {
- char *end_tok;
- int toklen;
- char *cond_start = NULL;
- char *cond_end = NULL;
- while (*tok == ' ' || *tok == '\t')
- tok++;
-
- end_tok = tok;
-
- while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
- end_tok++;
-
- toklen = end_tok - tok;
-
- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
- {
- tok = cond_start = end_tok + 1;
- cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc),
- 0);
- make_cleanup (xfree, cond[i]);
- cond_end = tok;
- cond_string[i] = savestring (cond_start,
- cond_end - cond_start);
- make_cleanup (xfree, cond_string[i]);
- }
- else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
- {
- char *tmptok;
-
- tok = end_tok + 1;
- tmptok = tok;
- thread = strtol (tok, &tok, 0);
- if (tok == tmptok)
- error (_("Junk after thread keyword."));
- if (!valid_thread_id (thread))
- error (_("Unknown thread %d."), thread);
- }
- else
- error (_("Junk at end of arguments."));
- }
- }
- create_breakpoints (sals, addr_string, cond, cond_string,
+ /* Here we only parse 'arg' to separate condition
+ from thread number, so parsing in context of first
+ sal is OK. When setting the breakpoint we'll
+ re-parse it in context of each sal. */
+ find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread);
+ if (cond_string)
+ make_cleanup (xfree, cond_string);
+ create_breakpoints (sals, addr_string, cond_string,
hardwareflag ? bp_hardware_breakpoint
: bp_breakpoint,
tempflag ? disp_del : disp_donttouch,
@@ -5398,10 +5434,10 @@
: bp_breakpoint);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
- b->loc->cond = *cond;
+ b->loc->cond = NULL;
b->thread = thread;
- b->addr_string = *addr_string;
- b->cond_string = *cond_string;
+ 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;
@@ -5445,7 +5481,7 @@
struct cleanup *breakpoint_chain = NULL;
int i;
char **addr_string;
- char **cond_string;
+ char *cond_string;
char *address_end;
@@ -5502,22 +5538,13 @@
/* Resolve all line numbers to PC's. */
breakpoint_sals_to_pc (&sals, args->address);
- /* Verify that conditions can be parsed, before setting any
- breakpoints. */
- for (i = 0; i < sals.nelts; i++)
+ if (args->condition != NULL)
{
- if (args->condition != NULL)
- {
- char *tok = args->condition;
- cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
- if (*tok != '\0')
- error (_("Garbage %s follows condition"), tok);
- make_cleanup (xfree, cond[i]);
- cond_string[i] = xstrdup (args->condition);
- }
+ cond_string = xstrdup (args->condition);
+ make_cleanup (xfree, cond_string);
}
- create_breakpoints (sals, addr_string, cond, cond_string,
+ create_breakpoints (sals, addr_string, args->condition,
args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint,
args->tempflag ? disp_del : disp_donttouch,
args->thread, args->ignore_count, 0/*from-tty*/,
2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.c (do_restore_lang_radix_cleanup): Remove.
(resolve_pending_breakpoint): Remove.
(re_enable_breakpoints_in_shlibs): Remove.
(unlink_locations_from_global_list): New.
(update_breakpoint_locations): New.
(breakpoint_re_set_one): Don't bail out on pending breakpoints.
Use parse_condition and update_breakpoint_location to
reset breakpoint. Ignore 'symbol not found' error from
decode_line_1.
(breakpoint_re_set): Don't emit newline before the
reason why breakpoint is not reset.
(do_enable_breakpoint): Don't specially process pending
breakpoints.
(free_bp_location): New.
(break_command_1): For pending breakpoints, initialize
all fields of a sal with zeroes.
* breakpoint.h (re_enable_breakpoints_in_shlibs): Remove.
* infcmd.c (post_create_inferior): Don't call
re_enable_breakpoints_in_shlibs.
* infrun.c (handle_inferior_event): Likewise.
* solib-irix.c (irix_solib_create_inferior_hook): Likewise.
* solib-osf.c (osf_solib_create_inferior_hook): Likewise.
* win32-nat.c (get_win32_debug_event): Likewise.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.266
retrieving revision 1.267
diff -u -r1.266 -r1.267
--- src/gdb/breakpoint.c 2007/09/22 19:10:05 1.266
+++ src/gdb/breakpoint.c 2007/09/22 19:33:31 1.267
@@ -203,6 +203,8 @@
static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc);
+static void free_bp_location (struct bp_location *loc);
+
/* Prototypes for exported functions. */
/* If FALSE, gdb will not use hardware support for watchpoints, even
@@ -4140,6 +4142,13 @@
return loc;
}
+static void free_bp_location (struct bp_location *loc)
+{
+ if (loc->cond)
+ xfree (loc->cond);
+ 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
@@ -4396,51 +4405,6 @@
int radix;
};
-/* Cleanup helper routine to restore the current language and
- input radix. */
-static void
-do_restore_lang_radix_cleanup (void *old)
-{
- struct lang_and_radix *p = old;
- set_language (p->lang);
- input_radix = p->radix;
-}
-
-/* Try and resolve a pending breakpoint. */
-static int
-resolve_pending_breakpoint (struct breakpoint *b)
-{
- /* Try and reparse the breakpoint in case the shared library
- is now loaded. */
- struct symtabs_and_lines sals;
- struct symtab_and_line pending_sal;
- char **cond_string = (char **) NULL;
- char *copy_arg = b->addr_string;
- char **addr_string;
- char *errmsg;
- int rc;
- int not_found = 0;
- struct ui_file *old_gdb_stderr;
- struct lang_and_radix old_lr;
- struct cleanup *old_chain;
-
- /* Set language, input-radix, then reissue breakpoint command.
- Ensure the language and input-radix are restored afterwards. */
- old_lr.lang = current_language->la_language;
- old_lr.radix = input_radix;
- old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr);
-
- set_language (b->language);
- input_radix = b->input_radix;
- rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b);
-
- if (rc == GDB_RC_OK)
- /* Pending breakpoint has been resolved. */
- printf_filtered (_("Pending breakpoint \"%s\" resolved\n"), b->addr_string);
-
- do_cleanups (old_chain);
- return rc;
-}
void
remove_solib_event_breakpoints (void)
@@ -4523,37 +4487,6 @@
}
}
-/* Try to reenable any breakpoints in shared libraries. */
-void
-re_enable_breakpoints_in_shlibs (void)
-{
- struct breakpoint *b, *tmp;
-
- ALL_BREAKPOINTS_SAFE (b, tmp)
- {
- if (b->enable_state == bp_shlib_disabled)
- {
- gdb_byte buf[1];
- char *lib;
-
- /* Do not reenable the breakpoint if the shared library is
- still not mapped in. */
-#ifdef PC_SOLIB
- lib = PC_SOLIB (b->loc->address);
-#else
- lib = solib_address (b->loc->address);
-#endif
- if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0)
- b->enable_state = bp_enabled;
- }
- else if (b->pending && (b->enable_state == bp_enabled))
- {
- if (resolve_pending_breakpoint (b) == GDB_RC_OK)
- delete_breakpoint (b);
- }
- }
-}
-
static void
solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname,
char *cond_string, enum bptype bp_kind)
@@ -5422,12 +5355,9 @@
}
else
{
- struct symtab_and_line sal;
+ struct symtab_and_line sal = {0};
struct breakpoint *b;
- sal.symtab = NULL;
- sal.pc = 0;
-
make_cleanup (xfree, copy_arg);
b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint
@@ -7153,6 +7083,97 @@
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. */
+{
+ 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;
+}
+
+
+static void
+update_breakpoint_location (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)
+ 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)
+ {
+ 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;
+ }
+ }
+
+ 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));
+
+ if (b->line_number == 0)
+ b->line_number = sal.line;
+
+ if (b->enable_state == bp_shlib_disabled)
+ b->enable_state = bp_enabled;
+
+ b->pending = 0;
+
+ check_duplicates (b);
+
+ if (existing)
+ free_bp_location (existing);
+}
+
+
/* Reset a breakpoint given it's struct breakpoint * BINT.
The value we return ends up being the return value from catch_errors.
Unused in this case. */
@@ -7164,11 +7185,13 @@
struct breakpoint *b = (struct breakpoint *) bint;
struct value *mark;
int i;
- int not_found;
- int *not_found_ptr = NULL;
- struct symtabs_and_lines sals;
+ int not_found = 0;
+ int *not_found_ptr = &not_found;
+ struct symtabs_and_lines sals = {};
char *s;
enum enable_state save_enable;
+ struct gdb_exception e;
+
switch (b->type)
{
@@ -7186,115 +7209,59 @@
delete_breakpoint (b);
return 0;
}
- /* HACK: cagney/2001-11-11: kettenis/2001-11-11: MarkK wrote:
-
- ``And a hack it is, although Apple's Darwin version of GDB
- contains an almost identical hack to implement a "future
- break" command. It seems to work in many real world cases,
- but it is easy to come up with a test case where the patch
- doesn't help at all.''
-
- ``It seems that the way GDB implements breakpoints - in -
- shared - libraries was designed for a.out shared library
- systems (SunOS 4) where shared libraries were loaded at a
- fixed address in memory. Since ELF shared libraries can (and
- will) be loaded at any address in memory, things break.
- Fixing this is not trivial. Therefore, I'm not sure whether
- we should add this hack to the branch only. I cannot
- guarantee that things will be fixed on the trunk in the near
- future.''
-
- In case we have a problem, disable this breakpoint. We'll
- restore its status if we succeed. Don't disable a
- shlib_disabled breakpoint though. There's a fair chance we
- can't re-set it if the shared library it's in hasn't been
- loaded yet. */
-
- if (b->pending)
- break;
-
- save_enable = b->enable_state;
- if (b->enable_state != bp_shlib_disabled)
- b->enable_state = bp_disabled;
- else
- /* If resetting a shlib-disabled breakpoint, we don't want to
- see an error message if it is not found since we will expect
- this to occur until the shared library is finally reloaded.
- We accomplish this by giving decode_line_1 a pointer to use
- for silent notification that the symbol is not found. */
- not_found_ptr = &not_found;
set_language (b->language);
input_radix = b->input_radix;
s = b->addr_string;
- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
- not_found_ptr);
- for (i = 0; i < sals.nelts; i++)
- {
- resolve_sal_pc (&sals.sals[i]);
-
- /* Reparse conditions, they might contain references to the
- old symtab. */
- if (b->cond_string != NULL)
- {
- s = b->cond_string;
- if (b->loc->cond)
- {
- xfree (b->loc->cond);
- /* Avoid re-freeing b->exp if an error during the call
- to parse_exp_1. */
- b->loc->cond = NULL;
- }
- b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
- }
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL,
+ not_found_ptr);
+ }
+ if (e.reason < 0)
+ {
+ int not_found_and_ok = 0;
+ /* For pending breakpoints, it's expected that parsing
+ will fail until the right shared library is loaded.
+ User has already told to create pending breakpoints and
+ 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))
+ not_found_and_ok = 1;
- /* We need to re-set the breakpoint if the address changes... */
- if (b->loc->address != sals.sals[i].pc
- /* ...or new and old breakpoints both have source files, and
- the source file name or the line number changes... */
- || (b->source_file != NULL
- && sals.sals[i].symtab != NULL
- && (strcmp (b->source_file, sals.sals[i].symtab->filename) != 0
- || b->line_number != sals.sals[i].line)
- )
- /* ...or we switch between having a source file and not having
- one. */
- || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
- )
+ if (!not_found_and_ok)
{
- 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->line_number = sals.sals[i].line;
- b->loc->requested_address = sals.sals[i].pc;
- b->loc->address
- = adjust_breakpoint_address (b->loc->requested_address,
- b->type);
-
- /* Used to check for duplicates here, but that can
- cause trouble, as it doesn't check for disabled
- breakpoints. */
-
- mention (b);
-
- /* Might be better to do this just once per breakpoint_re_set,
- rather than once for every breakpoint. */
- breakpoints_changed ();
+ /* We surely don't want to warn about the same breakpoint
+ 10 times. One solution, implemented here, is disable
+ the breakpoint on error. Another solution would be to
+ have separate 'warning emitted' flag. Since this
+ happens only when a binary has changed, I don't know
+ which approach is better. */
+ b->enable_state = bp_disabled;
+ throw_exception (e);
}
- b->loc->section = sals.sals[i].section;
- b->enable_state = save_enable; /* Restore it, this worked. */
+ }
+ if (not_found)
+ break;
+
+ gdb_assert (sals.nelts == 1);
+ resolve_sal_pc (&sals.sals[0]);
+ if (b->pending && s && s[0])
+ {
+ char *cond_string = 0;
+ int thread = -1;
+ find_condition_and_thread (s, sals.sals[0].pc,
+ &cond_string, &thread);
+ if (cond_string)
+ b->cond_string = cond_string;
+ b->thread = thread;
+ }
- /* Now that this is re-enabled, check_duplicates
- can be used. */
- check_duplicates (b);
+ update_breakpoint_location (b, sals);
- }
xfree (sals.sals);
break;
@@ -7408,7 +7375,7 @@
ALL_BREAKPOINTS_SAFE (b, temp)
{
/* Format possible error msg */
- char *message = xstrprintf ("Error in re-setting breakpoint %d:\n",
+ char *message = xstrprintf ("Error in re-setting breakpoint %d: ",
b->number);
struct cleanup *cleanups = make_cleanup (xfree, message);
catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL);
@@ -7635,88 +7602,68 @@
error (_("Hardware breakpoints used exceeds limit."));
}
- if (bpt->pending)
+ if (bpt->enable_state != bp_permanent)
+ bpt->enable_state = bp_enabled;
+ bpt->disposition = disposition;
+ check_duplicates (bpt);
+ breakpoints_changed ();
+
+ if (bpt->type == bp_watchpoint ||
+ bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
+ bpt->type == bp_access_watchpoint)
{
- if (bpt->enable_state != bp_enabled)
+ struct frame_id saved_frame_id;
+
+ saved_frame_id = get_frame_id (get_selected_frame (NULL));
+ if (bpt->exp_valid_block != NULL)
{
- /* When enabling a pending breakpoint, we need to check if the breakpoint
- is resolvable since shared libraries could have been loaded
- after the breakpoint was disabled. */
- breakpoints_changed ();
- if (resolve_pending_breakpoint (bpt) == GDB_RC_OK)
+ struct frame_info *fr =
+ fr = frame_find_by_id (bpt->watchpoint_frame);
+ if (fr == NULL)
{
- delete_breakpoint (bpt);
+ printf_filtered (_("\
+Cannot enable watchpoint %d because the block in which its expression\n\
+is valid is not currently in scope.\n"), bpt->number);
+ bpt->enable_state = bp_disabled;
return;
}
- bpt->enable_state = bp_enabled;
- bpt->disposition = disposition;
+ select_frame (fr);
}
- }
- else /* Not a pending breakpoint. */
- {
- if (bpt->enable_state != bp_permanent)
- bpt->enable_state = bp_enabled;
- bpt->disposition = disposition;
- check_duplicates (bpt);
- breakpoints_changed ();
- if (bpt->type == bp_watchpoint ||
- bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
+ value_free (bpt->val);
+ mark = value_mark ();
+ bpt->val = evaluate_expression (bpt->exp);
+ release_value (bpt->val);
+ if (value_lazy (bpt->val))
+ value_fetch_lazy (bpt->val);
+
+ if (bpt->type == bp_hardware_watchpoint ||
+ bpt->type == bp_read_watchpoint ||
bpt->type == bp_access_watchpoint)
{
- struct frame_id saved_frame_id;
-
- saved_frame_id = get_frame_id (get_selected_frame (NULL));
- if (bpt->exp_valid_block != NULL)
- {
- struct frame_info *fr =
- fr = frame_find_by_id (bpt->watchpoint_frame);
- if (fr == NULL)
- {
- printf_filtered (_("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n"), bpt->number);
- bpt->enable_state = bp_disabled;
- return;
- }
- select_frame (fr);
- }
-
- value_free (bpt->val);
- mark = value_mark ();
- bpt->val = evaluate_expression (bpt->exp);
- release_value (bpt->val);
- if (value_lazy (bpt->val))
- value_fetch_lazy (bpt->val);
+ int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
+ int mem_cnt = can_use_hardware_watchpoint (bpt->val);
- if (bpt->type == bp_hardware_watchpoint ||
- bpt->type == bp_read_watchpoint ||
- bpt->type == bp_access_watchpoint)
+ /* Hack around 'unused var' error for some targets here */
+ (void) mem_cnt, (void) i;
+ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
+ bpt->type, i + mem_cnt, other_type_used);
+ /* we can consider of type is bp_hardware_watchpoint, convert to
+ bp_watchpoint in the following condition */
+ if (target_resources_ok < 0)
{
- int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
- int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-
- /* Hack around 'unused var' error for some targets here */
- (void) mem_cnt, (void) i;
- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT (
- bpt->type, i + mem_cnt, other_type_used);
- /* we can consider of type is bp_hardware_watchpoint, convert to
- bp_watchpoint in the following condition */
- if (target_resources_ok < 0)
- {
- printf_filtered (_("\
+ printf_filtered (_("\
Cannot enable watchpoint %d because target watch resources\n\
have been allocated for other watchpoints.\n"), bpt->number);
- bpt->enable_state = bp_disabled;
- value_free_to_mark (mark);
- return;
- }
+ bpt->enable_state = bp_disabled;
+ value_free_to_mark (mark);
+ return;
}
-
- select_frame (frame_find_by_id (saved_frame_id));
- value_free_to_mark (mark);
}
+
+ select_frame (frame_find_by_id (saved_frame_id));
+ value_free_to_mark (mark);
}
if (deprecated_modify_breakpoint_hook)
@@ -7724,6 +7671,7 @@
breakpoint_modify_event (bpt->number);
}
+
void
enable_breakpoint (struct breakpoint *bpt)
{
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- src/gdb/breakpoint.h 2007/09/22 19:06:59 1.49
+++ src/gdb/breakpoint.h 2007/09/22 19:33:31 1.50
@@ -799,8 +799,6 @@
extern void disable_breakpoints_in_shlibs (void);
-extern void re_enable_breakpoints_in_shlibs (void);
-
extern void create_solib_load_event_breakpoint (char *, int, char *, char *);
extern void create_solib_unload_event_breakpoint (char *, int,
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.158
retrieving revision 1.159
diff -u -r1.158 -r1.159
--- src/gdb/infcmd.c 2007/09/04 01:38:07 1.158
+++ src/gdb/infcmd.c 2007/09/22 19:33:31 1.159
@@ -433,10 +433,6 @@
#else
solib_create_inferior_hook ();
#endif
-
- /* Enable any breakpoints which were disabled when the
- underlying shared library was deleted. */
- re_enable_breakpoints_in_shlibs ();
}
observer_notify_inferior_created (target, from_tty);
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.247
retrieving revision 1.248
diff -u -r1.247 -r1.248
--- src/gdb/infrun.c 2007/09/17 19:44:20 1.247
+++ src/gdb/infrun.c 2007/09/22 19:33:31 1.248
@@ -1337,10 +1337,6 @@
#endif
target_terminal_inferior ();
- /* Try to reenable shared library breakpoints, additional
- code segments in shared libraries might be mapped in now. */
- re_enable_breakpoints_in_shlibs ();
-
/* If requested, stop when the dynamic linker notifies
gdb of events. This allows the user to get control
and place breakpoints in initializer routines for
@@ -2276,10 +2272,6 @@
#endif
target_terminal_inferior ();
- /* Try to reenable shared library breakpoints, additional
- code segments in shared libraries might be mapped in now. */
- re_enable_breakpoints_in_shlibs ();
-
/* If requested, stop when the dynamic linker notifies
gdb of events. This allows the user to get control
and place breakpoints in initializer routines for
===================================================================
RCS file: /cvs/src/src/gdb/solib-irix.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- src/gdb/solib-irix.c 2007/08/23 18:08:38 1.14
+++ src/gdb/solib-irix.c 2007/09/22 19:33:31 1.15
@@ -457,7 +457,6 @@
suppresses the warning. */
solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
stop_soon = NO_STOP_QUIETLY;
- re_enable_breakpoints_in_shlibs ();
}
/* LOCAL FUNCTION
===================================================================
RCS file: /cvs/src/src/gdb/solib-osf.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/solib-osf.c 2007/08/23 18:08:38 1.11
+++ src/gdb/solib-osf.c 2007/09/22 19:33:31 1.12
@@ -336,9 +336,6 @@
suppresses the warning. */
solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
stop_soon = NO_STOP_QUIETLY;
-
- /* Enable breakpoints disabled (unnecessarily) by clear_solib(). */
- re_enable_breakpoints_in_shlibs ();
}
/* target_so_ops callback. Do additional symbol handling, lookup, etc. after
2007-09-22 Vladimir Prus <vladimir@codesourcery.com>
* gdb.base/pending.exp: No longer expect "Pending breakpoint resolved"
messages.
* gdb.base/chng-syms.exp: Likewise.
* gdb.base/unload.exp: Likewise.
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/chng-syms.exp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- src/gdb/testsuite/gdb.base/chng-syms.exp 2007/08/23 18:14:16 1.8
+++ src/gdb/testsuite/gdb.base/chng-syms.exp 2007/09/22 19:33:32 1.9
@@ -105,10 +105,10 @@
gdb_run_cmd
gdb_expect {
- -re "Error in re-setting .*No symbol .var1..*Program exited normally.*$gdb_prompt $" {
+ -re ".*No symbol .var1..*Program exited normally.*$gdb_prompt $" {
pass "running with invalidated bpt condition after executable changes"
}
- -re "Error in re-setting .*No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" {
+ -re "No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" {
pass "running with invalidated bpt condition after executable changes"
}
-re "$gdb_prompt $" {
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- src/gdb/testsuite/gdb.base/pending.exp 2007/08/23 18:14:17 1.10
+++ src/gdb/testsuite/gdb.base/pending.exp 2007/09/22 19:33:32 1.11
@@ -194,9 +194,7 @@
gdb_run_cmd
gdb_test "" \
-"Breakpoint.*at.*
-Pending breakpoint \"pendshr.c:$bp2_loc if x > 3\" resolved.*
-Breakpoint.*, main.*$mainline.*" \
+".*Breakpoint.*, main.*$mainline.*" \
"running to main"
#
@@ -204,8 +202,7 @@
#
gdb_test "enable 1" \
-"Breakpoint.*at.*
-Pending breakpoint \"pendfunc1.* resolved.*" \
+"" \
"re-enabling pending breakpoint that can resolve instantly"
#
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/testsuite/gdb.base/unload.exp 2007/08/23 18:14:17 1.11
+++ src/gdb/testsuite/gdb.base/unload.exp 2007/09/22 19:33:32 1.12
@@ -89,9 +89,7 @@
gdb_run_cmd
gdb_test "" \
-"Breakpoint.*at.*
-Pending breakpoint \"shrfunc1\" resolved.*
-Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \
+".*Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \
"running program"
gdb_test "continue" \
2007-09-23 Vladimir Prus <vladimir@codesourcery.com>
Allow a code breakpoint to have several locations
associated with it.
* 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.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.267
retrieving revision 1.268
diff -u -r1.267 -r1.268
--- src/gdb/breakpoint.c 2007/09/22 19:33:31 1.267
+++ src/gdb/breakpoint.c 2007/09/23 07:56:22 1.268
@@ -275,11 +275,11 @@
/* 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 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 @@
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 @@
/* 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 @@
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 @@
{
/* 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 @@
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 @@
{
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 @@
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 @@
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 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 @@
&& 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 @@
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 @@
/* 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 @@
{
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 @@
/* 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 @@
*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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
loc->owner = bpt;
loc->cond = NULL;
+ loc->shlib_disabled = 0;
+ loc->enabled = 1;
switch (bp_type)
{
@@ -4134,9 +4250,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
/* 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 @@
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 @@
}
+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 @@
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 @@
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 @@
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 @@
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 @@
struct cleanup *breakpoint_chain = NULL;
int i;
char **addr_string;
- char *cond_string;
+ char *cond_string = 0;
char *address_end;
@@ -5440,10 +5627,6 @@
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 @@
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 @@
}
}
+/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+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 @@
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 @@
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);
}
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -r1.50 -r1.51
--- src/gdb/breakpoint.h 2007/09/22 19:33:31 1.50
+++ src/gdb/breakpoint.h 2007/09/23 07:56:22 1.51
@@ -143,9 +143,6 @@
{
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 @@
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 @@
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 @@
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 @@
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;
};
/* The following stuff is an abstract data type "bpstat" ("breakpoint
2007-09-23 Vladimir Prus <vladimir@codesourcery.com>
* 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.
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota1.exp,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- src/gdb/testsuite/gdb.base/annota1.exp 2007/08/23 18:14:16 1.24
+++ src/gdb/testsuite/gdb.base/annota1.exp 2007/09/23 07:56:22 1.25
@@ -117,9 +117,9 @@
#
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" }
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota3.exp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- src/gdb/testsuite/gdb.base/annota3.exp 2007/08/23 18:14:16 1.14
+++ src/gdb/testsuite/gdb.base/annota3.exp 2007/09/23 07:56:22 1.15
@@ -127,8 +127,8 @@
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"
}
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/break.exp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- src/gdb/testsuite/gdb.base/break.exp 2007/08/23 18:14:16 1.29
+++ src/gdb/testsuite/gdb.base/break.exp 2007/09/23 07:56:22 1.30
@@ -179,7 +179,7 @@
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 @@
#
# 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\]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/condbreak.exp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- src/gdb/testsuite/gdb.base/condbreak.exp 2007/08/23 18:14:16 1.8
+++ src/gdb/testsuite/gdb.base/condbreak.exp 2007/09/23 07:56:22 1.9
@@ -125,14 +125,14 @@
}
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"
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- src/gdb/testsuite/gdb.base/pending.exp 2007/09/22 19:33:32 1.11
+++ src/gdb/testsuite/gdb.base/pending.exp 2007/09/23 07:56:22 1.12
@@ -71,8 +71,8 @@
}
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 @@
"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 "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 "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 @@
"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 "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 @@
"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 @@
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"
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- src/gdb/testsuite/gdb.base/sepdebug.exp 2007/09/21 22:42:52 1.10
+++ src/gdb/testsuite/gdb.base/sepdebug.exp 2007/09/23 07:56:22 1.11
@@ -179,7 +179,7 @@
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 @@
#
# 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\]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- src/gdb/testsuite/gdb.base/unload.exp 2007/09/22 19:33:32 1.12
+++ src/gdb/testsuite/gdb.base/unload.exp 2007/09/23 07:56:22 1.13
@@ -81,8 +81,8 @@
}
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}]
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/ovldbreak.exp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- src/gdb/testsuite/gdb.cp/ovldbreak.exp 2007/08/23 18:14:17 1.6
+++ src/gdb/testsuite/gdb.cp/ovldbreak.exp 2007/09/23 07:56:22 1.7
@@ -153,7 +153,7 @@
# 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_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_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
2007-09-24 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.c (remove_sal): New.
(expand_line_sal_maybe): New.
(create_breakpoints): Call expand_line_sal_maybe.
(clear_command): Add comment.
(breakpoint_re_set_one): Call expand_line_sal_maybe.
* linespec.c (decode_indirect): Set explicit_pc to 1.
(decode_all_digits): Set explicit_line to 1.
(append_expanded_sal): New.
(expand_line_sal): New.
* linespec.h (expand_line_sal): Declare.
* symtab.c (init_sal): Initialize explicit_pc
and explicit_line.
* symtab.h (struct symtab_and_line): New fields
explicit_pc and explicit_line.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.268
retrieving revision 1.269
diff -u -r1.268 -r1.269
--- src/gdb/breakpoint.c 2007/09/23 07:56:22 1.268
+++ src/gdb/breakpoint.c 2007/09/24 07:40:32 1.269
@@ -5184,6 +5184,128 @@
mention (b);
}
+/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
+ elements to fill the void space. */
+static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
+{
+ int i = index_to_remove+1;
+ int last_index = sal->nelts-1;
+
+ for (;i <= last_index; ++i)
+ sal->sals[i-1] = sal->sals[i];
+
+ --(sal->nelts);
+}
+
+/* If appropriate, obtains all sals that correspond
+ to the same file and line as SAL. This is done
+ only if SAL does not have explicit PC and has
+ line and file information. If we got just a single
+ expanded sal, return the original.
+
+ Otherwise, if SAL.explicit_line is not set, filter out
+ all sals for which the name of enclosing function
+ is different from SAL. This makes sure that if we have
+ breakpoint originally set in template instantiation, say
+ foo<int>(), we won't expand SAL to locations at the same
+ line in all existing instantiations of 'foo'.
+
+*/
+struct symtabs_and_lines
+expand_line_sal_maybe (struct symtab_and_line sal)
+{
+ struct symtabs_and_lines expanded;
+ CORE_ADDR original_pc = sal.pc;
+ char *original_function = NULL;
+ int found;
+ int i;
+
+ /* If we have explicit pc, don't expand.
+ If we have no line number, we can't expand. */
+ if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL)
+ {
+ expanded.nelts = 1;
+ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+ expanded.sals[0] = sal;
+ return expanded;
+ }
+
+ sal.pc = 0;
+ find_pc_partial_function (original_pc, &original_function, NULL, NULL);
+
+ expanded = expand_line_sal (sal);
+ if (expanded.nelts == 1)
+ {
+ /* We had one sal, we got one sal. Without futher
+ processing, just return the original sal. */
+ xfree (expanded.sals);
+ expanded.nelts = 1;
+ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+ sal.pc = original_pc;
+ expanded.sals[0] = sal;
+ return expanded;
+ }
+
+ if (!sal.explicit_line)
+ {
+ CORE_ADDR func_addr, func_end;
+ for (i = 0; i < expanded.nelts; ++i)
+ {
+ CORE_ADDR pc = expanded.sals[i].pc;
+ char *this_function;
+ if (find_pc_partial_function (pc, &this_function,
+ &func_addr, &func_end))
+ {
+ if (this_function &&
+ strcmp (this_function, original_function) != 0)
+ {
+ remove_sal (&expanded, i);
+ --i;
+ }
+ else if (func_addr == pc)
+ {
+ /* We're at beginning of a function, and should
+ skip prologue. */
+ struct symbol *sym = find_pc_function (pc);
+ if (sym)
+ expanded.sals[i] = find_function_start_sal (sym, 1);
+ else
+ expanded.sals[i].pc
+ = gdbarch_skip_prologue (current_gdbarch, pc);
+ }
+ }
+ }
+ }
+
+
+ if (expanded.nelts <= 1)
+ {
+ /* This is un ugly workaround. If we get zero
+ expanded sals then something is really wrong.
+ Fix that by returnign the original sal. */
+ xfree (expanded.sals);
+ expanded.nelts = 1;
+ expanded.sals = xmalloc (sizeof (struct symtab_and_line));
+ sal.pc = original_pc;
+ expanded.sals[0] = sal;
+ return expanded;
+ }
+
+ if (original_pc)
+ {
+ found = 0;
+ for (i = 0; i < expanded.nelts; ++i)
+ if (expanded.sals[i].pc == original_pc)
+ {
+ found = 1;
+ break;
+ }
+ gdb_assert (found);
+ }
+
+ return expanded;
+}
+
/* Add SALS.nelts breakpoints to the breakpoint table. For each
SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
value. COND_STRING, if not NULL, specified the condition to be
@@ -5214,11 +5336,10 @@
int i;
for (i = 0; i < sals.nelts; ++i)
{
- struct symtabs_and_lines sals2;
- sals2.sals = sals.sals + i;
- sals2.nelts = 1;
+ struct symtabs_and_lines expanded =
+ expand_line_sal_maybe (sals.sals[i]);
- create_breakpoint (sals2, addr_string[i],
+ create_breakpoint (expanded, addr_string[i],
cond_string, type, disposition,
thread, ignore_count, from_tty,
pending_bp);
@@ -6889,6 +7010,23 @@
default_match = 1;
}
+ /* We don't call resolve_sal_pc here. That's not
+ as bad as it seems, because all existing breakpoints
+ typically have both file/line and pc set. So, if
+ clear is given file/line, we can match this to existing
+ breakpoint without obtaining pc at all.
+
+ We only support clearing given the address explicitly
+ present in breakpoint table. Say, we've set breakpoint
+ at file:line. There were several PC values for that file:line,
+ due to optimization, all in one block.
+ We've picked one PC value. If "clear" is issued with another
+ PC corresponding to the same file:line, the breakpoint won't
+ be cleared. We probably can still clear the breakpoint, but
+ since the other PC value is never presented to user, user
+ can only find it by guessing, and it does not seem important
+ to support that. */
+
/* For each line spec given, delete bps which correspond
to it. Do it in two passes, solely to preserve the current
behavior that from_tty is forced true if we delete more than
@@ -7404,8 +7542,12 @@
}
}
- if (existing_locations)
- free_bp_location (existing_locations);
+ while (existing_locations)
+ {
+ struct bp_location *next = existing_locations->next;
+ free_bp_location (existing_locations);
+ existing_locations = next;
+ }
}
@@ -7423,6 +7565,7 @@
int not_found = 0;
int *not_found_ptr = &not_found;
struct symtabs_and_lines sals = {};
+ struct symtabs_and_lines expanded;
char *s;
enum enable_state save_enable;
struct gdb_exception e;
@@ -7497,8 +7640,8 @@
b->thread = thread;
b->condition_not_parsed = 0;
}
-
- update_breakpoint_locations (b, sals);
+ expanded = expand_line_sal_maybe (sals.sals[0]);
+ update_breakpoint_locations (b, expanded);
/* Now that this is re-enabled, check_duplicates
can be used. */
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- src/gdb/linespec.c 2007/08/23 18:08:35 1.72
+++ src/gdb/linespec.c 2007/09/24 07:40:32 1.73
@@ -963,6 +963,7 @@
values.sals[0] = find_pc_line (pc, 0);
values.sals[0].pc = pc;
values.sals[0].section = find_pc_overlay (pc);
+ values.sals[0].explicit_pc = 1;
return values;
}
@@ -1633,6 +1634,7 @@
values.nelts = 1;
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
+ values.sals[0].explicit_line = 1;
return values;
}
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.164
retrieving revision 1.165
diff -u -r1.164 -r1.165
--- src/gdb/symtab.c 2007/08/29 18:34:46 1.164
+++ src/gdb/symtab.c 2007/09/24 07:40:32 1.165
@@ -691,6 +691,8 @@
sal->line = 0;
sal->pc = 0;
sal->end = 0;
+ sal->explicit_pc = 0;
+ sal->explicit_line = 0;
}
@@ -4172,6 +4174,166 @@
set_main_name (NULL);
}
+/* Helper to expand_line_sal below. Appends new sal to SAL,
+ initializing it from SYMTAB, LINENO and PC. */
+static void
+append_expanded_sal (struct symtabs_and_lines *sal,
+ struct symtab *symtab,
+ int lineno, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr, func_end;
+
+ sal->sals = xrealloc (sal->sals,
+ sizeof (sal->sals[0])
+ * (sal->nelts + 1));
+ init_sal (sal->sals + sal->nelts);
+ sal->sals[sal->nelts].symtab = symtab;
+ sal->sals[sal->nelts].section = NULL;
+ sal->sals[sal->nelts].end = 0;
+ sal->sals[sal->nelts].line = lineno;
+ sal->sals[sal->nelts].pc = pc;
+ ++sal->nelts;
+}
+
+/* Compute a set of all sals in
+ the entire program that correspond to same file
+ and line as SAL and return those. If there
+ are several sals that belong to the same block,
+ only one sal for the block is included in results. */
+
+struct symtabs_and_lines
+expand_line_sal (struct symtab_and_line sal)
+{
+ struct symtabs_and_lines ret, this_line;
+ int i, j;
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ struct symtab *symtab;
+ int lineno;
+ int deleted = 0;
+ struct block **blocks = NULL;
+ int *filter;
+
+ ret.nelts = 0;
+ ret.sals = NULL;
+
+ if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
+ {
+ ret.sals = xmalloc (sizeof (struct symtab_and_line));
+ ret.sals[0] = sal;
+ ret.nelts = 1;
+ return ret;
+ }
+ else
+ {
+ struct linetable_entry *best_item = 0;
+ struct symtab *best_symtab = 0;
+ int exact = 0;
+
+ lineno = sal.line;
+
+ /* We meed to find all symtabs for a file which name
+ is described by sal. We cannot just directly
+ iterate over symtabs, since a symtab might not be
+ yet created. We also cannot iterate over psymtabs,
+ calling PSYMTAB_TO_SYMTAB and working on that symtab,
+ since PSYMTAB_TO_SYMTAB will return NULL for psymtab
+ corresponding to an included file. Therefore, we do
+ first pass over psymtabs, reading in those with
+ the right name. Then, we iterate over symtabs, knowing
+ that all symtabs we're interested in are loaded. */
+
+ ALL_PSYMTABS (objfile, psymtab)
+ {
+ if (strcmp (sal.symtab->filename,
+ psymtab->filename) == 0)
+ PSYMTAB_TO_SYMTAB (psymtab);
+ }
+
+
+ /* For each symtab, we add all pcs to ret.sals. I'm actually
+ not sure what to do if we have exact match in one symtab,
+ and non-exact match on another symtab.
+ */
+ ALL_SYMTABS (objfile, symtab)
+ {
+ if (strcmp (sal.symtab->filename,
+ symtab->filename) == 0)
+ {
+ struct linetable *l;
+ int len;
+ l = LINETABLE (symtab);
+ if (!l)
+ continue;
+ len = l->nitems;
+
+ for (j = 0; j < len; j++)
+ {
+ struct linetable_entry *item = &(l->item[j]);
+
+ if (item->line == lineno)
+ {
+ exact = 1;
+ append_expanded_sal (&ret, symtab, lineno, item->pc);
+ }
+ else if (!exact && item->line > lineno
+ && (best_item == NULL || item->line < best_item->line))
+
+ {
+ best_item = item;
+ best_symtab = symtab;
+ }
+ }
+ }
+ }
+ if (!exact && best_item)
+ append_expanded_sal (&ret, best_symtab, lineno, best_item->pc);
+ }
+
+ /* For optimized code, compiler can scatter one source line accross
+ disjoint ranges of PC values, even when no duplicate functions
+ or inline functions are involved. For example, 'for (;;)' inside
+ non-template non-inline non-ctor-or-dtor function can result
+ in two PC ranges. In this case, we don't want to set breakpoint
+ on first PC of each range. To filter such cases, we use containing
+ blocks -- for each PC found above we see if there are other PCs
+ that are in the same block. If yes, the other PCs are filtered out. */
+
+ filter = xmalloc (ret.nelts * sizeof (int));
+ blocks = xmalloc (ret.nelts * sizeof (struct block *));
+ for (i = 0; i < ret.nelts; ++i)
+ {
+ filter[i] = 1;
+ blocks[i] = block_for_pc (ret.sals[i].pc);
+ }
+
+ for (i = 0; i < ret.nelts; ++i)
+ if (blocks[i] != NULL)
+ for (j = i+1; j < ret.nelts; ++j)
+ if (blocks[j] == blocks[i])
+ {
+ filter[j] = 0;
+ ++deleted;
+ break;
+ }
+
+ {
+ struct symtab_and_line *final =
+ xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
+
+ for (i = 0, j = 0; i < ret.nelts; ++i)
+ if (filter[i])
+ final[j++] = ret.sals[i];
+
+ ret.nelts -= deleted;
+ xfree (ret.sals);
+ ret.sals = final;
+ }
+
+ return ret;
+}
+
+
void
_initialize_symtab (void)
{
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -r1.106 -r1.107
--- src/gdb/symtab.h 2007/08/23 18:08:45 1.106
+++ src/gdb/symtab.h 2007/09/24 07:40:32 1.107
@@ -1213,6 +1213,8 @@
CORE_ADDR pc;
CORE_ADDR end;
+ int explicit_pc;
+ int explicit_line;
};
extern void init_sal (struct symtab_and_line *sal);
@@ -1404,5 +1406,7 @@
const domain_enum domain,
struct symtab **symtab);
+extern struct symtabs_and_lines
+expand_line_sal (struct symtab_and_line sal);
#endif /* !defined(SYMTAB_H) */
2007-09-24 Vladimir Prus <vladimir@codesourcery.com>
* gdb.cp/mb-ctor.cc: New.
* gdb.cp/mb-ctor.exp: New.
* gdb.cp/mb-templates.cc: New.
* gdb.cp/mb-templates.exp: New.
/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.cc,v --> standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-ctor.cc
+++ - 2007-11-01 22:04:53.928594000 +0000
@@ -0,0 +1,58 @@
+
+#include <stdio.h>
+
+class Base
+{
+public:
+ Base(int k);
+ ~Base();
+ virtual void foo() {}
+private:
+ int k;
+};
+
+Base::Base(int k)
+{
+ this->k = k;
+}
+
+Base::~Base()
+{
+ printf("~Base\n");
+}
+
+class Derived : public virtual Base
+{
+public:
+ Derived(int i);
+ ~Derived();
+private:
+ int i;
+};
+
+Derived::Derived(int i) : Base(i)
+{
+ this->i = i;
+}
+
+Derived::~Derived()
+{
+ printf("~Derived\n");
+}
+
+class DeeplyDerived : public Derived
+{
+public:
+ DeeplyDerived(int i) : Base(i), Derived(i) {}
+};
+
+int main()
+{
+ /* Invokes the Derived ctor that constructs both
+ Derived and Base. */
+ Derived d(7);
+ /* Invokes the Derived ctor that constructs only
+ Derived. Base is constructed separately by
+ DeeplyDerived's ctor. */
+ DeeplyDerived dd(15);
+}
/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.exp,v --> standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-ctor.exp
+++ - 2007-11-01 22:04:54.490054000 +0000
@@ -0,0 +1,86 @@
+# Copyright 2007
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test that breakpoints on C++ constructors work, despite the
+# fact that gcc generates several versions of constructor function.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "mb-ctor"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ untested mb-ctor.exp
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Set a breakpoint with multiple locations
+# and a condition.
+
+gdb_test "break 'Derived::Derived(int)'" \
+ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "set-breakpoint at ctor"
+
+gdb_test "break 'Derived::~Derived()'" \
+ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "set-breakpoint at ctor"
+
+gdb_run_cmd
+gdb_expect {
+ -re "Breakpoint \[0-9\]+,.*Derived.*i=7.*$gdb_prompt $" {
+ pass "run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "run to breakpoint"
+ }
+ timeout {
+ fail "run to breakpoint (timeout)"
+ }
+}
+
+gdb_test "continue" \
+ ".*Breakpoint.*Derived.*i=15.*" \
+ "run to breakpoint 2"
+
+gdb_test "continue" \
+ ".*Breakpoint.*~Derived.*" \
+ "run to breakpoint 3"
+
+gdb_test "continue" \
+ ".*Breakpoint.*~Derived.*" \
+ "run to breakpoint 4"
+
+gdb_test "continue" \
+ ".*exited normally.*" \
+ "run to exit"
+
+
+
/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.cc,v --> standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-templates.cc
+++ - 2007-11-01 22:04:55.064722000 +0000
@@ -0,0 +1,19 @@
+
+#include <iostream>
+using namespace std;
+
+template<class T>
+void foo(T i)
+{
+ std::cout << "hi\n"; // set breakpoint here
+}
+
+int main()
+{
+ foo<int>(0);
+ foo<double>(0);
+ foo<int>(1);
+ foo<double>(1);
+ foo<int>(2);
+ foo<double>(2);
+}
/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.exp,v --> standard output
revision 1.1
--- src/gdb/testsuite/gdb.cp/mb-templates.exp
+++ - 2007-11-01 22:04:55.647560000 +0000
@@ -0,0 +1,161 @@
+# Copyright 2007
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This test verifies that setting breakpoint on line in template
+# function will fire in all instantiations of that template.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile "mb-templates"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+ return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+ untested mb-templates.exp
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set bp_location [gdb_get_line_number "set breakpoint here"]
+
+# Set a breakpoint with multiple locations
+# and a condition.
+
+gdb_test "break $srcfile:$bp_location if i==1" \
+ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "initial condition: set breakpoint"
+
+gdb_run_cmd
+gdb_expect {
+ -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
+ pass "initial condition: run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "initial condition: run to breakpoint"
+ }
+ timeout {
+ fail "initial condition: run to breakpoint (timeout)"
+ }
+}
+
+gdb_test "continue" \
+ ".*Breakpoint.*foo<double> \\(i=1\\).*" \
+ "initial condition: run to breakpoint 2"
+
+# Set breakpoint with multiple locations.
+# Separately set the condition.
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break $srcfile:$bp_location" \
+ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "separate condition: set breakpoint"
+
+gdb_test "condition 1 i==1" "" \
+ "separate condition: set condition"
+
+gdb_run_cmd
+gdb_expect {
+ -re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
+ pass "separate condition: run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "separate condition: run to breakpoint"
+ }
+ timeout {
+ fail "separate condition: run to breakpoint (timeout)"
+ }
+}
+
+gdb_test "continue" \
+ ".*Breakpoint.*foo<double> \\(i=1\\).*" \
+ "separate condition: run to breakpoint 2"
+
+# Try disabling a single location. We also test
+# that at least in simple cases, the enable/disable
+# state of locations surive "run".
+gdb_test "disable 1.1" "" "disabling location: disable"
+
+gdb_run_cmd
+gdb_expect {
+ -re "Breakpoint \[0-9\]+,.*foo<double> \\(i=1\\).*$gdb_prompt $" {
+ pass "disabling location: run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "disabling location: run to breakpoint"
+ }
+ timeout {
+ fail "disabling location: run to breakpoint (timeout)"
+ }
+}
+
+# Try disabling entire breakpoint
+gdb_test "enable 1.1" "" "disabling location: enable"
+
+
+gdb_test "disable 1" "" "disable breakpoint: disable"
+
+gdb_run_cmd
+gdb_expect {
+ -re "Program exited normally.*$gdb_prompt $" {
+ pass "disable breakpoint: run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "disable breakpoint: run to breakpoint"
+ }
+ timeout {
+ fail "disable breakpoint: run to breakpoint (timeout)"
+ }
+}
+
+# Make sure breakpoint can be set on a specific instantion.
+delete_breakpoints
+gdb_test "break 'void foo<int>(int)'" ".*" \
+ "instantiation: set breakpoint"
+
+
+gdb_run_cmd
+gdb_expect {
+ -re ".*Breakpoint \[0-9\]+,.*foo<int> \\(i=0\\).*$gdb_prompt $" {
+ pass "instantiation: run to breakpoint"
+ }
+ -re "$gdb_prompt $" {
+ fail "instantiation: run to breakpoint"
+ }
+ timeout {
+ fail "instantiation: run to breakpoint (timeout)"
+ }
+}
+
+gdb_test "continue" \
+ ".*Breakpoint.*foo<int> \\(i=1\\).*" \
+ "instantiation: run to breakpoint 2"
+
2007-09-26 Vladimir Prus <vladimir@codesourcery.com>
* breakpoint.c (create_breakpoint): Set
condition on each location, not on the first
location of breakpoint.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.269
retrieving revision 1.270
diff -u -r1.269 -r1.270
--- src/gdb/breakpoint.c 2007/09/24 07:40:32 1.269
+++ src/gdb/breakpoint.c 2007/09/26 18:44:55 1.270
@@ -5163,7 +5163,7 @@
if (b->cond_string)
{
char *arg = b->cond_string;
- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0);
+ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0);
if (*arg)
{
if (pending_bp)
2007-09-28 Vladimir Prus <vladimir@codesourcery.com>
* NEW: Mention pending breakpoint changes and
support for breakpoints at multiple locations.
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.239
retrieving revision 1.240
diff -u -r1.239 -r1.240
--- src/gdb/NEWS 2007/09/17 19:30:05 1.239
+++ src/gdb/NEWS 2007/09/28 06:24:20 1.240
@@ -3,6 +3,13 @@
*** Changes since GDB 6.7
+* Pending breakpoints no longer change their number when their address
+ is resolved.
+
+* GDB now supports breakpoints with multiple locations,
+ including breakpoints on C++ constructors, inside C++ templates,
+ and in inlined functions.
+
*** Changes in GDB 6.6
* Resolved 101 resource leaks, null pointer dereferences, etc. in gdb,
2007-09-28 Vladimir Prus <vladimir@codesourcery.com>
* gdb.texinfo (Setting Breakpoints): Revise
documentation for pending breakpoints. Document
breakpoints with multiple locations.
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.432
retrieving revision 1.433
diff -u -r1.432 -r1.433
--- src/gdb/doc/gdb.texinfo 2007/09/16 14:59:30 1.432
+++ src/gdb/doc/gdb.texinfo 2007/09/28 06:24:20 1.433
@@ -2991,11 +2991,17 @@
Whether the breakpoint is marked to be disabled or deleted when hit.
@item Enabled or Disabled
Enabled breakpoints are marked with @samp{y}. @samp{n} marks breakpoints
-that are not enabled.
+that are not enabled. An optional @samp{(p)} suffix marks pending
+breakpoints --- breakpoints for which address is either not yet
+resolved, pending load of a shared library, or for which address was
+in a shared library that was since unloaded. Such breakpoint won't
+fire until a shared library that has the symbol or line referred by
+breakpoint is loaded. See below for details.
@item Address
-Where the breakpoint is in your program, as a memory address. If the
-breakpoint is pending (see below for details) on a future load of a shared library, the address
-will be listed as @samp{<PENDING>}.
+Where the breakpoint is in your program, as a memory address. For a
+pending breakpoint whose address is not yet known, this field will
+contain @samp{<PENDING>}. A breakpoint with several locations will
+have @samp{<MULTIPLE>} in this field --- see below for details.
@item What
Where the breakpoint is in the source for your program, as a file and
line number. For a pending breakpoint, the original string passed to
@@ -3032,23 +3038,83 @@
the breakpoints are conditional, this is even useful
(@pxref{Conditions, ,Break Conditions}).
-@cindex pending breakpoints
-If a specified breakpoint location cannot be found, it may be due to the fact
-that the location is in a shared library that is yet to be loaded. In such
-a case, you may want @value{GDBN} to create a special breakpoint (known as
-a @dfn{pending breakpoint}) that
-attempts to resolve itself in the future when an appropriate shared library
-gets loaded.
-
-Pending breakpoints are useful to set at the start of your
-@value{GDBN} session for locations that you know will be dynamically loaded
-later by the program being debugged. When shared libraries are loaded,
-a check is made to see if the load resolves any pending breakpoint locations.
-If a pending breakpoint location gets resolved,
-a regular breakpoint is created and the original pending breakpoint is removed.
+It is possible that a breakpoint correspond to several locations
+in your program. Examples of this situation are:
+
+@itemize @bullet
+
+@item
+For a C@t{++} constructor, the @value{NGCC} compiler generates several
+instances of the function body, used in different cases.
-@value{GDBN} provides some additional commands for controlling pending
-breakpoint support:
+@item
+For a C@t{++} template function, a given line in the function can
+correspond to any number of instantiations.
+
+@item
+For an inlined function, a given source line can correspond to
+several places where that function is inlined.
+
+@end itemize
+
+In all those cases, @value{GDBN} will insert a breakpoint at all
+the relevant locations.
+
+A breakpoint with multiple locations is displayed in the
+breakpoint table using several rows --- one header row, followed
+by one row for each breakpoint location. The header row
+has @samp{<MULTIPLE>} in the address column. The rows for
+individual locations contain the actual addresses for locations,
+and say what functions those locations are in. The number
+column for a location has number in the format
+@var{breakpoint-number}.@var{location-number}.
+
+For example:
+@smallexample
+Num Type Disp Enb Address What
+1 breakpoint keep y <MULTIPLE>
+ stop only if i==1
+ breakpoint already hit 1 time
+1.1 y 0x080486a2 in void foo<int>() at t.cc:8
+1.2 y 0x080486ca in void foo<double>() at t.cc:8
+@end smallexample
+
+Each location can be individually enabled or disabled by passing
+@var{breakpoint-number}.@var{location-number} as argument to the
+@code{enable} and @code{disable} commands.
+
+@cindex pending breakpoints
+It's quite common to have a breakpoint inside a shared library.
+The shared library may be loaded and unloaded explicitly,
+and possibly repeatedly, as the program is executed. To support
+this use case, @value{GDBN} updates breakpoint locations whenever
+any shared library is loaded or unloaded. Typically, you would
+set a breakpoint in a shared library at the beginning of your
+debugging session, when the library is not loaded, and when the
+symbols from the library are not available. When you try to set
+breakpoint, @value{GDBN} will ask you if you want to set
+a so called @dfn{pending breakpoint} --- breakpoint whose address
+is not yet resolved.
+
+After the program is run, whenever a new shared library is loaded,
+@value{GDBN} reevaluates all the breakpoints. When a newly loaded
+shared library contains the symbol or line referred to by some
+pending breakpoint, that breakpoint is resolved and becomes an
+ordinary breakpoint. When a library is unloaded, all breakpoints
+that refer to its symbols or source lines become pending again.
+
+This logic works for breakpoints with multiple locations, too. For
+example, if you have a breakpoint in a C@t{++} template function, and
+a newly loaded shared library has an instantiation of that template,
+a new location is added to the list of locations for the breakpoint.
+
+Except for having unresolved address, pending breakpoints do not
+differ from regular breakpoints. You can set conditions or commands,
+enable and disable them and perform other breakpoint operations.
+
+@value{GDBN} provides some additional commands for controlling what
+happens when the @samp{break} command cannot resolve breakpoint
+address specification to an address:
@kindex set breakpoint pending
@kindex show breakpoint pending
@@ -3070,19 +3136,9 @@
Show the current behavior setting for creating pending breakpoints.
@end table
-@cindex operations allowed on pending breakpoints
-Normal breakpoint operations apply to pending breakpoints as well. You may
-specify a condition for a pending breakpoint and/or commands to run when the
-breakpoint is reached. You can also enable or disable
-the pending breakpoint. When you specify a condition for a pending breakpoint,
-the parsing of the condition will be deferred until the point where the
-pending breakpoint location is resolved. Disabling a pending breakpoint
-tells @value{GDBN} to not attempt to resolve the breakpoint on any subsequent
-shared library load. When a pending breakpoint is re-enabled,
-@value{GDBN} checks to see if the location is already resolved.
-This is done because any number of shared library loads could have
-occurred since the time the breakpoint was disabled and one or more
-of these loads could resolve the location.
+The settings above only affect the @code{break} command and its
+variants. Once breakpoint is set, it will be automatically updated
+as shared libraries are loaded and unloaded.
@cindex automatic hardware breakpoints
For some targets, @value{GDBN} can automatically decide if hardware or
2007-10-08 Pierre Muller <muller@ics.u-strasbg.fr>
* breakpoint.c (print_one_breakpoint_location): ARI fix:
Replace asprintf by xstrprintf.
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.271
retrieving revision 1.272
diff -u -r1.271 -r1.272
--- src/gdb/breakpoint.c 2007/10/01 00:17:57 1.271
+++ src/gdb/breakpoint.c 2007/10/08 15:23:42 1.272
@@ -3526,7 +3526,7 @@
if (part_of_multiple)
{
char *formatted;
- asprintf (&formatted, "%d.%d", b->number, loc_number);
+ formatted = xstrprintf ("%d.%d", b->number, loc_number);
ui_out_field_string (uiout, "number", formatted);
xfree (formatted);
}