2011-10-12 Gary Benson <gbenson@redhat.com>
* breakpoint.h (pc_at_non_inline_function): Declare. * breakpoint.c (is_non_inline_function, pc_at_non_inline_function): New functions. * infrun.c (handle_inferior_event): Don't call skip_inline_frames if the stop is at a location where functions cannot be inlined.
This commit is contained in:
parent
ecf8e7f5f6
commit
0574c78f39
4 changed files with 79 additions and 1 deletions
|
@ -1,3 +1,11 @@
|
|||
2011-10-12 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* breakpoint.h (pc_at_non_inline_function): Declare.
|
||||
* breakpoint.c (is_non_inline_function,
|
||||
pc_at_non_inline_function): New functions.
|
||||
* infrun.c (handle_inferior_event): Don't call skip_inline_frames
|
||||
if the stop is at a location where functions cannot be inlined.
|
||||
|
||||
2011-10-12 Pedro Alves <pedro@codesourcery.com>
|
||||
|
||||
* linux-nat.c (stop_and_resume_callback): Don't re-resume LWPs if
|
||||
|
|
|
@ -13325,6 +13325,45 @@ iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *),
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Zero if any of the breakpoint's locations could be a location where
|
||||
functions have been inlined, nonzero otherwise. */
|
||||
|
||||
static int
|
||||
is_non_inline_function (struct breakpoint *b)
|
||||
{
|
||||
/* The shared library event breakpoint is set on the address of a
|
||||
non-inline function. */
|
||||
if (b->type == bp_shlib_event)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nonzero if the specified PC cannot be a location where functions
|
||||
have been inlined. */
|
||||
|
||||
int
|
||||
pc_at_non_inline_function (struct address_space *aspace, CORE_ADDR pc)
|
||||
{
|
||||
struct breakpoint *b;
|
||||
struct bp_location *bl;
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
{
|
||||
if (!is_non_inline_function (b))
|
||||
continue;
|
||||
|
||||
for (bl = b->loc; bl != NULL; bl = bl->next)
|
||||
{
|
||||
if (!bl->shlib_disabled
|
||||
&& bpstat_check_location (bl, aspace, pc))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
initialize_breakpoint_ops (void)
|
||||
{
|
||||
|
|
|
@ -1357,6 +1357,12 @@ extern void end_rbreak_breakpoints (void);
|
|||
extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
|
||||
void *), void *);
|
||||
|
||||
/* Nonzero if the specified PC cannot be a location where functions
|
||||
have been inlined. */
|
||||
|
||||
extern int pc_at_non_inline_function (struct address_space *aspace,
|
||||
CORE_ADDR pc);
|
||||
|
||||
extern int user_breakpoint_p (struct breakpoint *);
|
||||
|
||||
#endif /* !defined (BREAKPOINT_H) */
|
||||
|
|
27
gdb/infrun.c
27
gdb/infrun.c
|
@ -4044,7 +4044,32 @@ handle_inferior_event (struct execution_control_state *ecs)
|
|||
nexti. After stepi and nexti, always show the innermost frame (not any
|
||||
inline function call sites). */
|
||||
if (ecs->event_thread->control.step_range_end != 1)
|
||||
skip_inline_frames (ecs->ptid);
|
||||
{
|
||||
struct address_space *aspace =
|
||||
get_regcache_aspace (get_thread_regcache (ecs->ptid));
|
||||
|
||||
/* skip_inline_frames is expensive, so we avoid it if we can
|
||||
determine that the address is one where functions cannot have
|
||||
been inlined. This improves performance with inferiors that
|
||||
load a lot of shared libraries, because the solib event
|
||||
breakpoint is defined as the address of a function (i.e. not
|
||||
inline). Note that we have to check the previous PC as well
|
||||
as the current one to catch cases when we have just
|
||||
single-stepped off a breakpoint prior to reinstating it.
|
||||
Note that we're assuming that the code we single-step to is
|
||||
not inline, but that's not definitive: there's nothing
|
||||
preventing the event breakpoint function from containing
|
||||
inlined code, and the single-step ending up there. If the
|
||||
user had set a breakpoint on that inlined code, the missing
|
||||
skip_inline_frames call would break things. Fortunately
|
||||
that's an extremely unlikely scenario. */
|
||||
if (!pc_at_non_inline_function (aspace, stop_pc)
|
||||
&& !(ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
|
||||
&& ecs->event_thread->control.trap_expected
|
||||
&& pc_at_non_inline_function (aspace,
|
||||
ecs->event_thread->prev_pc)))
|
||||
skip_inline_frames (ecs->ptid);
|
||||
}
|
||||
|
||||
if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
|
||||
&& ecs->event_thread->control.trap_expected
|
||||
|
|
Loading…
Reference in a new issue