aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2019-10-18 14:28:45 +0200
committerSimon Marchi <simon.marchi@polymtl.ca>2019-12-16 21:02:22 -0500
commit4a4c04f1f4a926f986a77e72277c16e1b90c2b73 (patch)
treeb01e7e192667a386842233108969fa735a7166ac /gdb
parent43a599b56c6651aad9f21a6e38d99a029e28440b (diff)
downloadgdb-4a4c04f1f4a926f986a77e72277c16e1b90c2b73.zip
gdb-4a4c04f1f4a926f986a77e72277c16e1b90c2b73.tar.gz
gdb-4a4c04f1f4a926f986a77e72277c16e1b90c2b73.tar.bz2
Check all inline frames if they are marked for skip
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.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/infcmd.c20
-rw-r--r--gdb/infrun.c54
3 files changed, 75 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fa3f0a6..6f193c3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 2a25346..af66eaf 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -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);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6a346d6..7ddd21d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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);