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 * 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 * 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 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 * 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 * 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 * 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 * 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 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", ""); + else if (header_of_multiple) + ui_out_field_string (uiout, "addr", ""); 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 * 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 * 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(), 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 * 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 + +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 . + +# 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 +using namespace std; + +template +void foo(T i) +{ + std::cout << "hi\n"; // set breakpoint here +} + +int main() +{ + foo(0); + foo(0); + foo(1); + foo(1); + foo(2); + foo(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 . + +# 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 \\(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 \\(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 \\(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 \\(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 \\(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)'" ".*" \ + "instantiation: set breakpoint" + + +gdb_run_cmd +gdb_expect { + -re ".*Breakpoint \[0-9\]+,.*foo \\(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 \\(i=1\\).*" \ + "instantiation: run to breakpoint 2" + 2007-09-26 Vladimir Prus * 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 * 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 * 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{}. +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{}. A breakpoint with several locations will +have @samp{} 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{} 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 + stop only if i==1 + breakpoint already hit 1 time +1.1 y 0x080486a2 in void foo() at t.cc:8 +1.2 y 0x080486ca in void foo() 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 * 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 * 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 * 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] http://sourceware.org/ml/gdb-patches/2007-12/msg00485.html http://sourceware.org/ml/gdb-cvs/2007-12/msg00166.html 2007-12-31 Daniel Jacobowitz * remote.c (unpack_nibble): Use fromhex. * symtab.c (find_line_common): Always set exact_match. =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.273 retrieving revision 1.274 diff -u -r1.273 -r1.274 --- src/gdb/remote.c 2007/12/07 15:02:12 1.273 +++ src/gdb/remote.c 2007/12/31 18:38:43 1.274 @@ -1353,7 +1353,7 @@ static char * unpack_nibble (char *buf, int *val) { - ishex (*buf++, val); + *val = fromhex (*buf++); return buf; } =================================================================== RCS file: /cvs/src/src/gdb/symtab.c,v retrieving revision 1.168 retrieving revision 1.169 diff -u -r1.168 -r1.169 --- src/gdb/symtab.c 2007/12/18 16:02:54 1.168 +++ src/gdb/symtab.c 2007/12/31 18:38:43 1.169 @@ -2424,6 +2424,8 @@ int best_index = -1; int best = 0; + *exact_match = 0; + if (lineno <= 0) return -1; if (l == 0) @@ -2449,8 +2451,6 @@ } /* If we got here, we didn't get an exact match. */ - - *exact_match = 0; return best_index; }