2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>

Tom Tromey  <tromey@redhat.com>

	* breakpoint.c (struct breakpoint_objfile_data)
	<longjmp_searched>,<longjmp_probes>,<exception_searched>,
	<exception_probes>: New fields.
	(free_breakpoint_probes): New function.
	(create_longjmp_master_breakpoint): Prefer SystemTap probe over
	`_Unwind_DebugHook'.
	(create_exception_master_breakpoint): Likewise.
	(_initialize_breakpoint): Registering cleanup for SystemTap probes.
	* infrun.c: Including necessary header files for handling SystemTap
	probes.
	(handle_inferior_event): Handling longjmp breakpoint and exceptions
	via SystemTap probes.
	(check_exception_resume): Remove `func' argument.  Handle exception
	unwinding breakpoint set via a SystemTap probe.
	(insert_exception_resume_from_probe): New function.
This commit is contained in:
Sergio Durigan Junior 2012-04-27 20:48:57 +00:00
parent 55aa24fb2e
commit 28106bc2fe
3 changed files with 171 additions and 11 deletions

View file

@ -1,3 +1,22 @@
2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>
Tom Tromey <tromey@redhat.com>
* breakpoint.c (struct breakpoint_objfile_data)
<longjmp_searched>,<longjmp_probes>,<exception_searched>,
<exception_probes>: New fields.
(free_breakpoint_probes): New function.
(create_longjmp_master_breakpoint): Prefer SystemTap probe over
`_Unwind_DebugHook'.
(create_exception_master_breakpoint): Likewise.
(_initialize_breakpoint): Registering cleanup for SystemTap probes.
* infrun.c: Including necessary header files for handling SystemTap
probes.
(handle_inferior_event): Handling longjmp breakpoint and exceptions
via SystemTap probes.
(check_exception_resume): Remove `func' argument. Handle exception
unwinding breakpoint set via a SystemTap probe.
(insert_exception_resume_from_probe): New function.
2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com> 2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>
Tom Tromey <tromey@redhat.com> Tom Tromey <tromey@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com> Jan Kratochvil <jan.kratochvil@redhat.com>

View file

