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:
Gary Benson 2011-10-12 15:43:49 +00:00
parent ecf8e7f5f6
commit 0574c78f39
4 changed files with 79 additions and 1 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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) */

View File

@ -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