2011-07-25 Pedro Alves <pedro@codesourcery.com>

Split internal, momentary and user breakpoints breakpoint_ops
	tables.

	gdb/
	* breakpoint.c (internal_breakpoint_ops)
	(momentary_breakpoint_ops): Forward declare.
	(create_internal_breakpoint): Add new breakpoint_ops parameter.
	Pass it down, rather than hardcoding bkpt_breakpoint_ops.
	(create_overlay_event_breakpoint)
	(create_std_terminate_master_breakpoint)
	(create_exception_master_breakpoint): Create breakpoints with
	internal_breakpoint_ops vtable.
	(set_longjmp_breakpoint): Create momentary breakpoints with
	momentary_breakpoint_ops vtable, using
	momentary_breakpoint_from_master.
	(create_thread_event_breakpoint, create_jit_event_breakpoint)
	(create_solib_event_breakpoint): Create breakpoints with
	internal_breakpoint_ops vtable.
	(set_momentary_breakpoint): Create breakpoints with
	momentary_breakpoint_ops vtable.
	(momentary_breakpoint_from_master): New, factored out from
	clone_momentary_breakpoint.
	(clone_momentary_breakpoint): Adjust.
	(watch_command_1): Create scope breakpoints with
	momentary_breakpoint_ops vtable.
	(bkpt_re_set): Remove handling of internal and momentary
	breakpoints.
	(bkpt_print_mention, bkpt_print_recreate): New.
	(bkpt_breakpoint_ops): Adjust.
	(internal_bkpt_re_set, internal_bkpt_check_status)
	(internal_bkpt_print_it, internal_bkpt_print_mention)
	(internal_bkpt_print_recreate, internal_breakpoint_ops): New.
	(momentary_bkpt_re_set, momentary_bkpt_check_status)
	(momentary_bkpt_print_it, momentary_bkpt_print_mention)
	(momentary_bkpt_print_recreate): New.
	(momentary_breakpoint_ops): New.
This commit is contained in:
Pedro Alves 2011-07-25 11:19:26 +00:00
parent 348d480fa9
commit 06edf0c005
2 changed files with 340 additions and 187 deletions

View File

@ -1,3 +1,41 @@
2011-07-25 Pedro Alves <pedro@codesourcery.com>
Split internal, momentary and user breakpoints breakpoint_ops
tables.
* breakpoint.c (internal_breakpoint_ops)
(momentary_breakpoint_ops): Forward declare.
(create_internal_breakpoint): Add new breakpoint_ops parameter.
Pass it down, rather than hardcoding bkpt_breakpoint_ops.
(create_overlay_event_breakpoint)
(create_std_terminate_master_breakpoint)
(create_exception_master_breakpoint): Create breakpoints with
internal_breakpoint_ops vtable.
(set_longjmp_breakpoint): Create momentary breakpoints with
momentary_breakpoint_ops vtable, using
momentary_breakpoint_from_master.
(create_thread_event_breakpoint, create_jit_event_breakpoint)
(create_solib_event_breakpoint): Create breakpoints with
internal_breakpoint_ops vtable.
(set_momentary_breakpoint): Create breakpoints with
momentary_breakpoint_ops vtable.
(momentary_breakpoint_from_master): New, factored out from
clone_momentary_breakpoint.
(clone_momentary_breakpoint): Adjust.
(watch_command_1): Create scope breakpoints with
momentary_breakpoint_ops vtable.
(bkpt_re_set): Remove handling of internal and momentary
breakpoints.
(bkpt_print_mention, bkpt_print_recreate): New.
(bkpt_breakpoint_ops): Adjust.
(internal_bkpt_re_set, internal_bkpt_check_status)
(internal_bkpt_print_it, internal_bkpt_print_mention)
(internal_bkpt_print_recreate, internal_breakpoint_ops): New.
(momentary_bkpt_re_set, momentary_bkpt_check_status)
(momentary_bkpt_print_it, momentary_bkpt_print_mention)
(momentary_bkpt_print_recreate): New.
(momentary_breakpoint_ops): New.
2011-07-25 Pedro Alves <pedro@codesourcery.com>
Implement most breakpoint_ops methods for all breakpoint types,

