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:
parent
55aa24fb2e
commit
28106bc2fe
3 changed files with 171 additions and 11 deletions
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
73
gdb/infrun.c
73
gdb/infrun.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue