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" 15 #include "sysemu/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 AioContext *aio_context; 148 149 *snapshot_icount = -1; 150 151 bs = bdrv_all_find_vmstate_bs(NULL, false, NULL, NULL); 152 if (!bs) { 153 goto fail; 154 } 155 aio_context = bdrv_get_aio_context(bs); 156 157 aio_context_acquire(aio_context); 158 nb_sns = bdrv_snapshot_list(bs, &sn_tab); 159 aio_context_release(aio_context); 160 161 for (i = 0; i < nb_sns; i++) { 162 rv = bdrv_all_has_snapshot(sn_tab[i].name, false, NULL, NULL); 163 if (rv < 0) 164 goto fail; 165 if (rv == 1) { 166 if (sn_tab[i].icount != -1ULL 167 && sn_tab[i].icount <= icount 168 && (!nearest || nearest->icount < sn_tab[i].icount)) { 169 nearest = &sn_tab[i]; 170 } 171 } 172 } 173 if (nearest) { 174 ret = g_strdup(nearest->name); 175 *snapshot_icount = nearest->icount; 176 } 177 g_free(sn_tab); 178 179 fail: 180 return ret; 181 } 182 183 static void replay_seek(int64_t icount, QEMUTimerCB callback, Error **errp) 184 { 185 char *snapshot = NULL; 186 int64_t snapshot_icount; 187 188 if (replay_mode != REPLAY_MODE_PLAY) { 189 error_setg(errp, "replay must be enabled to seek"); 190 return; 191 } 192 193 snapshot = replay_find_nearest_snapshot(icount, &snapshot_icount); 194 if (snapshot) { 195 if (icount < replay_get_current_icount() 196 || replay_get_current_icount() < snapshot_icount) { 197 vm_stop(RUN_STATE_RESTORE_VM); 198 load_snapshot(snapshot, NULL, false, NULL, errp); 199 } 200 g_free(snapshot); 201 } 202 if (replay_get_current_icount() <= icount) { 203 replay_break(icount, callback, NULL); 204 vm_start(); 205 } else { 206 error_setg(errp, "cannot seek to the specified instruction count"); 207 } 208 } 209 210 void qmp_replay_seek(int64_t icount, Error **errp) 211 { 212 replay_seek(icount, replay_stop_vm, errp); 213 } 214 215 void hmp_replay_seek(Monitor *mon, const QDict *qdict) 216 { 217 int64_t icount = qdict_get_try_int(qdict, "icount", -1LL); 218 Error *err = NULL; 219 220 qmp_replay_seek(icount, &err); 221 if (err) { 222 error_report_err(err); 223 return; 224 } 225 } 226 227 static void replay_stop_vm_debug(void *opaque) 228 { 229 replay_is_debugging = false; 230 vm_stop(RUN_STATE_DEBUG); 231 replay_delete_break(); 232 } 233 234 bool replay_reverse_step(void) 235 { 236 Error *err = NULL; 237 238 assert(replay_mode == REPLAY_MODE_PLAY); 239 240 if (replay_get_current_icount() != 0) { 241 replay_seek(replay_get_current_icount() - 1, 242 replay_stop_vm_debug, &err); 243 if (err) { 244 error_free(err); 245 return false; 246 } 247 replay_is_debugging = true; 248 return true; 249 } 250 251 return false; 252 } 253 254 static void replay_continue_end(void) 255 { 256 replay_is_debugging = false; 257 vm_stop(RUN_STATE_DEBUG); 258 replay_delete_break(); 259 } 260 261 static void replay_continue_stop(void *opaque) 262 { 263 Error *err = NULL; 264 if (replay_last_breakpoint != -1LL) { 265 replay_seek(replay_last_breakpoint, replay_stop_vm_debug, &err); 266 if (err) { 267 error_free(err); 268 replay_continue_end(); 269 } 270 return; 271 } 272 /* 273 * No breakpoints since the last snapshot. 274 * Find previous snapshot and try again. 275 */ 276 if (replay_last_snapshot != 0) { 277 replay_seek(replay_last_snapshot - 1, replay_continue_stop, &err); 278 if (err) { 279 error_free(err); 280 replay_continue_end(); 281 } 282 replay_last_snapshot = replay_get_current_icount(); 283 } else { 284 /* Seek to the very first step */ 285 replay_seek(0, replay_stop_vm_debug, &err); 286 if (err) { 287 error_free(err); 288 replay_continue_end(); 289 } 290 } 291 } 292 293 bool replay_reverse_continue(void) 294 { 295 Error *err = NULL; 296 297 assert(replay_mode == REPLAY_MODE_PLAY); 298 299 if (replay_get_current_icount() != 0) { 300 replay_seek(replay_get_current_icount() - 1, 301 replay_continue_stop, &err); 302 if (err) { 303 error_free(err); 304 return false; 305 } 306 replay_last_breakpoint = -1LL; 307 replay_is_debugging = true; 308 replay_last_snapshot = replay_get_current_icount(); 309 return true; 310 } 311 312 return false; 313 } 314 315 void replay_breakpoint(void) 316 { 317 assert(replay_mode == REPLAY_MODE_PLAY); 318 replay_last_breakpoint = replay_get_current_icount(); 319 } 320 321 void replay_gdb_attached(void) 322 { 323 /* 324 * Create VM snapshot on temporary overlay to allow reverse 325 * debugging even if snapshots were not enabled. 326 */ 327 if (replay_mode == REPLAY_MODE_PLAY 328 && !replay_snapshot) { 329 if (!save_snapshot("start_debugging", true, NULL, false, NULL, NULL)) { 330 /* Can't create the snapshot. Continue conventional debugging. */ 331 } 332 } 333 } 334