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