View File

@ -115,6 +115,11 @@ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch,
struct symtab_and_line,
enum bptype, struct breakpoint_ops *);
static struct breakpoint *
momentary_breakpoint_from_master (struct breakpoint *orig,
enum bptype type,
struct breakpoint_ops *ops);
static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
@ -231,6 +236,10 @@ static int is_masked_watchpoint (const struct breakpoint *b);
#define is_marker_spec(s) \
(s != NULL && strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t'))
/* Forward declarations. */
static struct breakpoint_ops internal_breakpoint_ops;
static struct breakpoint_ops momentary_breakpoint_ops;
/* A reference-counted struct command_line. This lets multiple
breakpoints share a single command list. */
struct counted_command_line
@ -2066,7 +2075,8 @@ set_breakpoint_number (int internal, struct breakpoint *b)
static struct breakpoint *
create_internal_breakpoint (struct gdbarch *gdbarch,
CORE_ADDR address, enum bptype type)
CORE_ADDR address, enum bptype type,
struct breakpoint_ops *ops)
{
struct symtab_and_line sal;
struct breakpoint *b;
@ -2077,7 +2087,7 @@ create_internal_breakpoint (struct gdbarch *gdbarch,
sal.section = find_pc_overlay (sal.pc);
sal.pspace = current_program_space;
b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops);
b = set_raw_breakpoint (gdbarch, sal, type, ops);
b->number = internal_breakpoint_number--;
b->disposition = disp_donttouch;
@ -2172,7 +2182,8 @@ create_overlay_event_breakpoint (void)
addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event);
bp_overlay_event,
&internal_breakpoint_ops);
b->addr_string = xstrdup (func_name);
if (overlay_debugging == ovly_auto)
@ -2240,7 +2251,8 @@ create_longjmp_master_breakpoint (void)
}
addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master);
b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup (func_name);
b->enable_state = bp_disabled;
}
@ -2295,7 +2307,8 @@ create_std_terminate_master_breakpoint (void)
addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master);
bp_std_terminate_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup (func_name);
b->enable_state = bp_disabled;
}
@ -2345,7 +2358,8 @@ create_exception_master_breakpoint (void)
addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
&current_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup (func_name);
b->enable_state = bp_disabled;
}
@ -5728,9 +5742,11 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
&& (b->type == bp_longjmp_master
|| b->type == bp_exception_master))
{
struct breakpoint *clone = clone_momentary_breakpoint (b);
enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
struct breakpoint *clone;
clone->type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
clone = momentary_breakpoint_from_master (b, type,
&momentary_breakpoint_ops);
clone->thread = thread;
}
@ -5790,8 +5806,8 @@ set_std_terminate_breakpoint (void)
if (b->pspace == current_program_space
&& b->type == bp_std_terminate_master)
{
struct breakpoint *clone = clone_momentary_breakpoint (b);
clone->type = bp_std_terminate;
momentary_breakpoint_from_master (b, bp_std_terminate,
&momentary_breakpoint_ops);
}
}
@ -5811,8 +5827,9 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
struct breakpoint *b;
b = create_internal_breakpoint (gdbarch, address, bp_thread_event);
b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
&internal_breakpoint_ops);
b->enable_state = bp_enabled;
/* addr_string has to be used or breakpoint_re_set will delete me. */
b->addr_string
@ -5847,7 +5864,8 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
struct breakpoint *b;
b = create_internal_breakpoint (gdbarch, address, bp_jit_event);
b = create_internal_breakpoint (gdbarch, address, bp_jit_event,
&internal_breakpoint_ops);
update_global_location_list_nothrow (1);
return b;
}
@ -5881,7 +5899,8 @@ create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
{
struct breakpoint *b;
b = create_internal_breakpoint (gdbarch, address, bp_shlib_event);
b = create_internal_breakpoint (gdbarch, address, bp_shlib_event,
&internal_breakpoint_ops);
update_global_location_list_nothrow (1);
return b;
}
@ -6880,7 +6899,7 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
one. */
gdb_assert (!frame_id_inlined_p (frame_id));
b = set_raw_breakpoint (gdbarch, sal, type, &bkpt_breakpoint_ops);
b = set_raw_breakpoint (gdbarch, sal, type, &momentary_breakpoint_ops);
b->enable_state = bp_enabled;
b->disposition = disp_donttouch;
b->frame_id = frame_id;
@ -6896,20 +6915,18 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
return b;
}
/* Make a deep copy of momentary breakpoint ORIG. Returns NULL if
ORIG is NULL. */
/* Make a momentary breakpoint based on the master breakpoint ORIG.
The new breakpoint will have type TYPE, and use OPS as it
breakpoint_ops. */
struct breakpoint *
clone_momentary_breakpoint (struct breakpoint *orig)
static struct breakpoint *
momentary_breakpoint_from_master (struct breakpoint *orig,
enum bptype type,
struct breakpoint_ops *ops)
{
struct breakpoint *copy;
/* If there's nothing to clone, then return nothing. */
if (orig == NULL)
return NULL;
copy = set_raw_breakpoint_without_location (orig->gdbarch,
orig->type, orig->ops);
copy = set_raw_breakpoint_without_location (orig->gdbarch, type, ops);
copy->loc = allocate_bp_location (copy);
set_breakpoint_location_function (copy->loc, 1);
@ -6937,6 +6954,19 @@ clone_momentary_breakpoint (struct breakpoint *orig)
return copy;
}
/* Make a deep copy of momentary breakpoint ORIG. Returns NULL if
ORIG is NULL. */
struct breakpoint *
clone_momentary_breakpoint (struct breakpoint *orig)
{
/* If there's nothing to clone, then return nothing. */
if (orig == NULL)
return NULL;
return momentary_breakpoint_from_master (orig, orig->type, orig->ops);
}
struct breakpoint *
set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc,
enum bptype type)
@ -9121,7 +9151,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty,
scope_breakpoint
= create_internal_breakpoint (frame_unwind_caller_arch (frame),
frame_unwind_caller_pc (frame),
bp_watchpoint_scope);
bp_watchpoint_scope,
&momentary_breakpoint_ops);
scope_breakpoint->enable_state = bp_enabled;
@ -10676,66 +10707,19 @@ bkpt_allocate_location (struct breakpoint *self)
void
bkpt_re_set (struct breakpoint *b)
{
switch (b->type)
/* Do not attempt to re-set breakpoints disabled during startup. */
if (b->enable_state == bp_startup_disabled)
return;
/* FIXME: is this still reachable? */
if (b->addr_string == NULL)
{
case bp_breakpoint:
case bp_hardware_breakpoint:
case bp_gnu_ifunc_resolver:
/* Do not attempt to re-set breakpoints disabled during
startup. */
if (b->enable_state == bp_startup_disabled)
return;
if (b->addr_string == NULL)
{
/* Anything without a string can't be re-set. */
delete_breakpoint (b);
return;
}
breakpoint_re_set_default (b);
break;
default:
printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type);
/* fall through */
/* Delete overlay event and longjmp master breakpoints; they
will be reset later by breakpoint_re_set. */
case bp_overlay_event:
case bp_longjmp_master:
case bp_std_terminate_master:
case bp_exception_master:
/* Anything without a string can't be re-set. */
delete_breakpoint (b);
break;
/* This breakpoint is special, it's set up when the inferior
starts and we really don't want to touch it. */
case bp_shlib_event:
/* Like bp_shlib_event, this breakpoint type is special. Once
it is set up, we do not want to touch it. */
case bp_thread_event:
/* Keep temporary breakpoints, which can be encountered when we
step over a dlopen call and SOLIB_ADD is resetting the
breakpoints. Otherwise these should have been blown away via
the cleanup chain or by breakpoint_init_inferior when we
rerun the executable. */
case bp_until:
case bp_finish:
case bp_watchpoint_scope:
case bp_call_dummy:
case bp_std_terminate:
case bp_step_resume:
case bp_hp_step_resume:
case bp_longjmp:
case bp_longjmp_resume:
case bp_exception:
case bp_exception_resume:
case bp_jit_event:
case bp_gnu_ifunc_resolver_return:
break;
return;
}
breakpoint_re_set_default (b);
}
int
@ -10779,15 +10763,7 @@ bkpt_breakpoint_hit (const struct bp_location *bl,
void
bkpt_check_status (bpstat bs)
{
struct breakpoint *b = bs->breakpoint_at;
if (b->type == bp_thread_event
|| b->type == bp_overlay_event
|| b->type == bp_longjmp_master
|| b->type == bp_std_terminate_master
|| b->type == bp_exception_master)
/* We do not stop for these. */
bs->stop = 0;
/* nothing, always stop */
}
int
@ -10847,79 +10823,6 @@ bkpt_print_it (bpstat bs)
result = PRINT_SRC_AND_LOC;
break;
case bp_shlib_event:
/* Did we stop because the user set the stop_on_solib_events
variable? (If so, we report this as a generic, "Stopped due
to shlib event" message.) */
printf_filtered (_("Stopped due to shared library event\n"));
result = PRINT_NOTHING;
break;
case bp_thread_event:
/* Not sure how we will get here.
GDB should not stop for these breakpoints. */
printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_overlay_event:
/* By analogy with the thread event, GDB should not stop for these. */
printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_longjmp_master:
/* These should never be enabled. */
printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_std_terminate_master:
/* These should never be enabled. */
printf_filtered (_("std::terminate Master Breakpoint: "
"gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_exception_master:
/* These should never be enabled. */
printf_filtered (_("Exception Master Breakpoint: "
"gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
/* Fall through, we don't deal with these types of breakpoints
here. */
case bp_finish:
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
result = PRINT_UNKNOWN;
break;
case bp_until:
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
result = PRINT_UNKNOWN;
break;
case bp_none:
case bp_longjmp:
case bp_longjmp_resume:
case bp_exception:
case bp_exception_resume:
case bp_step_resume:
case bp_hp_step_resume:
case bp_watchpoint_scope:
case bp_call_dummy:
case bp_std_terminate:
case bp_jit_event:
case bp_gnu_ifunc_resolver:
case bp_gnu_ifunc_resolver_return:
default:
result = PRINT_UNKNOWN;
break;
@ -10946,33 +10849,13 @@ bkpt_print_mention (struct breakpoint *b)
printf_filtered (_(" %d"), b->number);
if (b->type == bp_gnu_ifunc_resolver)
printf_filtered (_(" at gnu-indirect-function resolver"));
say_where (b);
break;
case bp_hardware_breakpoint:
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
say_where (b);
break;
case bp_until:
case bp_finish:
case bp_longjmp:
case bp_longjmp_resume:
case bp_exception:
case bp_exception_resume:
case bp_step_resume:
case bp_hp_step_resume:
case bp_call_dummy:
case bp_std_terminate:
case bp_watchpoint_scope:
case bp_shlib_event:
case bp_thread_event:
case bp_overlay_event:
case bp_jit_event:
case bp_longjmp_master:
case bp_std_terminate_master:
case bp_exception_master:
case bp_gnu_ifunc_resolver_return:
break;
}
say_where (b);
}
void
@ -11024,6 +10907,238 @@ struct breakpoint_ops bkpt_breakpoint_ops =
bkpt_print_recreate
};
/* Virtual table for internal breakpoints. */
static void
internal_bkpt_re_set (struct breakpoint *b)
{
switch (b->type)
{
/* Delete overlay event and longjmp master breakpoints; they
will be reset later by breakpoint_re_set. */
case bp_overlay_event:
case bp_longjmp_master:
case bp_std_terminate_master:
case bp_exception_master:
delete_breakpoint (b);
break;
/* This breakpoint is special, it's set up when the inferior
starts and we really don't want to touch it. */
case bp_shlib_event:
/* Like bp_shlib_event, this breakpoint type is special. Once
it is set up, we do not want to touch it. */
case bp_thread_event:
break;
}
}
static void
internal_bkpt_check_status (bpstat bs)
{
/* We do not stop for these. */
bs->stop = 0;
}
static enum print_stop_action
internal_bkpt_print_it (bpstat bs)
{
struct cleanup *old_chain;
struct breakpoint *b;
const struct bp_location *bl;
struct ui_stream *stb;
int bp_temp = 0;
enum print_stop_action result;
gdb_assert (bs->bp_location_at != NULL);
bl = bs->bp_location_at;
b = bs->breakpoint_at;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
switch (b->type)
{
case bp_shlib_event:
/* Did we stop because the user set the stop_on_solib_events
variable? (If so, we report this as a generic, "Stopped due
to shlib event" message.) */
printf_filtered (_("Stopped due to shared library event\n"));
result = PRINT_NOTHING;
break;
case bp_thread_event:
/* Not sure how we will get here.
GDB should not stop for these breakpoints. */
printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_overlay_event:
/* By analogy with the thread event, GDB should not stop for these. */
printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_longjmp_master:
/* These should never be enabled. */
printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_std_terminate_master:
/* These should never be enabled. */
printf_filtered (_("std::terminate Master Breakpoint: "
"gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
case bp_exception_master:
/* These should never be enabled. */
printf_filtered (_("Exception Master Breakpoint: "
"gdb should not stop!\n"));
result = PRINT_NOTHING;
break;
default:
result = PRINT_UNKNOWN;
break;
}
do_cleanups (old_chain);
return result;
}
static void
internal_bkpt_print_mention (struct breakpoint *b)
{
/* Nothing to mention. These breakpoints are internal. */
}
static void
internal_bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
{
gdb_assert_not_reached ("internal_bkpt_print_recreate called");
}
/* The breakpoint_ops structure to be used with internal
breakpoints. */
static struct breakpoint_ops internal_breakpoint_ops =
{
bkpt_dtor,
bkpt_allocate_location,
internal_bkpt_re_set,
bkpt_insert_location,
bkpt_remove_location,
bkpt_breakpoint_hit,
internal_bkpt_check_status,
bkpt_resources_needed,
null_works_in_software_mode,
internal_bkpt_print_it,
NULL, /* print_one */
null_print_one_detail,
internal_bkpt_print_mention,
internal_bkpt_print_recreate
};
/* Virtual table for momentary breakpoints */
static void
momentary_bkpt_re_set (struct breakpoint *b)
{
/* Keep temporary breakpoints, which can be encountered when we step
over a dlopen call and SOLIB_ADD is resetting the breakpoints.
Otherwise these should have been blown away via the cleanup chain
or by breakpoint_init_inferior when we rerun the executable. */
}
static void
momentary_bkpt_check_status (bpstat bs)
{
/* Nothing. The point of these breakpoints is causing a stop. */
}
static enum print_stop_action
momentary_bkpt_print_it (bpstat bs)
{
struct cleanup *old_chain;
struct breakpoint *b;
const struct bp_location *bl;
struct ui_stream *stb;
int bp_temp = 0;
enum print_stop_action result;
gdb_assert (bs->bp_location_at != NULL);
bl = bs->bp_location_at;
b = bs->breakpoint_at;
stb = ui_out_stream_new (uiout);
old_chain = make_cleanup_ui_out_stream_delete (stb);
switch (b->type)
{
case bp_finish:
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
result = PRINT_UNKNOWN;
break;
case bp_until:
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED));
result = PRINT_UNKNOWN;
break;
default:
result = PRINT_UNKNOWN;
break;
}
do_cleanups (old_chain);
return result;
}
static void
momentary_bkpt_print_mention (struct breakpoint *b)
{
/* Nothing to mention. These breakpoints are internal. */
}
static void
momentary_bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
{
gdb_assert_not_reached ("momentary_bkpt_print_recreate called");
}
/* The breakpoint_ops structure to be used with momentary
breakpoints. */
static struct breakpoint_ops momentary_breakpoint_ops =
{
bkpt_dtor,
bkpt_allocate_location,
momentary_bkpt_re_set,
bkpt_insert_location,
bkpt_remove_location,
bkpt_breakpoint_hit,
momentary_bkpt_check_status,
bkpt_resources_needed,
null_works_in_software_mode,
momentary_bkpt_print_it,
NULL, /* print_one */
null_print_one_detail,
momentary_bkpt_print_mention,
momentary_bkpt_print_recreate
};
/* The breakpoint_ops structure to be used in tracepoints. */
static void