Check all inline frames if they are marked for skip
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Fri, 18 Oct 2019 12:28:45 +0000 (14:28 +0200)
committerSimon Marchi <simon.marchi@polymtl.ca>
Tue, 17 Dec 2019 02:02:22 +0000 (21:02 -0500)
This makes the skip command work in optimized builds, where skipped
functions may be inlined.  Previously that was only working when
stepping into a non-inlined function.

gdb/ChangeLog
gdb/infcmd.c
gdb/infrun.c

index fa3f0a689357b9c998b51177b89bdf4016e12228..6f193c378b633f8a0803c362901c8175e94fa5e1 100644 (file)
@@ -1,3 +1,9 @@
+2019-12-16  Bernd Edlinger  <bernd.edlinger@hotmail.de>
+
+       * infcmd.c (prepare_one_step): Step over skipped inline functions.
+       * infrun.c (inline_frame_is_marked_for_skip): New helper function.
+       (process_event_stop_test): Keep stepping over skipped inline functions.
+
 2019-12-16  Simon Marchi  <simon.marchi@polymtl.ca>
 
        * jit.c (struct gdb_block) <next>: Remove field.
index 2a253469e745774c468a194697d42f745e03c1a3..af66eaffd8a4d3813a9e8bb0a0586f9dea29e351 100644 (file)
@@ -52,6 +52,7 @@
 #include "thread-fsm.h"
 #include "top.h"
 #include "interps.h"
+#include "skip.h"
 #include "gdbsupport/gdb_optional.h"
 #include "source.h"
 #include "cli/cli-style.h"
@@ -1106,14 +1107,29 @@ prepare_one_step (struct step_command_fsm *sm)
              && inline_skipped_frames (tp))
            {
              ptid_t resume_ptid;
+             const char *fn = NULL;
+             symtab_and_line sal;
+             struct symbol *sym;
 
              /* Pretend that we've ran.  */
              resume_ptid = user_visible_resume_ptid (1);
              set_running (resume_ptid, 1);
 
              step_into_inline_frame (tp);
-             sm->count--;
-             return prepare_one_step (sm);
+
+             frame = get_current_frame ();
+             sal = find_frame_sal (frame);
+             sym = get_frame_function (frame);
+
+             if (sym != NULL)
+               fn = sym->print_name ();
+
+             if (sal.line == 0
+                 || !function_name_is_marked_for_skip (fn, sal))
+               {
+                 sm->count--;
+                 return prepare_one_step (sm);
+               }
            }
 
          pc = get_frame_pc (frame);
index 6a346d6aefe3f0bd3566a83be2c3a184c4598d0c..7ddd21dd09977c8340cb7037108789307481177d 100644 (file)
@@ -4034,6 +4034,45 @@ stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id)
   return 0;
 }
 
+/* Look for an inline frame that is marked for skip.
+   If PREV_FRAME is TRUE start at the previous frame,
+   otherwise start at the current frame.  Stop at the
+   first non-inline frame, or at the frame where the
+   step started.  */
+
+static bool
+inline_frame_is_marked_for_skip (bool prev_frame, struct thread_info *tp)
+{
+  struct frame_info *frame = get_current_frame ();
+
+  if (prev_frame)
+    frame = get_prev_frame (frame);
+
+  for (; frame != NULL; frame = get_prev_frame (frame))
+    {
+      const char *fn = NULL;
+      symtab_and_line sal;
+      struct symbol *sym;
+
+      if (frame_id_eq (get_frame_id (frame), tp->control.step_frame_id))
+       break;
+      if (get_frame_type (frame) != INLINE_FRAME)
+       break;
+
+      sal = find_frame_sal (frame);
+      sym = get_frame_function (frame);
+
+      if (sym != NULL)
+       fn = sym->print_name ();
+
+      if (sal.line != 0
+         && function_name_is_marked_for_skip (fn, sal))
+       return true;
+    }
+
+  return false;
+}
+
 /* If the event thread has the stop requested flag set, pretend it
    stopped for a GDB_SIGNAL_0 (i.e., as if it stopped due to
    target_stop).  */
@@ -6524,7 +6563,8 @@ process_event_stop_test (struct execution_control_state *ecs)
        tmp_sal = find_pc_line (ecs->stop_func_start, 0);
        if (tmp_sal.line != 0
            && !function_name_is_marked_for_skip (ecs->stop_func_name,
-                                                 tmp_sal))
+                                                 tmp_sal)
+           && !inline_frame_is_marked_for_skip (true, ecs->event_thread))
          {
            if (execution_direction == EXEC_REVERSE)
              handle_step_into_function_backward (gdbarch, ecs);
@@ -6690,7 +6730,14 @@ process_event_stop_test (struct execution_control_state *ecs)
 
          if (call_sal.line == ecs->event_thread->current_line
              && call_sal.symtab == ecs->event_thread->current_symtab)
-           step_into_inline_frame (ecs->event_thread);
+           {
+             step_into_inline_frame (ecs->event_thread);
+             if (inline_frame_is_marked_for_skip (false, ecs->event_thread))
+               {
+                 keep_going (ecs);
+                 return;
+               }
+           }
 
          end_stepping_range (ecs);
          return;
@@ -6724,7 +6771,8 @@ process_event_stop_test (struct execution_control_state *ecs)
        fprintf_unfiltered (gdb_stdlog,
                            "infrun: stepping through inlined function\n");
 
-      if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL)
+      if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL
+         || inline_frame_is_marked_for_skip (false, ecs->event_thread))
        keep_going (ecs);
       else
        end_stepping_range (ecs);