From: Gary Benson <gbenson@redhat.com>
To: Pedro Alves <pedro@codesourcery.com>
Cc: gdb-patches@sourceware.org
Subject: [commit] Improve performance with lots of shared libraries
Date: Wed, 12 Oct 2011 15:59:00 -0000 [thread overview]
Message-ID: <20111012155918.GA4216@redhat.com> (raw)
In-Reply-To: <201110111753.27321.pedro@codesourcery.com>
[-- Attachment #1: Type: text/plain, Size: 2989 bytes --]
Pedro Alves wrote:
> Thanks for extending the comment. The first check is quite
> definitive. The second is heuristic. There's nothing preventing
> the event breakpoint function to contain a bit of 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.
> But please do adjust the comment to mention that we assume the code
> the single-step takes us to after single-stepping is also not
> inlined.
>
> Also, let's not trust prev_pc unless we did finish a single-step:
>
> if (!stopped_at_non_inline_function (aspace, stop_pc)
> && !(ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP
> && ecs->event_thread->control.trap_expected
> && stopped_at_non_inline_function (aspace,
> ecs->event_thread->prev_pc))
>
> Please drop the "stopped" from the function's name. The prev_pc
> case clearly isn't about having stopped at prev_pc. Something like
> pc_at_non_inline_function would be better. It is just concerned
> with returning whether its passed in PC is known to point at a
> non-inlined location, whether the thread is currently stopped there
> or not.
>
> Okay with these changes.
Thanks, I made them and committed it (patch attached).
> To make this generic for all breakpoints/stops, what I have in mind
> would be:
>
> - at breakpoint creation or re-set time, check if the locations
> we've created point at inlined code, and set a flag in the
> breakpoint's locations. We know the location is inlined or not
> from the debug info. Breakpoint creation is the slow path, so
> that's okay.
>
> - given that we need to single-step over those breakpoints, we also
> need to know whether the PC after stepping over those breakpoints
> points at inlined code. I think we can still do that at
> breakpoint creation or re-set time. We'd need to reuse the
> software single-step machinery to know where the single-step
> would take us, and record somewhere that those locations point to
> inline code or not. We'd also check this list in
> stopped_at_non_inline_function. The software single-step
> machinery would need some cleaning up to make this possible.
> It's interface, gdbarch_software_single_step, isn't fit for this.
> The gdbarch hook should return a list of locations where to put
> the breakpoint, instead of implementations planting the
> breakpoints themselves, which would be a nice cleanup for other
> things too. We'd also need to implement this hook for x86. It's
> not implemented currently because x86 can do hardware
> single-stepping.
Ah, nice! Would it be appropriate to file a bug containing this
information? So it doesn't get lost before I have a chance to work
on it?
Thanks,
Gary
--
http://gbenson.net/
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 4827 bytes --]
Index: gdb/ChangeLog
===================================================================
RCS file: /cvs/src/src/gdb/ChangeLog,v
retrieving revision 1.13424
retrieving revision 1.13425
diff -u -r1.13424 -r1.13425
--- gdb/ChangeLog 12 Oct 2011 12:17:29 -0000 1.13424
+++ gdb/ChangeLog 12 Oct 2011 15:43:47 -0000 1.13425
@@ -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
Index: gdb/breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.615
retrieving revision 1.616
diff -u -r1.615 -r1.616
--- gdb/breakpoint.c 2 Oct 2011 02:13:12 -0000 1.615
+++ gdb/breakpoint.c 12 Oct 2011 15:43:48 -0000 1.616
@@ -13325,6 +13325,45 @@
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)
{
Index: gdb/breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.160
retrieving revision 1.161
diff -u -r1.160 -r1.161
--- gdb/breakpoint.h 26 Aug 2011 09:28:27 -0000 1.160
+++ gdb/breakpoint.h 12 Oct 2011 15:43:49 -0000 1.161
@@ -1357,6 +1357,12 @@
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) */
Index: gdb/infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.508
retrieving revision 1.509
diff -u -r1.508 -r1.509
--- gdb/infrun.c 7 Oct 2011 12:06:46 -0000 1.508
+++ gdb/infrun.c 12 Oct 2011 15:43:49 -0000 1.509
@@ -4044,7 +4044,32 @@
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
next prev parent reply other threads:[~2011-10-12 15:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-22 17:35 [RFA] " Gary Benson
2011-10-04 10:25 ` PING: " Gary Benson
2011-10-04 20:19 ` Tom Tromey
2011-10-07 15:02 ` Pedro Alves
2011-10-10 11:58 ` Gary Benson
2011-10-11 15:53 ` [RFA take 2] " Gary Benson
2011-10-11 16:53 ` Pedro Alves
2011-10-12 15:59 ` Gary Benson [this message]
2011-10-12 16:16 ` [commit] " Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20111012155918.GA4216@redhat.com \
--to=gbenson@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=pedro@codesourcery.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox