2009-10-21 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / record.c
CommitLineData
69d05d38
HZ
1/* Process record and replay target for GDB, the GNU debugger.
2
3 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "gdbcmd.h"
22#include "regcache.h"
23#include "gdbthread.h"
24#include "event-top.h"
25#include "exceptions.h"
26#include "record.h"
27
28#include <signal.h>
29
6df67667
MS
30/* This module implements "target record", also known as "process
31 record and replay". This target sits on top of a "normal" target
32 (a target that "has execution"), and provides a record and replay
33 functionality, including reverse debugging.
34
35 Target record has two modes: recording, and replaying.
36
37 In record mode, we intercept the to_resume and to_wait methods.
38 Whenever gdb resumes the target, we run the target in single step
39 mode, and we build up an execution log in which, for each executed
40 instruction, we record all changes in memory and register state.
41 This is invisible to the user, to whom it just looks like an
42 ordinary debugging session (except for performance degredation).
43
44 In replay mode, instead of actually letting the inferior run as a
45 process, we simulate its execution by playing back the recorded
46 execution log. For each instruction in the log, we simulate the
47 instruction's side effects by duplicating the changes that it would
48 have made on memory and registers. */
49
69d05d38
HZ
50#define DEFAULT_RECORD_INSN_MAX_NUM 200000
51
52#define RECORD_IS_REPLAY \
53 (record_list->next || execution_direction == EXEC_REVERSE)
54
fda458ee 55/* These are the core structs of the process record functionality.
69d05d38 56
fda458ee 57 A record_entry is a record of the value change of a register
69d05d38 58 ("record_reg") or a part of memory ("record_mem"). And each
fda458ee
MS
59 instruction must have a struct record_entry ("record_end") that
60 indicates that this is the last struct record_entry of this
61 instruction.
69d05d38 62
fda458ee
MS
63 Each struct record_entry is linked to "record_list" by "prev" and
64 "next" pointers. */
69d05d38 65
69d05d38
HZ
66struct record_mem_entry
67{
68 CORE_ADDR addr;
69 int len;
afd0cd3f
MS
70 /* Set this flag if target memory for this entry
71 can no longer be accessed. */
72 int mem_entry_not_accessible;
44389f9b
MS
73 union
74 {
75 gdb_byte *ptr;
76 gdb_byte buf[sizeof (gdb_byte *)];
77 } u;
78};
79
80struct record_reg_entry
81{
82 unsigned short num;
83 unsigned short len;
84 union
85 {
86 gdb_byte *ptr;
87 gdb_byte buf[2 * sizeof (gdb_byte *)];
88 } u;
69d05d38
HZ
89};
90
8b739a96
HZ
91struct record_end_entry
92{
93 enum target_signal sigval;
b54295a7 94 ULONGEST insn_num;
8b739a96
HZ
95};
96
69d05d38
HZ
97enum record_type
98{
99 record_end = 0,
100 record_reg,
101 record_mem
102};
103
6df67667
MS
104/* This is the data structure that makes up the execution log.
105
106 The execution log consists of a single linked list of entries
107 of type "struct record_entry". It is doubly linked so that it
108 can be traversed in either direction.
109
110 The start of the list is anchored by a struct called
111 "record_first". The pointer "record_list" either points to the
112 last entry that was added to the list (in record mode), or to the
113 next entry in the list that will be executed (in replay mode).
114
115 Each list element (struct record_entry), in addition to next and
116 prev pointers, consists of a union of three entry types: mem, reg,
117 and end. A field called "type" determines which entry type is
118 represented by a given list element.
119
120 Each instruction that is added to the execution log is represented
121 by a variable number of list elements ('entries'). The instruction
122 will have one "reg" entry for each register that is changed by
123 executing the instruction (including the PC in every case). It
124 will also have one "mem" entry for each memory change. Finally,
125 each instruction will have an "end" entry that separates it from
126 the changes associated with the next instruction. */
127
69d05d38
HZ
128struct record_entry
129{
130 struct record_entry *prev;
131 struct record_entry *next;
132 enum record_type type;
133 union
134 {
135 /* reg */
136 struct record_reg_entry reg;
137 /* mem */
138 struct record_mem_entry mem;
8b739a96
HZ
139 /* end */
140 struct record_end_entry end;
69d05d38
HZ
141 } u;
142};
143
144/* This is the debug switch for process record. */
145int record_debug = 0;
146
6df67667
MS
147/* The following variables are used for managing the linked list that
148 represents the execution log.
149
150 record_first is the anchor that holds down the beginning of the list.
151
152 record_list serves two functions:
153 1) In record mode, it anchors the end of the list.
154 2) In replay mode, it traverses the list and points to
155 the next instruction that must be emulated.
156
157 record_arch_list_head and record_arch_list_tail are used to manage
158 a separate list, which is used to build up the change elements of
159 the currently executing instruction during record mode. When this
160 instruction has been completely annotated in the "arch list", it
161 will be appended to the main execution log. */
162
69d05d38
HZ
163static struct record_entry record_first;
164static struct record_entry *record_list = &record_first;
165static struct record_entry *record_arch_list_head = NULL;
166static struct record_entry *record_arch_list_tail = NULL;
167
168/* 1 ask user. 0 auto delete the last struct record_entry. */
169static int record_stop_at_limit = 1;
b54295a7 170/* Maximum allowed number of insns in execution log. */
191e1813 171static unsigned int record_insn_max_num = DEFAULT_RECORD_INSN_MAX_NUM;
b54295a7 172/* Actual count of insns presently in execution log. */
69d05d38 173static int record_insn_num = 0;
b54295a7
MS
174/* Count of insns logged so far (may be larger
175 than count of insns presently in execution log). */
176static ULONGEST record_insn_count;
69d05d38
HZ
177
178/* The target_ops of process record. */
179static struct target_ops record_ops;
180
181/* The beneath function pointers. */
182static struct target_ops *record_beneath_to_resume_ops;
183static void (*record_beneath_to_resume) (struct target_ops *, ptid_t, int,
184 enum target_signal);
185static struct target_ops *record_beneath_to_wait_ops;
186static ptid_t (*record_beneath_to_wait) (struct target_ops *, ptid_t,
47608cb1
PA
187 struct target_waitstatus *,
188 int);
69d05d38
HZ
189static struct target_ops *record_beneath_to_store_registers_ops;
190static void (*record_beneath_to_store_registers) (struct target_ops *,
191 struct regcache *,
192 int regno);
193static struct target_ops *record_beneath_to_xfer_partial_ops;
194static LONGEST (*record_beneath_to_xfer_partial) (struct target_ops *ops,
195 enum target_object object,
196 const char *annex,
197 gdb_byte *readbuf,
198 const gdb_byte *writebuf,
199 ULONGEST offset,
200 LONGEST len);
a6d9a66e
UW
201static int (*record_beneath_to_insert_breakpoint) (struct gdbarch *,
202 struct bp_target_info *);
203static int (*record_beneath_to_remove_breakpoint) (struct gdbarch *,
204 struct bp_target_info *);
69d05d38 205
61f75dd8
MS
206/* Alloc and free functions for record_reg, record_mem, and record_end
207 entries. */
208
209/* Alloc a record_reg record entry. */
210
211static inline struct record_entry *
212record_reg_alloc (struct regcache *regcache, int regnum)
213{
214 struct record_entry *rec;
215 struct gdbarch *gdbarch = get_regcache_arch (regcache);
216
217 rec = (struct record_entry *) xcalloc (1, sizeof (struct record_entry));
218 rec->type = record_reg;
219 rec->u.reg.num = regnum;
44389f9b
MS
220 rec->u.reg.len = register_size (gdbarch, regnum);
221 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
222 rec->u.reg.u.ptr = (gdb_byte *) xmalloc (rec->u.reg.len);
61f75dd8
MS
223
224 return rec;
225}
226
227/* Free a record_reg record entry. */
228
229static inline void
230record_reg_release (struct record_entry *rec)
231{
232 gdb_assert (rec->type == record_reg);
44389f9b
MS
233 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
234 xfree (rec->u.reg.u.ptr);
61f75dd8
MS
235 xfree (rec);
236}
237
238/* Alloc a record_mem record entry. */
239
240static inline struct record_entry *
241record_mem_alloc (CORE_ADDR addr, int len)
242{
243 struct record_entry *rec;
244
245 rec = (struct record_entry *) xcalloc (1, sizeof (struct record_entry));
246 rec->type = record_mem;
247 rec->u.mem.addr = addr;
248 rec->u.mem.len = len;
44389f9b
MS
249 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
250 rec->u.mem.u.ptr = (gdb_byte *) xmalloc (len);
61f75dd8
MS
251
252 return rec;
253}
254
255/* Free a record_mem record entry. */
256
257static inline void
258record_mem_release (struct record_entry *rec)
259{
260 gdb_assert (rec->type == record_mem);
44389f9b
MS
261 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
262 xfree (rec->u.mem.u.ptr);
61f75dd8
MS
263 xfree (rec);
264}
265
266/* Alloc a record_end record entry. */
267
268static inline struct record_entry *
269record_end_alloc (void)
270{
271 struct record_entry *rec;
272
273 rec = (struct record_entry *) xcalloc (1, sizeof (struct record_entry));
274 rec->type = record_end;
275
276 return rec;
277}
278
279/* Free a record_end record entry. */
280
281static inline void
282record_end_release (struct record_entry *rec)
283{
284 xfree (rec);
285}
286
287/* Free one record entry, any type.
288 Return entry->type, in case caller wants to know. */
289
290static inline enum record_type
291record_entry_release (struct record_entry *rec)
292{
293 enum record_type type = rec->type;
294
295 switch (type) {
296 case record_reg:
297 record_reg_release (rec);
298 break;
299 case record_mem:
300 record_mem_release (rec);
301 break;
302 case record_end:
303 record_end_release (rec);
304 break;
305 }
306 return type;
307}
308
309/* Free all record entries in list pointed to by REC. */
310
69d05d38
HZ
311static void
312record_list_release (struct record_entry *rec)
313{
69d05d38
HZ
314 if (!rec)
315 return;
316
317 while (rec->next)
61f75dd8 318 rec = rec->next;
69d05d38
HZ
319
320 while (rec->prev)
321 {
69d05d38 322 rec = rec->prev;
61f75dd8 323 record_entry_release (rec->next);
69d05d38
HZ
324 }
325
61f75dd8
MS
326 if (rec == &record_first)
327 {
328 record_insn_num = 0;
329 record_first.next = NULL;
330 }
331 else
332 record_entry_release (rec);
69d05d38
HZ
333}
334
61f75dd8
MS
335/* Free all record entries forward of the given list position. */
336
69d05d38 337static void
61f75dd8 338record_list_release_following (struct record_entry *rec)
69d05d38 339{
69d05d38 340 struct record_entry *tmp = rec->next;
61f75dd8 341
69d05d38
HZ
342 rec->next = NULL;
343 while (tmp)
344 {
345 rec = tmp->next;
61f75dd8 346 if (record_entry_release (tmp) == record_end)
b54295a7
MS
347 {
348 record_insn_num--;
349 record_insn_count--;
350 }
69d05d38
HZ
351 tmp = rec;
352 }
353}
354
265aad34
MS
355/* Delete the first instruction from the beginning of the log, to make
356 room for adding a new instruction at the end of the log.
357
358 Note -- this function does not modify record_insn_num. */
359
69d05d38
HZ
360static void
361record_list_release_first (void)
362{
61f75dd8 363 struct record_entry *tmp;
69d05d38
HZ
364
365 if (!record_first.next)
366 return;
367
61f75dd8 368 /* Loop until a record_end. */
69d05d38
HZ
369 while (1)
370 {
61f75dd8 371 /* Cut record_first.next out of the linked list. */
69d05d38
HZ
372 tmp = record_first.next;
373 record_first.next = tmp->next;
61f75dd8
MS
374 tmp->next->prev = &record_first;
375
376 /* tmp is now isolated, and can be deleted. */
377 if (record_entry_release (tmp) == record_end)
b54295a7 378 break; /* End loop at first record_end. */
69d05d38
HZ
379
380 if (!record_first.next)
381 {
382 gdb_assert (record_insn_num == 1);
61f75dd8 383 break; /* End loop when list is empty. */
69d05d38 384 }
69d05d38 385 }
69d05d38
HZ
386}
387
388/* Add a struct record_entry to record_arch_list. */
389
390static void
391record_arch_list_add (struct record_entry *rec)
392{
393 if (record_debug > 1)
394 fprintf_unfiltered (gdb_stdlog,
395 "Process record: record_arch_list_add %s.\n",
396 host_address_to_string (rec));
397
398 if (record_arch_list_tail)
399 {
400 record_arch_list_tail->next = rec;
401 rec->prev = record_arch_list_tail;
402 record_arch_list_tail = rec;
403 }
404 else
405 {
406 record_arch_list_head = rec;
407 record_arch_list_tail = rec;
408 }
409}
410
44389f9b
MS
411/* Return the value storage location of a record entry. */
412static inline gdb_byte *
413record_get_loc (struct record_entry *rec)
414{
415 switch (rec->type) {
416 case record_mem:
417 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
418 return rec->u.mem.u.ptr;
419 else
420 return rec->u.mem.u.buf;
421 case record_reg:
422 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
423 return rec->u.reg.u.ptr;
424 else
425 return rec->u.reg.u.buf;
426 case record_end:
427 default:
428 gdb_assert (0);
429 return NULL;
430 }
431}
432
433/* Record the value of a register NUM to record_arch_list. */
69d05d38
HZ
434
435int
61f75dd8 436record_arch_list_add_reg (struct regcache *regcache, int regnum)
69d05d38
HZ
437{
438 struct record_entry *rec;
439
440 if (record_debug > 1)
441 fprintf_unfiltered (gdb_stdlog,
442 "Process record: add register num = %d to "
443 "record list.\n",
61f75dd8 444 regnum);
69d05d38 445
61f75dd8 446 rec = record_reg_alloc (regcache, regnum);
69d05d38 447
44389f9b 448 regcache_raw_read (regcache, regnum, record_get_loc (rec));
69d05d38
HZ
449
450 record_arch_list_add (rec);
451
452 return 0;
453}
454
455/* Record the value of a region of memory whose address is ADDR and
456 length is LEN to record_arch_list. */
457
458int
459record_arch_list_add_mem (CORE_ADDR addr, int len)
460{
461 struct record_entry *rec;
462
463 if (record_debug > 1)
464 fprintf_unfiltered (gdb_stdlog,
5af949e3 465 "Process record: add mem addr = %s len = %d to "
69d05d38 466 "record list.\n",
5af949e3 467 paddress (target_gdbarch, addr), len);
69d05d38 468
61f75dd8 469 if (!addr) /* FIXME: Why? Some arch must permit it... */
69d05d38
HZ
470 return 0;
471
61f75dd8 472 rec = record_mem_alloc (addr, len);
69d05d38 473
44389f9b 474 if (target_read_memory (addr, record_get_loc (rec), len))
69d05d38
HZ
475 {
476 if (record_debug)
477 fprintf_unfiltered (gdb_stdlog,
478 "Process record: error reading memory at "
5af949e3
UW
479 "addr = %s len = %d.\n",
480 paddress (target_gdbarch, addr), len);
61f75dd8 481 record_mem_release (rec);
69d05d38
HZ
482 return -1;
483 }
484
485 record_arch_list_add (rec);
486
487 return 0;
488}
489
490/* Add a record_end type struct record_entry to record_arch_list. */
491
492int
493record_arch_list_add_end (void)
494{
495 struct record_entry *rec;
496
497 if (record_debug > 1)
498 fprintf_unfiltered (gdb_stdlog,
499 "Process record: add end to arch list.\n");
500
61f75dd8 501 rec = record_end_alloc ();
8b739a96 502 rec->u.end.sigval = TARGET_SIGNAL_0;
b54295a7 503 rec->u.end.insn_num = ++record_insn_count;
69d05d38
HZ
504
505 record_arch_list_add (rec);
506
507 return 0;
508}
509
510static void
511record_check_insn_num (int set_terminal)
512{
513 if (record_insn_max_num)
514 {
515 gdb_assert (record_insn_num <= record_insn_max_num);
516 if (record_insn_num == record_insn_max_num)
517 {
518 /* Ask user what to do. */
519 if (record_stop_at_limit)
520 {
521 int q;
522 if (set_terminal)
523 target_terminal_ours ();
524 q = yquery (_("Do you want to auto delete previous execution "
525 "log entries when record/replay buffer becomes "
526 "full (record stop-at-limit)?"));
527 if (set_terminal)
528 target_terminal_inferior ();
529 if (q)
530 record_stop_at_limit = 0;
531 else
532 error (_("Process record: inferior program stopped."));
533 }
534 }
535 }
536}
537
538/* Before inferior step (when GDB record the running message, inferior
539 only can step), GDB will call this function to record the values to
540 record_list. This function will call gdbarch_process_record to
541 record the running message of inferior and set them to
542 record_arch_list, and add it to record_list. */
543
544static void
545record_message_cleanups (void *ignore)
546{
547 record_list_release (record_arch_list_tail);
548}
549
8b739a96
HZ
550struct record_message_args {
551 struct regcache *regcache;
552 enum target_signal signal;
553};
554
69d05d38
HZ
555static int
556record_message (void *args)
557{
558 int ret;
8b739a96
HZ
559 struct record_message_args *myargs = args;
560 struct gdbarch *gdbarch = get_regcache_arch (myargs->regcache);
69d05d38
HZ
561 struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0);
562
563 record_arch_list_head = NULL;
564 record_arch_list_tail = NULL;
565
566 /* Check record_insn_num. */
567 record_check_insn_num (1);
568
8b739a96
HZ
569 /* If gdb sends a signal value to target_resume,
570 save it in the 'end' field of the previous instruction.
571
572 Maybe process record should record what really happened,
573 rather than what gdb pretends has happened.
574
575 So if Linux delivered the signal to the child process during
576 the record mode, we will record it and deliver it again in
577 the replay mode.
578
579 If user says "ignore this signal" during the record mode, then
580 it will be ignored again during the replay mode (no matter if
581 the user says something different, like "deliver this signal"
582 during the replay mode).
583
584 User should understand that nothing he does during the replay
585 mode will change the behavior of the child. If he tries,
586 then that is a user error.
587
588 But we should still deliver the signal to gdb during the replay,
589 if we delivered it during the recording. Therefore we should
590 record the signal during record_wait, not record_resume. */
591 if (record_list != &record_first) /* FIXME better way to check */
592 {
593 gdb_assert (record_list->type == record_end);
594 record_list->u.end.sigval = myargs->signal;
595 }
596
597 if (myargs->signal == TARGET_SIGNAL_0
598 || !gdbarch_process_record_signal_p (gdbarch))
599 ret = gdbarch_process_record (gdbarch,
600 myargs->regcache,
601 regcache_read_pc (myargs->regcache));
602 else
603 ret = gdbarch_process_record_signal (gdbarch,
604 myargs->regcache,
605 myargs->signal);
606
69d05d38
HZ
607 if (ret > 0)
608 error (_("Process record: inferior program stopped."));
609 if (ret < 0)
610 error (_("Process record: failed to record execution log."));
611
612 discard_cleanups (old_cleanups);
613
614 record_list->next = record_arch_list_head;
615 record_arch_list_head->prev = record_list;
616 record_list = record_arch_list_tail;
617
618 if (record_insn_num == record_insn_max_num && record_insn_max_num)
619 record_list_release_first ();
620 else
621 record_insn_num++;
622
623 return 1;
624}
625
626static int
8b739a96
HZ
627do_record_message (struct regcache *regcache,
628 enum target_signal signal)
69d05d38 629{
8b739a96
HZ
630 struct record_message_args args;
631
632 args.regcache = regcache;
633 args.signal = signal;
634 return catch_errors (record_message, &args, NULL, RETURN_MASK_ALL);
69d05d38
HZ
635}
636
637/* Set to 1 if record_store_registers and record_xfer_partial
638 doesn't need record. */
639
640static int record_gdb_operation_disable = 0;
641
642struct cleanup *
643record_gdb_operation_disable_set (void)
644{
645 struct cleanup *old_cleanups = NULL;
646
647 old_cleanups =
648 make_cleanup_restore_integer (&record_gdb_operation_disable);
649 record_gdb_operation_disable = 1;
650
651 return old_cleanups;
652}
653
90ca0479
MS
654/* Execute one instruction from the record log. Each instruction in
655 the log will be represented by an arbitrary sequence of register
656 entries and memory entries, followed by an 'end' entry. */
657
658static inline void
659record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch,
660 struct record_entry *entry)
661{
662 switch (entry->type)
663 {
664 case record_reg: /* reg */
665 {
666 gdb_byte reg[MAX_REGISTER_SIZE];
667
668 if (record_debug > 1)
669 fprintf_unfiltered (gdb_stdlog,
670 "Process record: record_reg %s to "
671 "inferior num = %d.\n",
672 host_address_to_string (entry),
673 entry->u.reg.num);
674
675 regcache_cooked_read (regcache, entry->u.reg.num, reg);
676 regcache_cooked_write (regcache, entry->u.reg.num,
677 record_get_loc (entry));
678 memcpy (record_get_loc (entry), reg, entry->u.reg.len);
679 }
680 break;
681
682 case record_mem: /* mem */
683 {
684 /* Nothing to do if the entry is flagged not_accessible. */
685 if (!entry->u.mem.mem_entry_not_accessible)
686 {
687 gdb_byte *mem = alloca (entry->u.mem.len);
688
689 if (record_debug > 1)
690 fprintf_unfiltered (gdb_stdlog,
691 "Process record: record_mem %s to "
692 "inferior addr = %s len = %d.\n",
693 host_address_to_string (entry),
694 paddress (gdbarch, entry->u.mem.addr),
695 entry->u.mem.len);
696
697 if (target_read_memory (entry->u.mem.addr, mem, entry->u.mem.len))
698 {
699 entry->u.mem.mem_entry_not_accessible = 1;
700 if (record_debug)
701 warning (_("Process record: error reading memory at "
702 "addr = %s len = %d."),
703 paddress (gdbarch, entry->u.mem.addr),
704 entry->u.mem.len);
705 }
706 else
707 {
708 if (target_write_memory (entry->u.mem.addr,
709 record_get_loc (entry),
710 entry->u.mem.len))
711 {
712 entry->u.mem.mem_entry_not_accessible = 1;
713 if (record_debug)
714 warning (_("Process record: error writing memory at "
715 "addr = %s len = %d."),
716 paddress (gdbarch, entry->u.mem.addr),
717 entry->u.mem.len);
718 }
719 else
720 memcpy (record_get_loc (entry), mem, entry->u.mem.len);
721 }
722 }
723 }
724 break;
725 }
726}
727
6df67667
MS
728/* "to_open" target method. Open the process record target. */
729
69d05d38
HZ
730static void
731record_open (char *name, int from_tty)
732{
733 struct target_ops *t;
734
735 if (record_debug)
736 fprintf_unfiltered (gdb_stdlog, "Process record: record_open\n");
737
738 /* check exec */
739 if (!target_has_execution)
740 error (_("Process record: the program is not being run."));
741 if (non_stop)
742 error (_("Process record target can't debug inferior in non-stop mode "
743 "(non-stop)."));
744 if (target_async_permitted)
745 error (_("Process record target can't debug inferior in asynchronous "
746 "mode (target-async)."));
747
a97b0ac8 748 if (!gdbarch_process_record_p (target_gdbarch))
69d05d38
HZ
749 error (_("Process record: the current architecture doesn't support "
750 "record function."));
751
752 /* Check if record target is already running. */
753 if (current_target.to_stratum == record_stratum)
5d40bb85
HZ
754 error (_("Process record target already running. Use \"record stop\" to "
755 "stop record target first."));
69d05d38
HZ
756
757 /*Reset the beneath function pointers. */
758 record_beneath_to_resume = NULL;
759 record_beneath_to_wait = NULL;
760 record_beneath_to_store_registers = NULL;
761 record_beneath_to_xfer_partial = NULL;
762 record_beneath_to_insert_breakpoint = NULL;
763 record_beneath_to_remove_breakpoint = NULL;
764
765 /* Set the beneath function pointers. */
766 for (t = current_target.beneath; t != NULL; t = t->beneath)
767 {
768 if (!record_beneath_to_resume)
769 {
770 record_beneath_to_resume = t->to_resume;
771 record_beneath_to_resume_ops = t;
772 }
773 if (!record_beneath_to_wait)
774 {
775 record_beneath_to_wait = t->to_wait;
776 record_beneath_to_wait_ops = t;
777 }
778 if (!record_beneath_to_store_registers)
779 {
780 record_beneath_to_store_registers = t->to_store_registers;
781 record_beneath_to_store_registers_ops = t;
782 }
783 if (!record_beneath_to_xfer_partial)
784 {
785 record_beneath_to_xfer_partial = t->to_xfer_partial;
786 record_beneath_to_xfer_partial_ops = t;
787 }
788 if (!record_beneath_to_insert_breakpoint)
789 record_beneath_to_insert_breakpoint = t->to_insert_breakpoint;
790 if (!record_beneath_to_remove_breakpoint)
791 record_beneath_to_remove_breakpoint = t->to_remove_breakpoint;
792 }
793 if (!record_beneath_to_resume)
794 error (_("Process record can't get to_resume."));
795 if (!record_beneath_to_wait)
796 error (_("Process record can't get to_wait."));
797 if (!record_beneath_to_store_registers)
798 error (_("Process record can't get to_store_registers."));
799 if (!record_beneath_to_xfer_partial)
800 error (_("Process record can't get to_xfer_partial."));
801 if (!record_beneath_to_insert_breakpoint)
802 error (_("Process record can't get to_insert_breakpoint."));
803 if (!record_beneath_to_remove_breakpoint)
804 error (_("Process record can't get to_remove_breakpoint."));
805
806 push_target (&record_ops);
807
808 /* Reset */
809 record_insn_num = 0;
b54295a7 810 record_insn_count = 0;
69d05d38
HZ
811 record_list = &record_first;
812 record_list->next = NULL;
813}
814
6df67667
MS
815/* "to_close" target method. Close the process record target. */
816
69d05d38
HZ
817static void
818record_close (int quitting)
819{
820 if (record_debug)
821 fprintf_unfiltered (gdb_stdlog, "Process record: record_close\n");
822
823 record_list_release (record_list);
824}
825
826static int record_resume_step = 0;
69d05d38
HZ
827static int record_resume_error;
828
6df67667
MS
829/* "to_resume" target method. Resume the process record target. */
830
69d05d38
HZ
831static void
832record_resume (struct target_ops *ops, ptid_t ptid, int step,
8b739a96 833 enum target_signal signal)
69d05d38
HZ
834{
835 record_resume_step = step;
69d05d38
HZ
836
837 if (!RECORD_IS_REPLAY)
838 {
8b739a96 839 if (do_record_message (get_current_regcache (), signal))
69d05d38
HZ
840 {
841 record_resume_error = 0;
842 }
843 else
844 {
845 record_resume_error = 1;
846 return;
847 }
848 record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
8b739a96 849 signal);
69d05d38
HZ
850 }
851}
852
853static int record_get_sig = 0;
854
6df67667
MS
855/* SIGINT signal handler, registered by "to_wait" method. */
856
69d05d38
HZ
857static void
858record_sig_handler (int signo)
859{
860 if (record_debug)
861 fprintf_unfiltered (gdb_stdlog, "Process record: get a signal\n");
862
863 /* It will break the running inferior in replay mode. */
864 record_resume_step = 1;
865
866 /* It will let record_wait set inferior status to get the signal
867 SIGINT. */
868 record_get_sig = 1;
869}
870
871static void
872record_wait_cleanups (void *ignore)
873{
874 if (execution_direction == EXEC_REVERSE)
875 {
876 if (record_list->next)
877 record_list = record_list->next;
878 }
879 else
880 record_list = record_list->prev;
881}
882
6df67667
MS
883/* "to_wait" target method for process record target.
884
885 In record mode, the target is always run in singlestep mode
886 (even when gdb says to continue). The to_wait method intercepts
887 the stop events and determines which ones are to be passed on to
888 gdb. Most stop events are just singlestep events that gdb is not
889 to know about, so the to_wait method just records them and keeps
890 singlestepping.
891
892 In replay mode, this function emulates the recorded execution log,
893 one instruction at a time (forward or backward), and determines
894 where to stop. */
69d05d38
HZ
895
896static ptid_t
897record_wait (struct target_ops *ops,
47608cb1
PA
898 ptid_t ptid, struct target_waitstatus *status,
899 int options)
69d05d38
HZ
900{
901 struct cleanup *set_cleanups = record_gdb_operation_disable_set ();
902
903 if (record_debug)
904 fprintf_unfiltered (gdb_stdlog,
905 "Process record: record_wait "
906 "record_resume_step = %d\n",
907 record_resume_step);
908
909 if (!RECORD_IS_REPLAY)
910 {
911 if (record_resume_error)
912 {
913 /* If record_resume get error, return directly. */
914 status->kind = TARGET_WAITKIND_STOPPED;
915 status->value.sig = TARGET_SIGNAL_ABRT;
916 return inferior_ptid;
917 }
918
919 if (record_resume_step)
920 {
921 /* This is a single step. */
922 return record_beneath_to_wait (record_beneath_to_wait_ops,
90092760 923 ptid, status, options);
69d05d38
HZ
924 }
925 else
926 {
927 /* This is not a single step. */
928 ptid_t ret;
929 CORE_ADDR tmp_pc;
930
931 while (1)
932 {
933 ret = record_beneath_to_wait (record_beneath_to_wait_ops,
90092760 934 ptid, status, options);
69d05d38 935
8b739a96 936 /* Is this a SIGTRAP? */
69d05d38
HZ
937 if (status->kind == TARGET_WAITKIND_STOPPED
938 && status->value.sig == TARGET_SIGNAL_TRAP)
939 {
6c95b8df
PA
940 struct regcache *regcache;
941
8b739a96 942 /* Yes -- check if there is a breakpoint. */
69d05d38 943 registers_changed ();
6c95b8df
PA
944 regcache = get_current_regcache ();
945 tmp_pc = regcache_read_pc (regcache);
946 if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
947 tmp_pc))
69d05d38 948 {
8b739a96 949 /* There is a breakpoint. GDB will want to stop. */
6c95b8df
PA
950 struct gdbarch *gdbarch = get_regcache_arch (regcache);
951 CORE_ADDR decr_pc_after_break
952 = gdbarch_decr_pc_after_break (gdbarch);
69d05d38 953 if (decr_pc_after_break)
6c95b8df
PA
954 regcache_write_pc (regcache,
955 tmp_pc + decr_pc_after_break);
69d05d38
HZ
956 }
957 else
958 {
8b739a96
HZ
959 /* There is not a breakpoint, and gdb is not
960 stepping, therefore gdb will not stop.
961 Therefore we will not return to gdb.
962 Record the insn and resume. */
6c95b8df
PA
963 if (!do_record_message (regcache, TARGET_SIGNAL_0))
964 break;
965
69d05d38
HZ
966 record_beneath_to_resume (record_beneath_to_resume_ops,
967 ptid, 1,
88fef440 968 TARGET_SIGNAL_0);
69d05d38
HZ
969 continue;
970 }
971 }
972
973 /* The inferior is broken by a breakpoint or a signal. */
974 break;
975 }
976
977 return ret;
978 }
979 }
980 else
981 {
982 struct regcache *regcache = get_current_regcache ();
5af949e3 983 struct gdbarch *gdbarch = get_regcache_arch (regcache);
69d05d38
HZ
984 int continue_flag = 1;
985 int first_record_end = 1;
986 struct cleanup *old_cleanups = make_cleanup (record_wait_cleanups, 0);
987 CORE_ADDR tmp_pc;
988
989 status->kind = TARGET_WAITKIND_STOPPED;
990
991 /* Check breakpoint when forward execute. */
992 if (execution_direction == EXEC_FORWARD)
993 {
994 tmp_pc = regcache_read_pc (regcache);
6c95b8df
PA
995 if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
996 tmp_pc))
69d05d38
HZ
997 {
998 if (record_debug)
999 fprintf_unfiltered (gdb_stdlog,
5af949e3
UW
1000 "Process record: break at %s.\n",
1001 paddress (gdbarch, tmp_pc));
1002 if (gdbarch_decr_pc_after_break (gdbarch)
69d05d38
HZ
1003 && !record_resume_step)
1004 regcache_write_pc (regcache,
1005 tmp_pc +
5af949e3 1006 gdbarch_decr_pc_after_break (gdbarch));
69d05d38
HZ
1007 goto replay_out;
1008 }
1009 }
1010
1011 record_get_sig = 0;
1012 signal (SIGINT, record_sig_handler);
1013 /* If GDB is in terminal_inferior mode, it will not get the signal.
1014 And in GDB replay mode, GDB doesn't need to be in terminal_inferior
1015 mode, because inferior will not executed.
1016 Then set it to terminal_ours to make GDB get the signal. */
1017 target_terminal_ours ();
1018
1019 /* In EXEC_FORWARD mode, record_list points to the tail of prev
1020 instruction. */
1021 if (execution_direction == EXEC_FORWARD && record_list->next)
1022 record_list = record_list->next;
1023
1024 /* Loop over the record_list, looking for the next place to
1025 stop. */
1026 do
1027 {
1028 /* Check for beginning and end of log. */
1029 if (execution_direction == EXEC_REVERSE
1030 && record_list == &record_first)
1031 {
1032 /* Hit beginning of record log in reverse. */
1033 status->kind = TARGET_WAITKIND_NO_HISTORY;
1034 break;
1035 }
1036 if (execution_direction != EXEC_REVERSE && !record_list->next)
1037 {
1038 /* Hit end of record log going forward. */
1039 status->kind = TARGET_WAITKIND_NO_HISTORY;
1040 break;
1041 }
1042
90ca0479
MS
1043 record_exec_insn (regcache, gdbarch, record_list);
1044
1045 if (record_list->type == record_end)
69d05d38
HZ
1046 {
1047 if (record_debug > 1)
1048 fprintf_unfiltered (gdb_stdlog,
1049 "Process record: record_end %s to "
1050 "inferior.\n",
1051 host_address_to_string (record_list));
1052
1053 if (first_record_end && execution_direction == EXEC_REVERSE)
1054 {
1055 /* When reverse excute, the first record_end is the part of
1056 current instruction. */
1057 first_record_end = 0;
1058 }
1059 else
1060 {
1061 /* In EXEC_REVERSE mode, this is the record_end of prev
1062 instruction.
1063 In EXEC_FORWARD mode, this is the record_end of current
1064 instruction. */
1065 /* step */
1066 if (record_resume_step)
1067 {
1068 if (record_debug > 1)
1069 fprintf_unfiltered (gdb_stdlog,
1070 "Process record: step.\n");
1071 continue_flag = 0;
1072 }
1073
1074 /* check breakpoint */
1075 tmp_pc = regcache_read_pc (regcache);
6c95b8df
PA
1076 if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
1077 tmp_pc))
69d05d38
HZ
1078 {
1079 if (record_debug)
1080 fprintf_unfiltered (gdb_stdlog,
1081 "Process record: break "
5af949e3
UW
1082 "at %s.\n",
1083 paddress (gdbarch, tmp_pc));
1084 if (gdbarch_decr_pc_after_break (gdbarch)
69d05d38
HZ
1085 && execution_direction == EXEC_FORWARD
1086 && !record_resume_step)
1087 regcache_write_pc (regcache,
1088 tmp_pc +
5af949e3 1089 gdbarch_decr_pc_after_break (gdbarch));
69d05d38
HZ
1090 continue_flag = 0;
1091 }
8b739a96
HZ
1092 /* Check target signal */
1093 if (record_list->u.end.sigval != TARGET_SIGNAL_0)
1094 /* FIXME: better way to check */
1095 continue_flag = 0;
69d05d38
HZ
1096 }
1097 }
1098
1099 if (continue_flag)
1100 {
1101 if (execution_direction == EXEC_REVERSE)
1102 {
1103 if (record_list->prev)
1104 record_list = record_list->prev;
1105 }
1106 else
1107 {
1108 if (record_list->next)
1109 record_list = record_list->next;
1110 }
1111 }
1112 }
1113 while (continue_flag);
1114
1115 signal (SIGINT, handle_sigint);
1116
1117replay_out:
1118 if (record_get_sig)
1119 status->value.sig = TARGET_SIGNAL_INT;
8b739a96
HZ
1120 else if (record_list->u.end.sigval != TARGET_SIGNAL_0)
1121 /* FIXME: better way to check */
1122 status->value.sig = record_list->u.end.sigval;
69d05d38
HZ
1123 else
1124 status->value.sig = TARGET_SIGNAL_TRAP;
1125
1126 discard_cleanups (old_cleanups);
1127 }
1128
1129 do_cleanups (set_cleanups);
1130 return inferior_ptid;
1131}
1132
6df67667
MS
1133/* "to_disconnect" method for process record target. */
1134
69d05d38
HZ
1135static void
1136record_disconnect (struct target_ops *target, char *args, int from_tty)
1137{
1138 if (record_debug)
1139 fprintf_unfiltered (gdb_stdlog, "Process record: record_disconnect\n");
1140
1141 unpush_target (&record_ops);
1142 target_disconnect (args, from_tty);
1143}
1144
6df67667
MS
1145/* "to_detach" method for process record target. */
1146
69d05d38
HZ
1147static void
1148record_detach (struct target_ops *ops, char *args, int from_tty)
1149{
1150 if (record_debug)
1151 fprintf_unfiltered (gdb_stdlog, "Process record: record_detach\n");
1152
1153 unpush_target (&record_ops);
1154 target_detach (args, from_tty);
1155}
1156
6df67667
MS
1157/* "to_mourn_inferior" method for process record target. */
1158
69d05d38
HZ
1159static void
1160record_mourn_inferior (struct target_ops *ops)
1161{
1162 if (record_debug)
1163 fprintf_unfiltered (gdb_stdlog, "Process record: "
1164 "record_mourn_inferior\n");
1165
1166 unpush_target (&record_ops);
1167 target_mourn_inferior ();
1168}
1169
1170/* Close process record target before killing the inferior process. */
1171
1172static void
1173record_kill (struct target_ops *ops)
1174{
1175 if (record_debug)
1176 fprintf_unfiltered (gdb_stdlog, "Process record: record_kill\n");
1177
1178 unpush_target (&record_ops);
1179 target_kill ();
1180}
1181
1182/* Record registers change (by user or by GDB) to list as an instruction. */
1183
1184static void
1185record_registers_change (struct regcache *regcache, int regnum)
1186{
1187 /* Check record_insn_num. */
1188 record_check_insn_num (0);
1189
1190 record_arch_list_head = NULL;
1191 record_arch_list_tail = NULL;
1192
1193 if (regnum < 0)
1194 {
1195 int i;
1196 for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
1197 {
1198 if (record_arch_list_add_reg (regcache, i))
1199 {
1200 record_list_release (record_arch_list_tail);
1201 error (_("Process record: failed to record execution log."));
1202 }
1203 }
1204 }
1205 else
1206 {
1207 if (record_arch_list_add_reg (regcache, regnum))
1208 {
1209 record_list_release (record_arch_list_tail);
1210 error (_("Process record: failed to record execution log."));
1211 }
1212 }
1213 if (record_arch_list_add_end ())
1214 {
1215 record_list_release (record_arch_list_tail);
1216 error (_("Process record: failed to record execution log."));
1217 }
1218 record_list->next = record_arch_list_head;
1219 record_arch_list_head->prev = record_list;
1220 record_list = record_arch_list_tail;
1221
1222 if (record_insn_num == record_insn_max_num && record_insn_max_num)
1223 record_list_release_first ();
1224 else
1225 record_insn_num++;
1226}
1227
6df67667
MS
1228/* "to_store_registers" method for process record target. */
1229
69d05d38
HZ
1230static void
1231record_store_registers (struct target_ops *ops, struct regcache *regcache,
1232 int regno)
1233{
1234 if (!record_gdb_operation_disable)
1235 {
1236 if (RECORD_IS_REPLAY)
1237 {
1238 int n;
69d05d38
HZ
1239
1240 /* Let user choose if he wants to write register or not. */
1241 if (regno < 0)
1242 n =
604ad007
JB
1243 query (_("Because GDB is in replay mode, changing the "
1244 "value of a register will make the execution "
1245 "log unusable from this point onward. "
1246 "Change all registers?"));
69d05d38
HZ
1247 else
1248 n =
604ad007
JB
1249 query (_("Because GDB is in replay mode, changing the value "
1250 "of a register will make the execution log unusable "
1251 "from this point onward. Change register %s?"),
69d05d38
HZ
1252 gdbarch_register_name (get_regcache_arch (regcache),
1253 regno));
1254
1255 if (!n)
1256 {
1257 /* Invalidate the value of regcache that was set in function
1258 "regcache_raw_write". */
1259 if (regno < 0)
1260 {
1261 int i;
1262 for (i = 0;
1263 i < gdbarch_num_regs (get_regcache_arch (regcache));
1264 i++)
1265 regcache_invalidate (regcache, i);
1266 }
1267 else
1268 regcache_invalidate (regcache, regno);
1269
1270 error (_("Process record canceled the operation."));
1271 }
1272
1273 /* Destroy the record from here forward. */
61f75dd8 1274 record_list_release_following (record_list);
69d05d38
HZ
1275 }
1276
1277 record_registers_change (regcache, regno);
1278 }
1279 record_beneath_to_store_registers (record_beneath_to_store_registers_ops,
1280 regcache, regno);
1281}
1282
1283/* Behavior is conditional on RECORD_IS_REPLAY.
1284 In replay mode, we cannot write memory unles we are willing to
1285 invalidate the record/replay log from this point forward. */
1286
1287static LONGEST
1288record_xfer_partial (struct target_ops *ops, enum target_object object,
1289 const char *annex, gdb_byte *readbuf,
1290 const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
1291{
1292 if (!record_gdb_operation_disable
1293 && (object == TARGET_OBJECT_MEMORY
1294 || object == TARGET_OBJECT_RAW_MEMORY) && writebuf)
1295 {
1296 if (RECORD_IS_REPLAY)
1297 {
1298 /* Let user choose if he wants to write memory or not. */
604ad007
JB
1299 if (!query (_("Because GDB is in replay mode, writing to memory "
1300 "will make the execution log unusable from this "
1301 "point onward. Write memory at address %s?"),
5af949e3 1302 paddress (target_gdbarch, offset)))
9a9dc473 1303 error (_("Process record canceled the operation."));
69d05d38
HZ
1304
1305 /* Destroy the record from here forward. */
61f75dd8 1306 record_list_release_following (record_list);
69d05d38
HZ
1307 }
1308
1309 /* Check record_insn_num */
1310 record_check_insn_num (0);
1311
1312 /* Record registers change to list as an instruction. */
1313 record_arch_list_head = NULL;
1314 record_arch_list_tail = NULL;
1315 if (record_arch_list_add_mem (offset, len))
1316 {
1317 record_list_release (record_arch_list_tail);
1318 if (record_debug)
1319 fprintf_unfiltered (gdb_stdlog,
1320 _("Process record: failed to record "
1321 "execution log."));
1322 return -1;
1323 }
1324 if (record_arch_list_add_end ())
1325 {
1326 record_list_release (record_arch_list_tail);
1327 if (record_debug)
1328 fprintf_unfiltered (gdb_stdlog,
1329 _("Process record: failed to record "
1330 "execution log."));
1331 return -1;
1332 }
1333 record_list->next = record_arch_list_head;
1334 record_arch_list_head->prev = record_list;
1335 record_list = record_arch_list_tail;
1336
1337 if (record_insn_num == record_insn_max_num && record_insn_max_num)
1338 record_list_release_first ();
1339 else
1340 record_insn_num++;
1341 }
1342
1343 return record_beneath_to_xfer_partial (record_beneath_to_xfer_partial_ops,
1344 object, annex, readbuf, writebuf,
1345 offset, len);
1346}
1347
1348/* Behavior is conditional on RECORD_IS_REPLAY.
1349 We will not actually insert or remove breakpoints when replaying,
1350 nor when recording. */
1351
1352static int
a6d9a66e
UW
1353record_insert_breakpoint (struct gdbarch *gdbarch,
1354 struct bp_target_info *bp_tgt)
69d05d38
HZ
1355{
1356 if (!RECORD_IS_REPLAY)
1357 {
1358 struct cleanup *old_cleanups = record_gdb_operation_disable_set ();
a6d9a66e 1359 int ret = record_beneath_to_insert_breakpoint (gdbarch, bp_tgt);
69d05d38
HZ
1360
1361 do_cleanups (old_cleanups);
1362
1363 return ret;
1364 }
1365
1366 return 0;
1367}
1368
6df67667
MS
1369/* "to_remove_breakpoint" method for process record target. */
1370
69d05d38 1371static int
a6d9a66e
UW
1372record_remove_breakpoint (struct gdbarch *gdbarch,
1373 struct bp_target_info *bp_tgt)
69d05d38
HZ
1374{
1375 if (!RECORD_IS_REPLAY)
1376 {
1377 struct cleanup *old_cleanups = record_gdb_operation_disable_set ();
a6d9a66e 1378 int ret = record_beneath_to_remove_breakpoint (gdbarch, bp_tgt);
69d05d38
HZ
1379
1380 do_cleanups (old_cleanups);
1381
1382 return ret;
1383 }
1384
1385 return 0;
1386}
1387
6df67667 1388/* "to_can_execute_reverse" method for process record target. */
69d05d38
HZ
1389static int
1390record_can_execute_reverse (void)
1391{
1392 return 1;
1393}
1394
1395static void
1396init_record_ops (void)
1397{
1398 record_ops.to_shortname = "record";
1399 record_ops.to_longname = "Process record and replay target";
1400 record_ops.to_doc =
1401 "Log program while executing and replay execution from log.";
1402 record_ops.to_open = record_open;
1403 record_ops.to_close = record_close;
1404 record_ops.to_resume = record_resume;
1405 record_ops.to_wait = record_wait;
1406 record_ops.to_disconnect = record_disconnect;
1407 record_ops.to_detach = record_detach;
1408 record_ops.to_mourn_inferior = record_mourn_inferior;
1409 record_ops.to_kill = record_kill;
1410 record_ops.to_create_inferior = find_default_create_inferior;
1411 record_ops.to_store_registers = record_store_registers;
1412 record_ops.to_xfer_partial = record_xfer_partial;
1413 record_ops.to_insert_breakpoint = record_insert_breakpoint;
1414 record_ops.to_remove_breakpoint = record_remove_breakpoint;
1415 record_ops.to_can_execute_reverse = record_can_execute_reverse;
1416 record_ops.to_stratum = record_stratum;
1417 record_ops.to_magic = OPS_MAGIC;
1418}
1419
6df67667
MS
1420/* Implement "show record debug" command. */
1421
69d05d38
HZ
1422static void
1423show_record_debug (struct ui_file *file, int from_tty,
1424 struct cmd_list_element *c, const char *value)
1425{
1426 fprintf_filtered (file, _("Debugging of process record target is %s.\n"),
1427 value);
1428}
1429
1430/* Alias for "target record". */
1431
1432static void
1433cmd_record_start (char *args, int from_tty)
1434{
1435 execute_command ("target record", from_tty);
1436}
1437
1438/* Truncate the record log from the present point
1439 of replay until the end. */
1440
1441static void
1442cmd_record_delete (char *args, int from_tty)
1443{
1444 if (current_target.to_stratum == record_stratum)
1445 {
1446 if (RECORD_IS_REPLAY)
1447 {
1448 if (!from_tty || query (_("Delete the log from this point forward "
1449 "and begin to record the running message "
1450 "at current PC?")))
61f75dd8 1451 record_list_release_following (record_list);
69d05d38
HZ
1452 }
1453 else
1454 printf_unfiltered (_("Already at end of record list.\n"));
1455
1456 }
1457 else
1458 printf_unfiltered (_("Process record is not started.\n"));
1459}
1460
6df67667 1461/* Implement the "stoprecord" or "record stop" command. */
69d05d38
HZ
1462
1463static void
1464cmd_record_stop (char *args, int from_tty)
1465{
1466 if (current_target.to_stratum == record_stratum)
1467 {
5d40bb85 1468 unpush_target (&record_ops);
b54295a7
MS
1469 printf_unfiltered (_("Process record is stopped and all execution "
1470 "logs are deleted.\n"));
69d05d38
HZ
1471 }
1472 else
1473 printf_unfiltered (_("Process record is not started.\n"));
1474}
1475
1476/* Set upper limit of record log size. */
1477
1478static void
1479set_record_insn_max_num (char *args, int from_tty, struct cmd_list_element *c)
1480{
1481 if (record_insn_num > record_insn_max_num && record_insn_max_num)
1482 {
265aad34 1483 /* Count down record_insn_num while releasing records from list. */
69d05d38 1484 while (record_insn_num > record_insn_max_num)
265aad34
MS
1485 {
1486 record_list_release_first ();
1487 record_insn_num--;
1488 }
69d05d38
HZ
1489 }
1490}
1491
69d05d38
HZ
1492static struct cmd_list_element *record_cmdlist, *set_record_cmdlist,
1493 *show_record_cmdlist, *info_record_cmdlist;
1494
1495static void
1496set_record_command (char *args, int from_tty)
1497{
1498 printf_unfiltered (_("\
1499\"set record\" must be followed by an apporpriate subcommand.\n"));
1500 help_list (set_record_cmdlist, "set record ", all_commands, gdb_stdout);
1501}
1502
1503static void
1504show_record_command (char *args, int from_tty)
1505{
1506 cmd_show_list (show_record_cmdlist, from_tty, "");
1507}
1508
b54295a7
MS
1509/* Display some statistics about the execution log. */
1510
69d05d38
HZ
1511static void
1512info_record_command (char *args, int from_tty)
1513{
b54295a7
MS
1514 struct record_entry *p;
1515
1516 if (current_target.to_stratum == record_stratum)
1517 {
1518 if (RECORD_IS_REPLAY)
1519 printf_filtered (_("Replay mode:\n"));
1520 else
1521 printf_filtered (_("Record mode:\n"));
1522
1523 /* Find entry for first actual instruction in the log. */
1524 for (p = record_first.next;
1525 p != NULL && p->type != record_end;
1526 p = p->next)
1527 ;
1528
1529 /* Do we have a log at all? */
1530 if (p != NULL && p->type == record_end)
1531 {
1532 /* Display instruction number for first instruction in the log. */
1533 printf_filtered (_("Lowest recorded instruction number is %s.\n"),
1534 pulongest (p->u.end.insn_num));
1535
1536 /* If in replay mode, display where we are in the log. */
1537 if (RECORD_IS_REPLAY)
1538 printf_filtered (_("Current instruction number is %s.\n"),
1539 pulongest (record_list->u.end.insn_num));
1540
1541 /* Display instruction number for last instruction in the log. */
1542 printf_filtered (_("Highest recorded instruction number is %s.\n"),
1543 pulongest (record_insn_count));
1544
1545 /* Display log count. */
1546 printf_filtered (_("Log contains %d instructions.\n"),
1547 record_insn_num);
1548 }
1549 else
1550 {
1551 printf_filtered (_("No instructions have been logged.\n"));
1552 }
1553 }
1554 else
1555 {
1556 printf_filtered (_("target record is not active.\n"));
1557 }
1558
1559 /* Display max log size. */
1560 printf_filtered (_("Max logged instructions is %d.\n"),
1561 record_insn_max_num);
69d05d38
HZ
1562}
1563
1564void
1565_initialize_record (void)
1566{
1567 /* Init record_first. */
1568 record_first.prev = NULL;
1569 record_first.next = NULL;
1570 record_first.type = record_end;
1571
1572 init_record_ops ();
1573 add_target (&record_ops);
1574
1575 add_setshow_zinteger_cmd ("record", no_class, &record_debug,
1576 _("Set debugging of record/replay feature."),
1577 _("Show debugging of record/replay feature."),
1578 _("When enabled, debugging output for "
1579 "record/replay feature is displayed."),
1580 NULL, show_record_debug, &setdebuglist,
1581 &showdebuglist);
1582
1583 add_prefix_cmd ("record", class_obscure, cmd_record_start,
1584 _("Abbreviated form of \"target record\" command."),
1585 &record_cmdlist, "record ", 0, &cmdlist);
1586 add_com_alias ("rec", "record", class_obscure, 1);
1587 add_prefix_cmd ("record", class_support, set_record_command,
1588 _("Set record options"), &set_record_cmdlist,
1589 "set record ", 0, &setlist);
1590 add_alias_cmd ("rec", "record", class_obscure, 1, &setlist);
1591 add_prefix_cmd ("record", class_support, show_record_command,
1592 _("Show record options"), &show_record_cmdlist,
1593 "show record ", 0, &showlist);
1594 add_alias_cmd ("rec", "record", class_obscure, 1, &showlist);
1595 add_prefix_cmd ("record", class_support, info_record_command,
1596 _("Info record options"), &info_record_cmdlist,
1597 "info record ", 0, &infolist);
1598 add_alias_cmd ("rec", "record", class_obscure, 1, &infolist);
1599
1600
1601 add_cmd ("delete", class_obscure, cmd_record_delete,
1602 _("Delete the rest of execution log and start recording it anew."),
1603 &record_cmdlist);
1604 add_alias_cmd ("d", "delete", class_obscure, 1, &record_cmdlist);
1605 add_alias_cmd ("del", "delete", class_obscure, 1, &record_cmdlist);
1606
1607 add_cmd ("stop", class_obscure, cmd_record_stop,
1608 _("Stop the record/replay target."),
1609 &record_cmdlist);
1610 add_alias_cmd ("s", "stop", class_obscure, 1, &record_cmdlist);
1611
1612 /* Record instructions number limit command. */
1613 add_setshow_boolean_cmd ("stop-at-limit", no_class,
fda458ee 1614 &record_stop_at_limit, _("\
299a410e
EZ
1615Set whether record/replay stops when record/replay buffer becomes full."), _("\
1616Show whether record/replay stops when record/replay buffer becomes full."), _("\
1617Default is ON.\n\
1618When ON, if the record/replay buffer becomes full, ask user what to do.\n\
1619When OFF, if the record/replay buffer becomes full,\n\
1620delete the oldest recorded instruction to make room for each new one."),
fda458ee
MS
1621 NULL, NULL,
1622 &set_record_cmdlist, &show_record_cmdlist);
191e1813 1623 add_setshow_uinteger_cmd ("insn-number-max", no_class,
69d05d38
HZ
1624 &record_insn_max_num,
1625 _("Set record/replay buffer limit."),
299a410e
EZ
1626 _("Show record/replay buffer limit."), _("\
1627Set the maximum number of instructions to be stored in the\n\
1628record/replay buffer. Zero means unlimited. Default is 200000."),
69d05d38
HZ
1629 set_record_insn_max_num,
1630 NULL, &set_record_cmdlist, &show_record_cmdlist);
69d05d38 1631}
This page took 0.243421 seconds and 4 git commands to generate.