2011-10-12 Gary Benson <gbenson@redhat.com>
authorGary Benson <gary@redhat.com>
Wed, 12 Oct 2011 15:43:49 +0000 (15:43 +0000)
committerGary Benson <gary@redhat.com>
Wed, 12 Oct 2011 15:43:49 +0000 (15:43 +0000)
* 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.

gdb/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/infrun.c

index 83cbcf1d0f92f2f9abd18c6325c633c9021ef15a..be9a96d2a3c8c185231058ba580efb40be35025e 100644 (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
index 08ff69bc57396b9794fda6975c44926d1a5a951c..ba1b08fdb8fbaf15c3718f197556247d5419ef25 100644 (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)
 {
index 5e5d1b9028d5fb6a0956a4cd7dc4d89623b2e160..c2116e2fdf9b5d3c600972f65c8f515c48a0cae4 100644 (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) */
index cc2e29b8bd13b20217fab71627283938fd0ecc9b..db6a5d140f8bed9e02779441378a79450b901e01 100644 (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
This page took 0.038453 seconds and 4 git commands to generate.