mirror of https://github.com/xemu-project/xemu.git
replay: allow runstate shutdown->running when replaying trace
When replaying a trace, it is possible to go from shutdown to running with a reverse-debugging step. This can be useful if the problem being debugged triggers a reset or shutdown. This can be tested by making a recording of a machine that shuts down, then using -action shutdown=pause when replaying it. Continuing to the end of the trace then reverse-stepping in gdb crashes due to invalid runstate transition. Just permitting the transition seems to be all that's necessary for reverse-debugging to work well in such a state. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru> Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Message-Id: <20240813050638.446172-5-npiggin@gmail.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20240813202329.1237572-13-alex.bennee@linaro.org>
This commit is contained in:
parent
4926b6e644
commit
9dbab31d9e
|
@ -9,6 +9,7 @@ void runstate_set(RunState new_state);
|
|||
RunState runstate_get(void);
|
||||
bool runstate_is_running(void);
|
||||
bool runstate_needs_reset(void);
|
||||
void runstate_replay_enable(void);
|
||||
|
||||
typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);
|
||||
|
||||
|
|
|
@ -385,6 +385,8 @@ static void replay_enable(const char *fname, int mode)
|
|||
replay_fetch_data_kind();
|
||||
}
|
||||
|
||||
runstate_replay_enable();
|
||||
|
||||
replay_init_events();
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,12 @@ static const RunStateTransition runstate_transitions_def[] = {
|
|||
{ RUN_STATE__MAX, RUN_STATE__MAX },
|
||||
};
|
||||
|
||||
static const RunStateTransition replay_play_runstate_transitions_def[] = {
|
||||
{ RUN_STATE_SHUTDOWN, RUN_STATE_RUNNING},
|
||||
|
||||
{ RUN_STATE__MAX, RUN_STATE__MAX },
|
||||
};
|
||||
|
||||
static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
|
||||
|
||||
bool runstate_check(RunState state)
|
||||
|
@ -188,14 +194,33 @@ bool runstate_check(RunState state)
|
|||
return current_run_state == state;
|
||||
}
|
||||
|
||||
static void runstate_init(void)
|
||||
static void transitions_set_valid(const RunStateTransition *rst)
|
||||
{
|
||||
const RunStateTransition *p;
|
||||
|
||||
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
|
||||
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
|
||||
for (p = rst; p->from != RUN_STATE__MAX; p++) {
|
||||
runstate_valid_transitions[p->from][p->to] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void runstate_replay_enable(void)
|
||||
{
|
||||
assert(replay_mode != REPLAY_MODE_NONE);
|
||||
|
||||
if (replay_mode == REPLAY_MODE_PLAY) {
|
||||
/*
|
||||
* When reverse-debugging, it is possible to move state from
|
||||
* shutdown to running.
|
||||
*/
|
||||
transitions_set_valid(&replay_play_runstate_transitions_def[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void runstate_init(void)
|
||||
{
|
||||
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
|
||||
|
||||
transitions_set_valid(&runstate_transitions_def[0]);
|
||||
|
||||
qemu_mutex_init(&vmstop_lock);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue