xref: /qemu/replay/replay-debugging.c (revision d2c12785be06da708fe1c8e4e81d7134f4f3c56a)
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 "system/replay.h"
15  #include "system/runstate.h"
16  #include "replay-internal.h"
17  #include "monitor/hmp.h"
18  #include "monitor/monitor.h"
19  #include "qapi/qapi-commands-replay.h"
20  #include "qapi/qmp/qdict.h"
21  #include "qemu/timer.h"
22  #include "block/snapshot.h"
23  #include "migration/snapshot.h"
24  
25  static bool replay_is_debugging;
26  static int64_t replay_last_breakpoint;
27  static int64_t replay_last_snapshot;
28  
29  bool replay_running_debug(void)
30  {
31      return replay_is_debugging;
32  }
33  
34  void hmp_info_replay(Monitor *mon, const QDict *qdict)
35  {
36      if (replay_mode == REPLAY_MODE_NONE) {
37          monitor_printf(mon, "Record/replay is not active\n");
38      } else {
39          monitor_printf(mon,
40              "%s execution '%s': instruction count = %"PRId64"\n",
41              replay_mode == REPLAY_MODE_RECORD ? "Recording" : "Replaying",
42              replay_get_filename(), replay_get_current_icount());
43      }
44  }
45  
46  ReplayInfo *qmp_query_replay(Error **errp)
47  {
48      ReplayInfo *retval = g_new0(ReplayInfo, 1);
49  
50      retval->mode = replay_mode;
51      if (replay_get_filename()) {
52          retval->filename = g_strdup(replay_get_filename());
53      }
54      retval->icount = replay_get_current_icount();
55      return retval;
56  }
57  
58  static void replay_break(uint64_t icount, QEMUTimerCB callback, void *opaque)
59  {
60      assert(replay_mode == REPLAY_MODE_PLAY);
61      assert(replay_mutex_locked());
62      assert(replay_break_icount >= replay_get_current_icount());
63      assert(callback);
64  
65      replay_break_icount = icount;
66  
67      if (replay_break_timer) {
68          timer_del(replay_break_timer);
69      }
70      replay_break_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
71                                        callback, opaque);
72  }
73  
74  static void replay_delete_break(void)
75  {
76      assert(replay_mode == REPLAY_MODE_PLAY);
77      assert(replay_mutex_locked());
78  
79      if (replay_break_timer) {
80          timer_free(replay_break_timer);
81          replay_break_timer = NULL;
82      }
83      replay_break_icount = -1ULL;
84  }
85  
86  static void replay_stop_vm(void *opaque)
87  {
88      vm_stop(RUN_STATE_PAUSED);
89      replay_delete_break();
90  }
91  
92  void qmp_replay_break(int64_t icount, Error **errp)
93  {
94      if (replay_mode == REPLAY_MODE_PLAY) {
95          if (icount >= replay_get_current_icount()) {
96              replay_break(icount, replay_stop_vm, NULL);
97          } else {
98              error_setg(errp,
99                  "cannot set breakpoint at the instruction in the past");
100          }
101      } else {
102          error_setg(errp, "setting the breakpoint is allowed only in play mode");
103      }
104  }
105  
106  void hmp_replay_break(Monitor *mon, const QDict *qdict)
107  {
108      int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
109      Error *err = NULL;
110  
111      qmp_replay_break(icount, &err);
112      if (err) {
113          error_report_err(err);
114          return;
115      }
116  }
117  
118  void qmp_replay_delete_break(Error **errp)
119  {
120      if (replay_mode == REPLAY_MODE_PLAY) {
121          replay_delete_break();
122      } else {
123          error_setg(errp, "replay breakpoints are allowed only in play mode");
124      }
125  }
126  
127  void hmp_replay_delete_break(Monitor *mon, const QDict *qdict)
128  {
129      Error *err = NULL;
130  
131      qmp_replay_delete_break(&err);
132      if (err) {
133          error_report_err(err);
134          return;
135      }
136  }
137  
138  static char *replay_find_nearest_snapshot(int64_t icount,
139                                            int64_t *snapshot_icount)
140  {
141      BlockDriverState *bs;
142      QEMUSnapshotInfo *sn_tab;
143      QEMUSnapshotInfo *nearest = NULL;
144      char *ret = NULL;
145      int rv;
146      int nb_sns, i;
147  
148      *snapshot_icount = -1;
149  
150      bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, NULL);
151      if (!bs) {
152          goto fail;
153      }
154  
155      nb_sns = bdrv_snapshot_list(bs, &sn_tab);
156  
157      for (i = 0; i < nb_sns; i++) {
158          rv = bdrv_all_has_snapshot(sn_tab[i].name, false, NULL, NULL);
159          if (rv < 0)
160              goto fail;
161          if (rv == 1) {
162              if (sn_tab[i].icount != -1ULL
163                  && sn_tab[i].icount <= icount
164                  && (!nearest || nearest->icount < sn_tab[i].icount)) {
165                  nearest = &sn_tab[i];
166              }
167          }
168      }
169      if (nearest) {
170          ret = g_strdup(nearest->name);
171          *snapshot_icount = nearest->icount;
172      }
173      g_free(sn_tab);
174  
175  fail:
176      return ret;
177  }
178  
179  static void replay_seek(int64_t icount, QEMUTimerCB callback, Error **errp)
180  {
181      char *snapshot = NULL;
182      int64_t snapshot_icount;
183  
184      if (replay_mode != REPLAY_MODE_PLAY) {
185          error_setg(errp, "replay must be enabled to seek");
186          return;
187      }
188  
189      snapshot = replay_find_nearest_snapshot(icount, &snapshot_icount);
190      if (snapshot) {
191          if (icount < replay_get_current_icount()
192              || replay_get_current_icount() < snapshot_icount) {
193              vm_stop(RUN_STATE_RESTORE_VM);
194              load_snapshot(snapshot, NULL, false, NULL, errp);
195          }
196          g_free(snapshot);
197      }
198      if (replay_get_current_icount() <= icount) {
199          replay_break(icount, callback, NULL);
200          vm_start();
201      } else {
202          error_setg(errp, "cannot seek to the specified instruction count");
203      }
204  }
205  
206  void qmp_replay_seek(int64_t icount, Error **errp)
207  {
208      replay_seek(icount, replay_stop_vm, errp);
209  }
210  
211  void hmp_replay_seek(Monitor *mon, const QDict *qdict)
212  {
213      int64_t icount = qdict_get_try_int(qdict, "icount", -1LL);
214      Error *err = NULL;
215  
216      qmp_replay_seek(icount, &err);
217      if (err) {
218          error_report_err(err);
219          return;
220      }
221  }
222  
223  static void replay_stop_vm_debug(void *opaque)
224  {
225      replay_is_debugging = false;
226      vm_stop(RUN_STATE_DEBUG);
227      replay_delete_break();
228  }
229  
230  bool replay_reverse_step(void)
231  {
232      Error *err = NULL;
233  
234      assert(replay_mode == REPLAY_MODE_PLAY);
235  
236      if (replay_get_current_icount() != 0) {
237          replay_seek(replay_get_current_icount() - 1,
238                      replay_stop_vm_debug, &err);
239          if (err) {
240              error_free(err);
241              return false;
242          }
243          replay_is_debugging = true;
244          return true;
245      }
246  
247      return false;
248  }
249  
250  static void replay_continue_end(void)
251  {
252      replay_is_debugging = false;
253      vm_stop(RUN_STATE_DEBUG);
254      replay_delete_break();
255  }
256  
257  static void replay_continue_stop(void *opaque)
258  {
259      Error *err = NULL;
260      if (replay_last_breakpoint != -1LL) {
261          replay_seek(replay_last_breakpoint, replay_stop_vm_debug, &err);
262          if (err) {
263              error_free(err);
264              replay_continue_end();
265          }
266          return;
267      }
268      /*
269       * No breakpoints since the last snapshot.
270       * Find previous snapshot and try again.
271       */
272      if (replay_last_snapshot != 0) {
273          replay_seek(replay_last_snapshot - 1, replay_continue_stop, &err);
274          if (err) {
275              error_free(err);
276              replay_continue_end();
277          }
278          replay_last_snapshot = replay_get_current_icount();
279      } else {
280          /* Seek to the very first step */
281          replay_seek(0, replay_stop_vm_debug, &err);
282          if (err) {
283              error_free(err);
284              replay_continue_end();
285          }
286      }
287  }
288  
289  bool replay_reverse_continue(void)
290  {
291      Error *err = NULL;
292  
293      assert(replay_mode == REPLAY_MODE_PLAY);
294  
295      if (replay_get_current_icount() != 0) {
296          replay_seek(replay_get_current_icount() - 1,
297                      replay_continue_stop, &err);
298          if (err) {
299              error_free(err);
300              return false;
301          }
302          replay_last_breakpoint = -1LL;
303          replay_is_debugging = true;
304          replay_last_snapshot = replay_get_current_icount();
305          return true;
306      }
307  
308      return false;
309  }
310  
311  void replay_breakpoint(void)
312  {
313      assert(replay_mode == REPLAY_MODE_PLAY);
314      replay_last_breakpoint = replay_get_current_icount();
315  }
316  
317  void replay_gdb_attached(void)
318  {
319      /*
320       * Create VM snapshot on temporary overlay to allow reverse
321       * debugging even if snapshots were not enabled.
322       */
323      if (replay_mode == REPLAY_MODE_PLAY
324          && !replay_snapshot) {
325          if (!save_snapshot("start_debugging", true, NULL, false, NULL, NULL)) {
326              /* Can't create the snapshot. Continue conventional debugging. */
327          }
328      }
329  }
330