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);
|
RunState runstate_get(void);
|
||||||
bool runstate_is_running(void);
|
bool runstate_is_running(void);
|
||||||
bool runstate_needs_reset(void);
|
bool runstate_needs_reset(void);
|
||||||
|
void runstate_replay_enable(void);
|
||||||
|
|
||||||
typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);
|
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();
|
replay_fetch_data_kind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runstate_replay_enable();
|
||||||
|
|
||||||
replay_init_events();
|
replay_init_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,12 @@ static const RunStateTransition runstate_transitions_def[] = {
|
||||||
{ RUN_STATE__MAX, RUN_STATE__MAX },
|
{ 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];
|
static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
|
||||||
|
|
||||||
bool runstate_check(RunState state)
|
bool runstate_check(RunState state)
|
||||||
|
@ -188,14 +194,33 @@ bool runstate_check(RunState state)
|
||||||
return current_run_state == state;
|
return current_run_state == state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void runstate_init(void)
|
static void transitions_set_valid(const RunStateTransition *rst)
|
||||||
{
|
{
|
||||||
const RunStateTransition *p;
|
const RunStateTransition *p;
|
||||||
|
|
||||||
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
|
for (p = rst; p->from != RUN_STATE__MAX; p++) {
|
||||||
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
|
|
||||||
runstate_valid_transitions[p->from][p->to] = true;
|
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);
|
qemu_mutex_init(&vmstop_lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue