]>
Commit | Line | Data |
---|---|---|
e3b09ad2 PD |
1 | /* |
2 | * replay-debugging.c | |
3 | * | |
4 | * Copyright (c) 2010-2020 Institute for System Programming | |
5 | * of the Russian Academy of Sciences. | |
6 | * | |
7 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
8 | * See the COPYING file in the top-level directory. | |
9 | * | |
10 | */ | |
11 | ||
12 | #include "qemu/osdep.h" | |
13 | #include "qapi/error.h" | |
14 | #include "sysemu/replay.h" | |
e7510671 | 15 | #include "sysemu/runstate.h" |
e3b09ad2 PD |
16 | #include "replay-internal.h" |
17 | #include "monitor/hmp.h" | |
18 | #include "monitor/monitor.h" | |
19 | #include "qapi/qapi-commands-replay.h" | |
e7510671 PD |
20 | #include "qapi/qmp/qdict.h" |
21 | #include "qemu/timer.h" | |
e3b09ad2 PD |
22 | |
23 | void hmp_info_replay(Monitor *mon, const QDict *qdict) | |
24 | { | |
25 | if (replay_mode == REPLAY_MODE_NONE) { | |
26 | monitor_printf(mon, "Record/replay is not active\n"); | |
27 | } else { | |
28 | monitor_printf(mon, | |
29 | "%s execution '%s': instruction count = %"PRId64"\n", | |
30 | replay_mode == REPLAY_MODE_RECORD ? "Recording" : "Replaying", | |
31 | replay_get_filename(), replay_get_current_icount()); | |
32 | } | |
33 | } | |
34 | ||
35 | ReplayInfo *qmp_query_replay(Error **errp) | |
36 | { | |
37 | ReplayInfo *retval = g_new0(ReplayInfo, 1); | |
38 | ||
39 | retval->mode = replay_mode; | |
40 | if (replay_get_filename()) { | |
41 | retval->filename = g_strdup(replay_get_filename()); | |
42 | retval->has_filename = true; | |
43 | } | |
44 | retval->icount = replay_get_current_icount(); | |
45 | return retval; | |
46 | } | |
e7510671 PD |
47 | |
48 | static void replay_break(uint64_t icount, QEMUTimerCB callback, void *opaque) | |
49 | { | |
50 | assert(replay_mode == REPLAY_MODE_PLAY); | |
51 | assert(replay_mutex_locked()); | |
52 | assert(replay_break_icount >= replay_get_current_icount()); | |
53 | assert(callback); | |
54 | ||
55 | replay_break_icount = icount; | |
56 | ||
57 | if (replay_break_timer) { | |
58 | timer_del(replay_break_timer); | |
59 | } | |
60 | replay_break_timer = timer_new_ns(QEMU_CLOCK_REALTIME, | |
61 | callback, opaque); | |
62 | } | |
63 | ||
64 | static void replay_delete_break(void) | |
65 | { | |
66 | assert(replay_mode == REPLAY_MODE_PLAY); | |
67 | assert(replay_mutex_locked()); | |
68 | ||
69 | if (replay_break_timer) { | |
70 | timer_del(replay_break_timer); | |
71 | timer_free(replay_break_timer); | |
72 | replay_break_timer = NULL; | |
73 | } | |
74 | replay_break_icount = -1ULL; | |
75 | } | |
76 | ||
77 | static void replay_stop_vm(void *opaque) | |
78 | { | |
79 | vm_stop(RUN_STATE_PAUSED); | |
80 | replay_delete_break(); | |
81 | } | |
82 | ||
83 | void qmp_replay_break(int64_t icount, Error **errp) | |
84 | { | |
85 | if (replay_mode == REPLAY_MODE_PLAY) { | |
86 | if (icount >= replay_get_current_icount()) { | |
87 | replay_break(icount, replay_stop_vm, NULL); | |
88 | } else { | |
89 | error_setg(errp, | |
90 | "cannot set breakpoint at the instruction in the past"); | |
91 | } | |
92 | } else { | |
93 | error_setg(errp, "setting the breakpoint is allowed only in play mode"); | |
94 | } | |
95 | } | |
96 | ||
97 | void hmp_replay_break(Monitor *mon, const QDict *qdict) | |
98 | { | |
99 | int64_t icount = qdict_get_try_int(qdict, "icount", -1LL); | |
100 | Error *err = NULL; | |
101 | ||
102 | qmp_replay_break(icount, &err); | |
103 | if (err) { | |
104 | error_report_err(err); | |
105 | return; | |
106 | } | |
107 | } | |
108 | ||
109 | void qmp_replay_delete_break(Error **errp) | |
110 | { | |
111 | if (replay_mode == REPLAY_MODE_PLAY) { | |
112 | replay_delete_break(); | |
113 | } else { | |
114 | error_setg(errp, "replay breakpoints are allowed only in play mode"); | |
115 | } | |
116 | } | |
117 | ||
118 | void hmp_replay_delete_break(Monitor *mon, const QDict *qdict) | |
119 | { | |
120 | Error *err = NULL; | |
121 | ||
122 | qmp_replay_delete_break(&err); | |
123 | if (err) { | |
124 | error_report_err(err); | |
125 | return; | |
126 | } | |
127 | } |