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.
This commit is contained in:
Bernd Edlinger 2019-10-18 14:28:45 +02:00 committed by Simon Marchi
parent 43a599b56c
commit 4a4c04f1f4
3 changed files with 75 additions and 5 deletions

View 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.

View 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);

View 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);