mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
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:
@ -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>
|
2011-10-12 Pedro Alves <pedro@codesourcery.com>
|
||||||
|
|
||||||
* linux-nat.c (stop_and_resume_callback): Don't re-resume LWPs if
|
* 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;
|
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
|
void
|
||||||
initialize_breakpoint_ops (void)
|
initialize_breakpoint_ops (void)
|
||||||
{
|
{
|
||||||
|
@ -1357,6 +1357,12 @@ extern void end_rbreak_breakpoints (void);
|
|||||||
extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
|
extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
|
||||||
void *), void *);
|
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 *);
|
extern int user_breakpoint_p (struct breakpoint *);
|
||||||
|
|
||||||
#endif /* !defined (BREAKPOINT_H) */
|
#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
|
nexti. After stepi and nexti, always show the innermost frame (not any
|
||||||
inline function call sites). */
|
inline function call sites). */
|
||||||
if (ecs->event_thread->control.step_range_end != 1)
|
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
|
if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
|
||||||
&& ecs->event_thread->control.trap_expected
|
&& ecs->event_thread->control.trap_expected
|
||||||
|
Reference in New Issue
Block a user