@ -2744,11 +2744,23 @@ struct breakpoint_objfile_data
/* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */ /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES]; struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES];
/* True if we have looked for longjmp probes. */
int longjmp_searched;
/* SystemTap probe points for longjmp (if any). */
VEC (probe_p) *longjmp_probes;
/* Minimal symbol for "std::terminate()" (if any). */ /* Minimal symbol for "std::terminate()" (if any). */
struct minimal_symbol *terminate_msym; struct minimal_symbol *terminate_msym;
/* Minimal symbol for "_Unwind_DebugHook" (if any). */ /* Minimal symbol for "_Unwind_DebugHook" (if any). */
struct minimal_symbol *exception_msym; struct minimal_symbol *exception_msym;
/* True if we have looked for exception probes. */
int exception_searched;
/* SystemTap probe points for unwinding (if any). */
VEC (probe_p) *exception_probes;
}; };
static const struct objfile_data *breakpoint_objfile_key; static const struct objfile_data *breakpoint_objfile_key;
@ -2784,6 +2796,15 @@ get_breakpoint_objfile_data (struct objfile *objfile)
return bp_objfile_data; return bp_objfile_data;
} }
static void
free_breakpoint_probes (struct objfile *obj, void *data)
{
struct breakpoint_objfile_data *bp_objfile_data = data;
VEC_free (probe_p, bp_objfile_data->longjmp_probes);
VEC_free (probe_p, bp_objfile_data->exception_probes);
}
static void static void
create_overlay_event_breakpoint (void) create_overlay_event_breakpoint (void)
{ {
@ -2861,6 +2882,37 @@ create_longjmp_master_breakpoint (void)
bp_objfile_data = get_breakpoint_objfile_data (objfile); bp_objfile_data = get_breakpoint_objfile_data (objfile);
if (!bp_objfile_data->longjmp_searched)
{
bp_objfile_data->longjmp_probes
= find_probes_in_objfile (objfile, "libc", "longjmp");
bp_objfile_data->longjmp_searched = 1;
}
if (bp_objfile_data->longjmp_probes != NULL)
{
int i;
struct probe *probe;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
for (i = 0;
VEC_iterate (probe_p,
bp_objfile_data->longjmp_probes,
i, probe);
++i)
{
struct breakpoint *b;
b = create_internal_breakpoint (gdbarch, probe->address,
bp_longjmp_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup ("-probe-stap libc:longjmp");
b->enable_state = bp_disabled;
}
continue;
}
for (i = 0; i < NUM_LONGJMP_NAMES; i++) for (i = 0; i < NUM_LONGJMP_NAMES; i++)
{ {
struct breakpoint *b; struct breakpoint *b;
@ -2971,6 +3023,40 @@ create_exception_master_breakpoint (void)
bp_objfile_data = get_breakpoint_objfile_data (objfile); bp_objfile_data = get_breakpoint_objfile_data (objfile);
/* We prefer the SystemTap probe point if it exists. */
if (!bp_objfile_data->exception_searched)
{
bp_objfile_data->exception_probes
= find_probes_in_objfile (objfile, "libgcc", "unwind");
bp_objfile_data->exception_searched = 1;
}
if (bp_objfile_data->exception_probes != NULL)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
int i;
struct probe *probe;
for (i = 0;
VEC_iterate (probe_p,
bp_objfile_data->exception_probes,
i, probe);
++i)
{
struct breakpoint *b;
b = create_internal_breakpoint (gdbarch, probe->address,
bp_exception_master,
&internal_breakpoint_ops);
b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
b->enable_state = bp_disabled;
}
continue;
}
/* Otherwise, try the hook function. */
if (msym_not_found_p (bp_objfile_data->exception_msym)) if (msym_not_found_p (bp_objfile_data->exception_msym))
continue; continue;

View file

@ -55,6 +55,8 @@
#include "continuations.h" #include "continuations.h"
#include "interps.h" #include "interps.h"
#include "skip.h" #include "skip.h"
#include "probe.h"
#include "objfiles.h"
/* Prototypes for local functions */ /* Prototypes for local functions */
@ -2402,7 +2404,7 @@ static void handle_step_into_function (struct gdbarch *gdbarch,
static void handle_step_into_function_backward (struct gdbarch *gdbarch, static void handle_step_into_function_backward (struct gdbarch *gdbarch,
struct execution_control_state *ecs); struct execution_control_state *ecs);
static void check_exception_resume (struct execution_control_state *, static void check_exception_resume (struct execution_control_state *,
struct frame_info *, struct symbol *); struct frame_info *);
static void stop_stepping (struct execution_control_state *ecs); static void stop_stepping (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs);
@ -4437,7 +4439,15 @@ process_event_stop_test:
if (what.is_longjmp) if (what.is_longjmp)
{ {
if (!gdbarch_get_longjmp_target_p (gdbarch) struct value *arg_value;
/* If we set the longjmp breakpoint via a SystemTap probe,
then use it to extract the arguments. The destination
PC is the third argument to the probe. */
arg_value = probe_safe_evaluate_at_pc (frame, 2);
if (arg_value)
jmp_buf_pc = value_as_address (arg_value);
else if (!gdbarch_get_longjmp_target_p (gdbarch)
|| !gdbarch_get_longjmp_target (gdbarch, || !gdbarch_get_longjmp_target (gdbarch,
frame, &jmp_buf_pc)) frame, &jmp_buf_pc))
{ {
@ -4457,12 +4467,7 @@ process_event_stop_test:
insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc); insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
} }
else else
{ check_exception_resume (ecs, frame);
struct symbol *func = get_frame_function (frame);
if (func)
check_exception_resume (ecs, frame, func);
}
keep_going (ecs); keep_going (ecs);
return; return;
@ -5552,15 +5557,65 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
} }
} }
/* A helper for check_exception_resume that sets an
exception-breakpoint based on a SystemTap probe. */
static void
insert_exception_resume_from_probe (struct thread_info *tp,
const struct probe *probe,
struct objfile *objfile,
struct frame_info *frame)
{
struct value *arg_value;
CORE_ADDR handler;
struct breakpoint *bp;
arg_value = probe_safe_evaluate_at_pc (frame, 1);
if (!arg_value)
return;
handler = value_as_address (arg_value);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: exception resume at %s\n",
paddress (get_objfile_arch (objfile),
handler));
bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
handler, bp_exception_resume);
bp->thread = tp->num;
inferior_thread ()->control.exception_resume_breakpoint = bp;
}
/* This is called when an exception has been intercepted. Check to /* This is called when an exception has been intercepted. Check to
see whether the exception's destination is of interest, and if so, see whether the exception's destination is of interest, and if so,
set an exception resume breakpoint there. */ set an exception resume breakpoint there. */
static void static void
check_exception_resume (struct execution_control_state *ecs, check_exception_resume (struct execution_control_state *ecs,
struct frame_info *frame, struct symbol *func) struct frame_info *frame)
{ {
volatile struct gdb_exception e; volatile struct gdb_exception e;
struct objfile *objfile;
const struct probe *probe;
struct symbol *func;
/* First see if this exception unwinding breakpoint was set via a
SystemTap probe point. If so, the probe has two arguments: the
CFA and the HANDLER. We ignore the CFA, extract the handler, and
set a breakpoint there. */
probe = find_probe_by_pc (get_frame_pc (frame), &objfile);
if (probe)
{
insert_exception_resume_from_probe (ecs->event_thread, probe,
objfile, frame);
return;
}
func = get_frame_function (frame);
if (!func)
return;
TRY_CATCH (e, RETURN_MASK_ERROR) TRY_CATCH (e, RETURN_MASK_ERROR)
{ {