5347 lines
172 KiB
Diff
5347 lines
172 KiB
Diff
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 = ¬_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 = ¬_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 = ¬_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);
|
||
}
|
||
|
||
2007-09-17 Daniel Jacobowitz <dan@codesourcery.com>
|
||
|
||
* schedlock.c (NUM): Change to 1.
|
||
(main): Use args[0] for the main thread.
|
||
* schedlock.exp: Only expect two threads. Only issue one pass or fail
|
||
regardless of the number of threads.
|
||
|
||
--- ./gdb/testsuite/gdb.threads/schedlock.exp 23 Aug 2007 18:14:19 -0000 1.6
|
||
+++ ./gdb/testsuite/gdb.threads/schedlock.exp 17 Sep 2007 15:38:05 -0000 1.7
|
||
@@ -32,6 +32,9 @@ set testfile "schedlock"
|
||
set srcfile ${testfile}.c
|
||
set binfile ${objdir}/${subdir}/${testfile}
|
||
|
||
+# The number of threads, including the main thread.
|
||
+set NUM 2
|
||
+
|
||
if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
|
||
return -1
|
||
}
|
||
@@ -44,11 +47,11 @@ proc get_args { } {
|
||
|
||
send_gdb "print args\n"
|
||
gdb_expect {
|
||
- -re "\\\$\[0-9\]+ = {(\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+), (\[0-9\]+)}.*$gdb_prompt"
|
||
+ -re "\\\$\[0-9\]+ = {(\[0-9\]+), (\[0-9\]+)}.*$gdb_prompt"
|
||
{
|
||
set list_count [expr $list_count + 1]
|
||
pass "listed args ($list_count)"
|
||
- return [list $expect_out(1,string) $expect_out(2,string) $expect_out(3,string) $expect_out(4,string) $expect_out(5,string) $expect_out(6,string)]
|
||
+ return [list $expect_out(1,string) $expect_out(2,string)]
|
||
}
|
||
-re "$gdb_prompt"
|
||
{
|
||
@@ -112,7 +115,7 @@ proc my_continue { msg } {
|
||
stop_process "stop all threads ($msg)"
|
||
|
||
# Make sure we're in one of the non-main looping threads.
|
||
- gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 5"]
|
||
+ gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"]
|
||
gdb_continue_to_breakpoint "return to loop ($msg)"
|
||
delete_breakpoints
|
||
}
|
||
@@ -198,13 +201,17 @@ my_continue "initial"
|
||
|
||
set cont_args [get_args]
|
||
|
||
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
|
||
+set ok 1
|
||
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
|
||
if {[lindex $start_args $i] == [lindex $cont_args $i]} {
|
||
- fail "thread $i ran (didn't run)"
|
||
- } else {
|
||
- pass "thread $i ran"
|
||
+ set ok 0
|
||
}
|
||
}
|
||
+if { $ok } {
|
||
+ pass "all threads alive"
|
||
+} else {
|
||
+ fail "all threads alive"
|
||
+}
|
||
|
||
# We can't change threads, unfortunately, in current GDB. Use
|
||
# whichever we stopped in.
|
||
@@ -230,7 +237,7 @@ set start_args $cont_args
|
||
set cont_args [get_args]
|
||
|
||
set num_other_threads 0
|
||
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
|
||
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
|
||
if {[lindex $start_args $i] == [lindex $cont_args $i]} {
|
||
if {$i == $curthread} {
|
||
fail "current thread stepped (didn't run)"
|
||
@@ -248,9 +255,9 @@ for {set i 0} {[expr $i < 6]} {set i [ex
|
||
}
|
||
}
|
||
if {$num_other_threads > 0} {
|
||
- pass "other threads ran (1)"
|
||
+ pass "other threads ran - unlocked"
|
||
} else {
|
||
- fail "other threads ran (no other threads ran) (1)"
|
||
+ fail "other threads ran - unlocked"
|
||
}
|
||
|
||
# Test continue with scheduler locking
|
||
@@ -269,21 +276,25 @@ if {$curthread == $newthread} {
|
||
set start_args $cont_args
|
||
set cont_args [get_args]
|
||
|
||
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
|
||
+set num_other_threads 0
|
||
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
|
||
if {[lindex $start_args $i] == [lindex $cont_args $i]} {
|
||
if {$i == $curthread} {
|
||
fail "current thread ran (didn't run)"
|
||
- } else {
|
||
- pass "other thread $i didn't run"
|
||
}
|
||
} else {
|
||
if {$i == $curthread} {
|
||
pass "current thread ran"
|
||
} else {
|
||
- fail "other thread $i didn't run (ran)"
|
||
+ incr num_other_threads
|
||
}
|
||
}
|
||
}
|
||
+if {$num_other_threads > 0} {
|
||
+ fail "other threads didn't run - locked"
|
||
+} else {
|
||
+ pass "other threads didn't run - locked"
|
||
+}
|
||
|
||
# Test stepping with scheduler locking
|
||
step_ten_loops "locked"
|
||
@@ -299,12 +310,11 @@ if {$curthread == $newthread} {
|
||
set start_args $cont_args
|
||
set cont_args [get_args]
|
||
|
||
-for {set i 0} {[expr $i < 6]} {set i [expr $i + 1]} {
|
||
+set num_other_threads 0
|
||
+for {set i 0} {[expr $i < $NUM]} {set i [expr $i + 1]} {
|
||
if {[lindex $start_args $i] == [lindex $cont_args $i]} {
|
||
if {$i == $curthread} {
|
||
fail "current thread stepped locked (didn't run)"
|
||
- } else {
|
||
- pass "other thread $i didn't run (stepping)"
|
||
}
|
||
} else {
|
||
if {$i == $curthread} {
|
||
@@ -314,9 +324,14 @@ for {set i 0} {[expr $i < 6]} {set i [ex
|
||
fail "current thread stepped locked (wrong amount)"
|
||
}
|
||
} else {
|
||
- fail "other thread $i didn't run (stepping) (ran)"
|
||
+ incr num_other_threads
|
||
}
|
||
}
|
||
}
|
||
+if {$num_other_threads > 0} {
|
||
+ fail "other threads didn't run - step locked"
|
||
+} else {
|
||
+ pass "other threads didn't run - step locked"
|
||
+}
|
||
|
||
return 0
|
||
--- ./gdb/testsuite/gdb.threads/schedlock.c 23 Aug 2007 18:08:50 -0000 1.7
|
||
+++ ./gdb/testsuite/gdb.threads/schedlock.c 17 Sep 2007 15:38:05 -0000 1.8
|
||
@@ -22,7 +22,7 @@
|
||
|
||
void *thread_function(void *arg); /* Pointer to function executed by each thread */
|
||
|
||
-#define NUM 5
|
||
+#define NUM 1
|
||
|
||
unsigned int args[NUM+1];
|
||
|
||
@@ -32,7 +32,7 @@ int main() {
|
||
void *thread_result;
|
||
long i;
|
||
|
||
- for (i = 0; i < NUM; i++)
|
||
+ for (i = 1; i <= NUM; i++)
|
||
{
|
||
args[i] = 1;
|
||
res = pthread_create(&threads[i],
|
||
@@ -42,8 +42,8 @@ int main() {
|
||
}
|
||
|
||
/* schedlock.exp: last thread start. */
|
||
- args[i] = 1;
|
||
- thread_function ((void *) i);
|
||
+ args[0] = 1;
|
||
+ thread_function ((void *) 0);
|
||
|
||
exit(EXIT_SUCCESS);
|
||
}
|
||
|
||
2007-12-10 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
* lib/gdb.exp (build_id_debug_filename_get): OBJCOPY pipe being read
|
||
must be set to binary.
|
||
|
||
--- ./gdb/testsuite/lib/gdb.exp 9 Dec 2007 11:21:21 -0000 1.93
|
||
+++ ./gdb/testsuite/lib/gdb.exp 10 Dec 2007 00:14:55 -0000
|
||
@@ -2500,6 +2500,7 @@ proc build_id_debug_filename_get { exec
|
||
return ""
|
||
}
|
||
set fi [open $tmp]
|
||
+ fconfigure $fi -translation binary
|
||
# Skip the NOTE header.
|
||
read $fi 16
|
||
set data [read $fi]
|