]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/record-full.c
[gdb] Fix segfault in for_each_block, part 1
[thirdparty/binutils-gdb.git] / gdb / record-full.c
CommitLineData
d02ed0bb
MM
1/* Process record and replay target for GDB, the GNU debugger.
2
213516ef 3 Copyright (C) 2013-2023 Free Software Foundation, Inc.
d02ed0bb
MM
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"
00431a78 24#include "inferior.h"
d02ed0bb 25#include "event-top.h"
d02ed0bb
MM
26#include "completer.h"
27#include "arch-utils.h"
28#include "gdbcore.h"
29#include "exec.h"
30#include "record.h"
31#include "record-full.h"
32#include "elf-bfd.h"
33#include "gcore.h"
400b5eca 34#include "gdbsupport/event-loop.h"
d02ed0bb
MM
35#include "inf-loop.h"
36#include "gdb_bfd.h"
76727919 37#include "observable.h"
45741a9c 38#include "infrun.h"
268a13a5
TT
39#include "gdbsupport/gdb_unlinker.h"
40#include "gdbsupport/byte-vector.h"
93b54c8e 41#include "async-event.h"
e24d337e 42#include "valprint.h"
44fbffc6 43#include "interps.h"
d02ed0bb
MM
44
45#include <signal.h>
46
47/* This module implements "target record-full", also known as "process
48 record and replay". This target sits on top of a "normal" target
49 (a target that "has execution"), and provides a record and replay
50 functionality, including reverse debugging.
51
52 Target record has two modes: recording, and replaying.
53
f6ac5f3d 54 In record mode, we intercept the resume and wait methods.
d02ed0bb
MM
55 Whenever gdb resumes the target, we run the target in single step
56 mode, and we build up an execution log in which, for each executed
57 instruction, we record all changes in memory and register state.
58 This is invisible to the user, to whom it just looks like an
30baf67b 59 ordinary debugging session (except for performance degradation).
d02ed0bb
MM
60
61 In replay mode, instead of actually letting the inferior run as a
62 process, we simulate its execution by playing back the recorded
63 execution log. For each instruction in the log, we simulate the
64 instruction's side effects by duplicating the changes that it would
65 have made on memory and registers. */
66
88d1aa9d 67#define DEFAULT_RECORD_FULL_INSN_MAX_NUM 200000
d02ed0bb 68
88d1aa9d 69#define RECORD_FULL_IS_REPLAY \
f6ac5f3d 70 (record_full_list->next || ::execution_direction == EXEC_REVERSE)
d02ed0bb 71
88d1aa9d 72#define RECORD_FULL_FILE_MAGIC netorder32(0x20091016)
d02ed0bb
MM
73
74/* These are the core structs of the process record functionality.
75
88d1aa9d
MM
76 A record_full_entry is a record of the value change of a register
77 ("record_full_reg") or a part of memory ("record_full_mem"). And each
78 instruction must have a struct record_full_entry ("record_full_end")
79 that indicates that this is the last struct record_full_entry of this
d02ed0bb
MM
80 instruction.
81
88d1aa9d
MM
82 Each struct record_full_entry is linked to "record_full_list" by "prev"
83 and "next" pointers. */
d02ed0bb 84
88d1aa9d 85struct record_full_mem_entry
d02ed0bb
MM
86{
87 CORE_ADDR addr;
88 int len;
89 /* Set this flag if target memory for this entry
90 can no longer be accessed. */
91 int mem_entry_not_accessible;
92 union
93 {
94 gdb_byte *ptr;
95 gdb_byte buf[sizeof (gdb_byte *)];
96 } u;
97};
98
88d1aa9d 99struct record_full_reg_entry
d02ed0bb
MM
100{
101 unsigned short num;
102 unsigned short len;
103 union
104 {
105 gdb_byte *ptr;
106 gdb_byte buf[2 * sizeof (gdb_byte *)];
107 } u;
108};
109
88d1aa9d 110struct record_full_end_entry
d02ed0bb
MM
111{
112 enum gdb_signal sigval;
113 ULONGEST insn_num;
114};
115
88d1aa9d 116enum record_full_type
d02ed0bb 117{
88d1aa9d
MM
118 record_full_end = 0,
119 record_full_reg,
120 record_full_mem
d02ed0bb
MM
121};
122
123/* This is the data structure that makes up the execution log.
124
125 The execution log consists of a single linked list of entries
88d1aa9d 126 of type "struct record_full_entry". It is doubly linked so that it
d02ed0bb
MM
127 can be traversed in either direction.
128
129 The start of the list is anchored by a struct called
88d1aa9d
MM
130 "record_full_first". The pointer "record_full_list" either points
131 to the last entry that was added to the list (in record mode), or to
132 the next entry in the list that will be executed (in replay mode).
d02ed0bb 133
88d1aa9d
MM
134 Each list element (struct record_full_entry), in addition to next
135 and prev pointers, consists of a union of three entry types: mem,
136 reg, and end. A field called "type" determines which entry type is
d02ed0bb
MM
137 represented by a given list element.
138
139 Each instruction that is added to the execution log is represented
140 by a variable number of list elements ('entries'). The instruction
141 will have one "reg" entry for each register that is changed by
142 executing the instruction (including the PC in every case). It
143 will also have one "mem" entry for each memory change. Finally,
144 each instruction will have an "end" entry that separates it from
145 the changes associated with the next instruction. */
146
88d1aa9d 147struct record_full_entry
d02ed0bb 148{
88d1aa9d
MM
149 struct record_full_entry *prev;
150 struct record_full_entry *next;
151 enum record_full_type type;
d02ed0bb
MM
152 union
153 {
154 /* reg */
88d1aa9d 155 struct record_full_reg_entry reg;
d02ed0bb 156 /* mem */
88d1aa9d 157 struct record_full_mem_entry mem;
d02ed0bb 158 /* end */
88d1aa9d 159 struct record_full_end_entry end;
d02ed0bb
MM
160 } u;
161};
162
163/* If true, query if PREC cannot record memory
164 change of next instruction. */
491144b5 165bool record_full_memory_query = false;
d02ed0bb 166
88d1aa9d 167struct record_full_core_buf_entry
d02ed0bb 168{
88d1aa9d 169 struct record_full_core_buf_entry *prev;
d02ed0bb
MM
170 struct target_section *p;
171 bfd_byte *buf;
172};
173
174/* Record buf with core target. */
c8ec2f33 175static detached_regcache *record_full_core_regbuf = NULL;
25b5a04e 176static std::vector<target_section> record_full_core_sections;
88d1aa9d 177static struct record_full_core_buf_entry *record_full_core_buf_list = NULL;
d02ed0bb
MM
178
179/* The following variables are used for managing the linked list that
180 represents the execution log.
181
88d1aa9d
MM
182 record_full_first is the anchor that holds down the beginning of
183 the list.
d02ed0bb 184
88d1aa9d 185 record_full_list serves two functions:
d02ed0bb
MM
186 1) In record mode, it anchors the end of the list.
187 2) In replay mode, it traverses the list and points to
dda83cd7 188 the next instruction that must be emulated.
d02ed0bb 189
88d1aa9d
MM
190 record_full_arch_list_head and record_full_arch_list_tail are used
191 to manage a separate list, which is used to build up the change
192 elements of the currently executing instruction during record mode.
193 When this instruction has been completely annotated in the "arch
194 list", it will be appended to the main execution log. */
d02ed0bb 195
88d1aa9d
MM
196static struct record_full_entry record_full_first;
197static struct record_full_entry *record_full_list = &record_full_first;
198static struct record_full_entry *record_full_arch_list_head = NULL;
199static struct record_full_entry *record_full_arch_list_tail = NULL;
d02ed0bb 200
491144b5
CB
201/* true ask user. false auto delete the last struct record_full_entry. */
202static bool record_full_stop_at_limit = true;
d02ed0bb 203/* Maximum allowed number of insns in execution log. */
88d1aa9d
MM
204static unsigned int record_full_insn_max_num
205 = DEFAULT_RECORD_FULL_INSN_MAX_NUM;
d02ed0bb 206/* Actual count of insns presently in execution log. */
7ee70bf5 207static unsigned int record_full_insn_num = 0;
d02ed0bb
MM
208/* Count of insns logged so far (may be larger
209 than count of insns presently in execution log). */
88d1aa9d 210static ULONGEST record_full_insn_count;
d02ed0bb 211
d9f719f1
PA
212static const char record_longname[]
213 = N_("Process record and replay target");
214static const char record_doc[]
215 = N_("Log program while executing and replay execution from log.");
216
f6ac5f3d
PA
217/* Base class implementing functionality common to both the
218 "record-full" and "record-core" targets. */
219
220class record_full_base_target : public target_ops
221{
222public:
d9f719f1 223 const target_info &info () const override = 0;
f6ac5f3d 224
66b4deae
PA
225 strata stratum () const override { return record_stratum; }
226
f6ac5f3d 227 void close () override;
4a570176 228 void async (bool) override;
b60cea74 229 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
57810aa7
PA
230 bool stopped_by_watchpoint () override;
231 bool stopped_data_address (CORE_ADDR *) override;
f6ac5f3d 232
57810aa7
PA
233 bool stopped_by_sw_breakpoint () override;
234 bool supports_stopped_by_sw_breakpoint () override;
f6ac5f3d 235
57810aa7
PA
236 bool stopped_by_hw_breakpoint () override;
237 bool supports_stopped_by_hw_breakpoint () override;
f6ac5f3d 238
57810aa7 239 bool can_execute_reverse () override;
f6ac5f3d
PA
240
241 /* Add bookmark target methods. */
242 gdb_byte *get_bookmark (const char *, int) override;
243 void goto_bookmark (const gdb_byte *, int) override;
244 enum exec_direction_kind execution_direction () override;
245 enum record_method record_method (ptid_t ptid) override;
246 void info_record () override;
247 void save_record (const char *filename) override;
248 bool supports_delete_record () override;
249 void delete_record () override;
57810aa7
PA
250 bool record_is_replaying (ptid_t ptid) override;
251 bool record_will_replay (ptid_t ptid, int dir) override;
f6ac5f3d
PA
252 void record_stop_replaying () override;
253 void goto_record_begin () override;
254 void goto_record_end () override;
255 void goto_record (ULONGEST insn) override;
256};
257
258/* The "record-full" target. */
259
d9f719f1
PA
260static const target_info record_full_target_info = {
261 "record-full",
262 record_longname,
263 record_doc,
264};
265
f6ac5f3d
PA
266class record_full_target final : public record_full_base_target
267{
268public:
d9f719f1
PA
269 const target_info &info () const override
270 { return record_full_target_info; }
f6ac5f3d 271
f6ac5f3d
PA
272 void resume (ptid_t, int, enum gdb_signal) override;
273 void disconnect (const char *, int) override;
274 void detach (inferior *, int) override;
275 void mourn_inferior () override;
276 void kill () override;
277 void store_registers (struct regcache *, int) override;
278 enum target_xfer_status xfer_partial (enum target_object object,
279 const char *annex,
280 gdb_byte *readbuf,
281 const gdb_byte *writebuf,
282 ULONGEST offset, ULONGEST len,
283 ULONGEST *xfered_len) override;
284 int insert_breakpoint (struct gdbarch *,
285 struct bp_target_info *) override;
286 int remove_breakpoint (struct gdbarch *,
287 struct bp_target_info *,
288 enum remove_bp_reason) override;
289};
290
291/* The "record-core" target. */
292
d9f719f1
PA
293static const target_info record_full_core_target_info = {
294 "record-core",
295 record_longname,
296 record_doc,
297};
298
f6ac5f3d
PA
299class record_full_core_target final : public record_full_base_target
300{
301public:
d9f719f1
PA
302 const target_info &info () const override
303 { return record_full_core_target_info; }
f6ac5f3d
PA
304
305 void resume (ptid_t, int, enum gdb_signal) override;
306 void disconnect (const char *, int) override;
307 void kill () override;
308 void fetch_registers (struct regcache *regcache, int regno) override;
309 void prepare_to_store (struct regcache *regcache) override;
310 void store_registers (struct regcache *, int) override;
311 enum target_xfer_status xfer_partial (enum target_object object,
312 const char *annex,
313 gdb_byte *readbuf,
314 const gdb_byte *writebuf,
315 ULONGEST offset, ULONGEST len,
316 ULONGEST *xfered_len) override;
317 int insert_breakpoint (struct gdbarch *,
318 struct bp_target_info *) override;
319 int remove_breakpoint (struct gdbarch *,
320 struct bp_target_info *,
321 enum remove_bp_reason) override;
322
5018ce90 323 bool has_execution (inferior *inf) override;
f6ac5f3d
PA
324};
325
326static record_full_target record_full_ops;
327static record_full_core_target record_full_core_ops;
328
329void
330record_full_target::detach (inferior *inf, int from_tty)
331{
332 record_detach (this, inf, from_tty);
333}
334
335void
336record_full_target::disconnect (const char *args, int from_tty)
337{
338 record_disconnect (this, args, from_tty);
339}
340
341void
342record_full_core_target::disconnect (const char *args, int from_tty)
343{
344 record_disconnect (this, args, from_tty);
345}
346
347void
348record_full_target::mourn_inferior ()
349{
350 record_mourn_inferior (this);
351}
352
353void
354record_full_target::kill ()
355{
356 record_kill (this);
357}
d02ed0bb 358
8213266a
PA
359/* See record-full.h. */
360
361int
362record_full_is_used (void)
363{
364 struct target_ops *t;
365
366 t = find_record_target ();
367 return (t == &record_full_ops
368 || t == &record_full_core_ops);
369}
370
371
d02ed0bb
MM
372/* Command lists for "set/show record full". */
373static struct cmd_list_element *set_record_full_cmdlist;
374static struct cmd_list_element *show_record_full_cmdlist;
375
376/* Command list for "record full". */
377static struct cmd_list_element *record_full_cmdlist;
378
88d1aa9d
MM
379static void record_full_goto_insn (struct record_full_entry *entry,
380 enum exec_direction_kind dir);
88d1aa9d
MM
381
382/* Alloc and free functions for record_full_reg, record_full_mem, and
383 record_full_end entries. */
384
385/* Alloc a record_full_reg record entry. */
386
387static inline struct record_full_entry *
388record_full_reg_alloc (struct regcache *regcache, int regnum)
389{
390 struct record_full_entry *rec;
ac7936df 391 struct gdbarch *gdbarch = regcache->arch ();
d02ed0bb 392
8d749320 393 rec = XCNEW (struct record_full_entry);
88d1aa9d 394 rec->type = record_full_reg;
d02ed0bb
MM
395 rec->u.reg.num = regnum;
396 rec->u.reg.len = register_size (gdbarch, regnum);
397 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
398 rec->u.reg.u.ptr = (gdb_byte *) xmalloc (rec->u.reg.len);
399
400 return rec;
401}
402
88d1aa9d 403/* Free a record_full_reg record entry. */
d02ed0bb
MM
404
405static inline void
88d1aa9d 406record_full_reg_release (struct record_full_entry *rec)
d02ed0bb 407{
88d1aa9d 408 gdb_assert (rec->type == record_full_reg);
d02ed0bb
MM
409 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
410 xfree (rec->u.reg.u.ptr);
411 xfree (rec);
412}
413
88d1aa9d 414/* Alloc a record_full_mem record entry. */
d02ed0bb 415
88d1aa9d
MM
416static inline struct record_full_entry *
417record_full_mem_alloc (CORE_ADDR addr, int len)
d02ed0bb 418{
88d1aa9d 419 struct record_full_entry *rec;
d02ed0bb 420
8d749320 421 rec = XCNEW (struct record_full_entry);
88d1aa9d 422 rec->type = record_full_mem;
d02ed0bb
MM
423 rec->u.mem.addr = addr;
424 rec->u.mem.len = len;
425 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
426 rec->u.mem.u.ptr = (gdb_byte *) xmalloc (len);
427
428 return rec;
429}
430
88d1aa9d 431/* Free a record_full_mem record entry. */
d02ed0bb
MM
432
433static inline void
88d1aa9d 434record_full_mem_release (struct record_full_entry *rec)
d02ed0bb 435{
88d1aa9d 436 gdb_assert (rec->type == record_full_mem);
d02ed0bb
MM
437 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
438 xfree (rec->u.mem.u.ptr);
439 xfree (rec);
440}
441
88d1aa9d 442/* Alloc a record_full_end record entry. */
d02ed0bb 443
88d1aa9d
MM
444static inline struct record_full_entry *
445record_full_end_alloc (void)
d02ed0bb 446{
88d1aa9d 447 struct record_full_entry *rec;
d02ed0bb 448
8d749320 449 rec = XCNEW (struct record_full_entry);
88d1aa9d 450 rec->type = record_full_end;
d02ed0bb
MM
451
452 return rec;
453}
454
88d1aa9d 455/* Free a record_full_end record entry. */
d02ed0bb
MM
456
457static inline void
88d1aa9d 458record_full_end_release (struct record_full_entry *rec)
d02ed0bb
MM
459{
460 xfree (rec);
461}
462
463/* Free one record entry, any type.
464 Return entry->type, in case caller wants to know. */
465
88d1aa9d
MM
466static inline enum record_full_type
467record_full_entry_release (struct record_full_entry *rec)
d02ed0bb 468{
88d1aa9d 469 enum record_full_type type = rec->type;
d02ed0bb
MM
470
471 switch (type) {
88d1aa9d
MM
472 case record_full_reg:
473 record_full_reg_release (rec);
d02ed0bb 474 break;
88d1aa9d
MM
475 case record_full_mem:
476 record_full_mem_release (rec);
d02ed0bb 477 break;
88d1aa9d
MM
478 case record_full_end:
479 record_full_end_release (rec);
d02ed0bb
MM
480 break;
481 }
482 return type;
483}
484
485/* Free all record entries in list pointed to by REC. */
486
487static void
88d1aa9d 488record_full_list_release (struct record_full_entry *rec)
d02ed0bb
MM
489{
490 if (!rec)
491 return;
492
493 while (rec->next)
494 rec = rec->next;
495
496 while (rec->prev)
497 {
498 rec = rec->prev;
88d1aa9d 499 record_full_entry_release (rec->next);
d02ed0bb
MM
500 }
501
88d1aa9d 502 if (rec == &record_full_first)
d02ed0bb 503 {
88d1aa9d
MM
504 record_full_insn_num = 0;
505 record_full_first.next = NULL;
d02ed0bb
MM
506 }
507 else
88d1aa9d 508 record_full_entry_release (rec);
d02ed0bb
MM
509}
510
511/* Free all record entries forward of the given list position. */
512
513static void
88d1aa9d 514record_full_list_release_following (struct record_full_entry *rec)
d02ed0bb 515{
88d1aa9d 516 struct record_full_entry *tmp = rec->next;
d02ed0bb
MM
517
518 rec->next = NULL;
519 while (tmp)
520 {
521 rec = tmp->next;
88d1aa9d 522 if (record_full_entry_release (tmp) == record_full_end)
d02ed0bb 523 {
88d1aa9d
MM
524 record_full_insn_num--;
525 record_full_insn_count--;
d02ed0bb
MM
526 }
527 tmp = rec;
528 }
529}
530
531/* Delete the first instruction from the beginning of the log, to make
532 room for adding a new instruction at the end of the log.
533
88d1aa9d 534 Note -- this function does not modify record_full_insn_num. */
d02ed0bb
MM
535
536static void
88d1aa9d 537record_full_list_release_first (void)
d02ed0bb 538{
88d1aa9d 539 struct record_full_entry *tmp;
d02ed0bb 540
88d1aa9d 541 if (!record_full_first.next)
d02ed0bb
MM
542 return;
543
88d1aa9d 544 /* Loop until a record_full_end. */
d02ed0bb
MM
545 while (1)
546 {
88d1aa9d
MM
547 /* Cut record_full_first.next out of the linked list. */
548 tmp = record_full_first.next;
549 record_full_first.next = tmp->next;
550 tmp->next->prev = &record_full_first;
d02ed0bb
MM
551
552 /* tmp is now isolated, and can be deleted. */
88d1aa9d
MM
553 if (record_full_entry_release (tmp) == record_full_end)
554 break; /* End loop at first record_full_end. */
d02ed0bb 555
88d1aa9d 556 if (!record_full_first.next)
d02ed0bb 557 {
88d1aa9d 558 gdb_assert (record_full_insn_num == 1);
d02ed0bb
MM
559 break; /* End loop when list is empty. */
560 }
561 }
562}
563
88d1aa9d 564/* Add a struct record_full_entry to record_full_arch_list. */
d02ed0bb
MM
565
566static void
88d1aa9d 567record_full_arch_list_add (struct record_full_entry *rec)
d02ed0bb
MM
568{
569 if (record_debug > 1)
6cb06a8c
TT
570 gdb_printf (gdb_stdlog,
571 "Process record: record_full_arch_list_add %s.\n",
572 host_address_to_string (rec));
d02ed0bb 573
88d1aa9d 574 if (record_full_arch_list_tail)
d02ed0bb 575 {
88d1aa9d
MM
576 record_full_arch_list_tail->next = rec;
577 rec->prev = record_full_arch_list_tail;
578 record_full_arch_list_tail = rec;
d02ed0bb
MM
579 }
580 else
581 {
88d1aa9d
MM
582 record_full_arch_list_head = rec;
583 record_full_arch_list_tail = rec;
d02ed0bb
MM
584 }
585}
586
587/* Return the value storage location of a record entry. */
588static inline gdb_byte *
88d1aa9d 589record_full_get_loc (struct record_full_entry *rec)
d02ed0bb
MM
590{
591 switch (rec->type) {
88d1aa9d 592 case record_full_mem:
d02ed0bb
MM
593 if (rec->u.mem.len > sizeof (rec->u.mem.u.buf))
594 return rec->u.mem.u.ptr;
595 else
596 return rec->u.mem.u.buf;
88d1aa9d 597 case record_full_reg:
d02ed0bb
MM
598 if (rec->u.reg.len > sizeof (rec->u.reg.u.buf))
599 return rec->u.reg.u.ptr;
600 else
601 return rec->u.reg.u.buf;
88d1aa9d 602 case record_full_end:
d02ed0bb 603 default:
88d1aa9d 604 gdb_assert_not_reached ("unexpected record_full_entry type");
d02ed0bb
MM
605 return NULL;
606 }
607}
608
88d1aa9d 609/* Record the value of a register NUM to record_full_arch_list. */
d02ed0bb
MM
610
611int
25ea693b 612record_full_arch_list_add_reg (struct regcache *regcache, int regnum)
d02ed0bb 613{
88d1aa9d 614 struct record_full_entry *rec;
d02ed0bb
MM
615
616 if (record_debug > 1)
6cb06a8c
TT
617 gdb_printf (gdb_stdlog,
618 "Process record: add register num = %d to "
619 "record list.\n",
620 regnum);
d02ed0bb 621
88d1aa9d 622 rec = record_full_reg_alloc (regcache, regnum);
d02ed0bb 623
0b883586 624 regcache->raw_read (regnum, record_full_get_loc (rec));
d02ed0bb 625
88d1aa9d 626 record_full_arch_list_add (rec);
d02ed0bb
MM
627
628 return 0;
629}
630
631/* Record the value of a region of memory whose address is ADDR and
88d1aa9d 632 length is LEN to record_full_arch_list. */
d02ed0bb
MM
633
634int
25ea693b 635record_full_arch_list_add_mem (CORE_ADDR addr, int len)
d02ed0bb 636{
88d1aa9d 637 struct record_full_entry *rec;
d02ed0bb
MM
638
639 if (record_debug > 1)
6cb06a8c
TT
640 gdb_printf (gdb_stdlog,
641 "Process record: add mem addr = %s len = %d to "
642 "record list.\n",
99d9c3b9 643 paddress (current_inferior ()->arch (), addr), len);
d02ed0bb
MM
644
645 if (!addr) /* FIXME: Why? Some arch must permit it... */
646 return 0;
647
88d1aa9d 648 rec = record_full_mem_alloc (addr, len);
d02ed0bb 649
99d9c3b9 650 if (record_read_memory (current_inferior ()->arch (), addr,
88d1aa9d 651 record_full_get_loc (rec), len))
d02ed0bb 652 {
88d1aa9d 653 record_full_mem_release (rec);
d02ed0bb
MM
654 return -1;
655 }
656
88d1aa9d 657 record_full_arch_list_add (rec);
d02ed0bb
MM
658
659 return 0;
660}
661
88d1aa9d
MM
662/* Add a record_full_end type struct record_full_entry to
663 record_full_arch_list. */
d02ed0bb
MM
664
665int
25ea693b 666record_full_arch_list_add_end (void)
d02ed0bb 667{
88d1aa9d 668 struct record_full_entry *rec;
d02ed0bb
MM
669
670 if (record_debug > 1)
6cb06a8c
TT
671 gdb_printf (gdb_stdlog,
672 "Process record: add end to arch list.\n");
d02ed0bb 673
88d1aa9d 674 rec = record_full_end_alloc ();
d02ed0bb 675 rec->u.end.sigval = GDB_SIGNAL_0;
88d1aa9d 676 rec->u.end.insn_num = ++record_full_insn_count;
d02ed0bb 677
88d1aa9d 678 record_full_arch_list_add (rec);
d02ed0bb
MM
679
680 return 0;
681}
682
683static void
651ce16a 684record_full_check_insn_num (void)
d02ed0bb 685{
7ee70bf5 686 if (record_full_insn_num == record_full_insn_max_num)
d02ed0bb 687 {
7ee70bf5
PA
688 /* Ask user what to do. */
689 if (record_full_stop_at_limit)
d02ed0bb 690 {
651ce16a 691 if (!yquery (_("Do you want to auto delete previous execution "
7ee70bf5 692 "log entries when record/replay buffer becomes "
651ce16a 693 "full (record full stop-at-limit)?")))
7ee70bf5 694 error (_("Process record: stopped by user."));
651ce16a 695 record_full_stop_at_limit = 0;
d02ed0bb
MM
696 }
697 }
698}
699
d02ed0bb
MM
700/* Before inferior step (when GDB record the running message, inferior
701 only can step), GDB will call this function to record the values to
88d1aa9d 702 record_full_list. This function will call gdbarch_process_record to
d02ed0bb 703 record the running message of inferior and set them to
88d1aa9d 704 record_full_arch_list, and add it to record_full_list. */
d02ed0bb 705
bf469271 706static void
88d1aa9d 707record_full_message (struct regcache *regcache, enum gdb_signal signal)
d02ed0bb
MM
708{
709 int ret;
ac7936df 710 struct gdbarch *gdbarch = regcache->arch ();
d02ed0bb 711
a70b8144 712 try
1ddbba9d
TT
713 {
714 record_full_arch_list_head = NULL;
715 record_full_arch_list_tail = NULL;
d02ed0bb 716
1ddbba9d
TT
717 /* Check record_full_insn_num. */
718 record_full_check_insn_num ();
719
720 /* If gdb sends a signal value to target_resume,
721 save it in the 'end' field of the previous instruction.
d02ed0bb 722
1ddbba9d
TT
723 Maybe process record should record what really happened,
724 rather than what gdb pretends has happened.
d02ed0bb 725
1ddbba9d
TT
726 So if Linux delivered the signal to the child process during
727 the record mode, we will record it and deliver it again in
728 the replay mode.
d02ed0bb 729
1ddbba9d
TT
730 If user says "ignore this signal" during the record mode, then
731 it will be ignored again during the replay mode (no matter if
732 the user says something different, like "deliver this signal"
733 during the replay mode).
d02ed0bb 734
1ddbba9d
TT
735 User should understand that nothing he does during the replay
736 mode will change the behavior of the child. If he tries,
737 then that is a user error.
d02ed0bb 738
1ddbba9d
TT
739 But we should still deliver the signal to gdb during the replay,
740 if we delivered it during the recording. Therefore we should
741 record the signal during record_full_wait, not
742 record_full_resume. */
743 if (record_full_list != &record_full_first) /* FIXME better way
744 to check */
745 {
746 gdb_assert (record_full_list->type == record_full_end);
747 record_full_list->u.end.sigval = signal;
748 }
d02ed0bb 749
1ddbba9d
TT
750 if (signal == GDB_SIGNAL_0
751 || !gdbarch_process_record_signal_p (gdbarch))
752 ret = gdbarch_process_record (gdbarch,
753 regcache,
754 regcache_read_pc (regcache));
755 else
756 ret = gdbarch_process_record_signal (gdbarch,
757 regcache,
758 signal);
759
760 if (ret > 0)
761 error (_("Process record: inferior program stopped."));
762 if (ret < 0)
763 error (_("Process record: failed to record execution log."));
764 }
230d2906 765 catch (const gdb_exception &ex)
d02ed0bb 766 {
1ddbba9d 767 record_full_list_release (record_full_arch_list_tail);
eedc3f4f 768 throw;
d02ed0bb 769 }
d02ed0bb 770
88d1aa9d
MM
771 record_full_list->next = record_full_arch_list_head;
772 record_full_arch_list_head->prev = record_full_list;
773 record_full_list = record_full_arch_list_tail;
d02ed0bb 774
7ee70bf5 775 if (record_full_insn_num == record_full_insn_max_num)
88d1aa9d 776 record_full_list_release_first ();
d02ed0bb 777 else
88d1aa9d 778 record_full_insn_num++;
d02ed0bb
MM
779}
780
bf469271 781static bool
88d1aa9d
MM
782record_full_message_wrapper_safe (struct regcache *regcache,
783 enum gdb_signal signal)
d02ed0bb 784{
a70b8144 785 try
bf469271
PA
786 {
787 record_full_message (regcache, signal);
788 }
b1ffd112 789 catch (const gdb_exception_error &ex)
bf469271
PA
790 {
791 exception_print (gdb_stderr, ex);
792 return false;
793 }
d02ed0bb 794
bf469271 795 return true;
d02ed0bb
MM
796}
797
88d1aa9d 798/* Set to 1 if record_full_store_registers and record_full_xfer_partial
d02ed0bb
MM
799 doesn't need record. */
800
88d1aa9d 801static int record_full_gdb_operation_disable = 0;
d02ed0bb 802
07036511 803scoped_restore_tmpl<int>
25ea693b 804record_full_gdb_operation_disable_set (void)
d02ed0bb 805{
07036511 806 return make_scoped_restore (&record_full_gdb_operation_disable, 1);
d02ed0bb
MM
807}
808
809/* Flag set to TRUE for target_stopped_by_watchpoint. */
9e8915c6
PA
810static enum target_stop_reason record_full_stop_reason
811 = TARGET_STOPPED_BY_NO_REASON;
d02ed0bb
MM
812
813/* Execute one instruction from the record log. Each instruction in
814 the log will be represented by an arbitrary sequence of register
815 entries and memory entries, followed by an 'end' entry. */
816
817static inline void
88d1aa9d
MM
818record_full_exec_insn (struct regcache *regcache,
819 struct gdbarch *gdbarch,
820 struct record_full_entry *entry)
d02ed0bb
MM
821{
822 switch (entry->type)
823 {
88d1aa9d 824 case record_full_reg: /* reg */
d02ed0bb 825 {
d7dcbefc 826 gdb::byte_vector reg (entry->u.reg.len);
d02ed0bb 827
dda83cd7 828 if (record_debug > 1)
6cb06a8c
TT
829 gdb_printf (gdb_stdlog,
830 "Process record: record_full_reg %s to "
831 "inferior num = %d.\n",
832 host_address_to_string (entry),
833 entry->u.reg.num);
d02ed0bb 834
dda83cd7
SM
835 regcache->cooked_read (entry->u.reg.num, reg.data ());
836 regcache->cooked_write (entry->u.reg.num, record_full_get_loc (entry));
837 memcpy (record_full_get_loc (entry), reg.data (), entry->u.reg.len);
d02ed0bb
MM
838 }
839 break;
840
88d1aa9d 841 case record_full_mem: /* mem */
d02ed0bb
MM
842 {
843 /* Nothing to do if the entry is flagged not_accessible. */
dda83cd7
SM
844 if (!entry->u.mem.mem_entry_not_accessible)
845 {
a2b2bc12 846 gdb::byte_vector mem (entry->u.mem.len);
d02ed0bb 847
dda83cd7 848 if (record_debug > 1)
6cb06a8c
TT
849 gdb_printf (gdb_stdlog,
850 "Process record: record_full_mem %s to "
851 "inferior addr = %s len = %d.\n",
852 host_address_to_string (entry),
853 paddress (gdbarch, entry->u.mem.addr),
854 entry->u.mem.len);
d02ed0bb 855
dda83cd7 856 if (record_read_memory (gdbarch,
a2b2bc12
TT
857 entry->u.mem.addr, mem.data (),
858 entry->u.mem.len))
d02ed0bb 859 entry->u.mem.mem_entry_not_accessible = 1;
dda83cd7
SM
860 else
861 {
862 if (target_write_memory (entry->u.mem.addr,
88d1aa9d 863 record_full_get_loc (entry),
d02ed0bb 864 entry->u.mem.len))
dda83cd7
SM
865 {
866 entry->u.mem.mem_entry_not_accessible = 1;
867 if (record_debug)
868 warning (_("Process record: error writing memory at "
d02ed0bb 869 "addr = %s len = %d."),
dda83cd7
SM
870 paddress (gdbarch, entry->u.mem.addr),
871 entry->u.mem.len);
872 }
873 else
d02ed0bb 874 {
a2b2bc12 875 memcpy (record_full_get_loc (entry), mem.data (),
88d1aa9d 876 entry->u.mem.len);
d02ed0bb
MM
877
878 /* We've changed memory --- check if a hardware
879 watchpoint should trap. Note that this
880 presently assumes the target beneath supports
881 continuable watchpoints. On non-continuable
882 watchpoints target, we'll want to check this
883 _before_ actually doing the memory change, and
884 not doing the change at all if the watchpoint
885 traps. */
886 if (hardware_watchpoint_inserted_in_range
f9582a22 887 (current_inferior ()->aspace.get (),
d02ed0bb 888 entry->u.mem.addr, entry->u.mem.len))
9e8915c6 889 record_full_stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
d02ed0bb 890 }
dda83cd7
SM
891 }
892 }
d02ed0bb
MM
893 }
894 break;
895 }
896}
897
88d1aa9d 898static void record_full_restore (void);
d02ed0bb
MM
899
900/* Asynchronous signal handle registered as event loop source for when
901 we have pending events ready to be passed to the core. */
902
88d1aa9d 903static struct async_event_handler *record_full_async_inferior_event_token;
d02ed0bb
MM
904
905static void
88d1aa9d 906record_full_async_inferior_event_handler (gdb_client_data data)
d02ed0bb 907{
b1a35af2 908 inferior_event_handler (INF_REG_EVENT);
d02ed0bb
MM
909}
910
d9f719f1 911/* Open the process record target for 'core' files. */
d02ed0bb
MM
912
913static void
014f9477 914record_full_core_open_1 (const char *name, int from_tty)
d02ed0bb 915{
9c742269 916 regcache *regcache = get_thread_regcache (inferior_thread ());
ac7936df 917 int regnum = gdbarch_num_regs (regcache->arch ());
d02ed0bb
MM
918 int i;
919
88d1aa9d 920 /* Get record_full_core_regbuf. */
d02ed0bb 921 target_fetch_registers (regcache, -1);
c8ec2f33
YQ
922 record_full_core_regbuf = new detached_regcache (regcache->arch (), false);
923
d02ed0bb 924 for (i = 0; i < regnum; i ++)
c8ec2f33 925 record_full_core_regbuf->raw_supply (i, *regcache);
d02ed0bb 926
2d128614 927 record_full_core_sections = build_section_table (core_bfd);
d02ed0bb 928
02980c56 929 current_inferior ()->push_target (&record_full_core_ops);
88d1aa9d 930 record_full_restore ();
d02ed0bb
MM
931}
932
d9f719f1 933/* Open the process record target for 'live' processes. */
d02ed0bb
MM
934
935static void
014f9477 936record_full_open_1 (const char *name, int from_tty)
d02ed0bb
MM
937{
938 if (record_debug)
6cb06a8c 939 gdb_printf (gdb_stdlog, "Process record: record_full_open_1\n");
d02ed0bb
MM
940
941 /* check exec */
55f6301a 942 if (!target_has_execution ())
d02ed0bb
MM
943 error (_("Process record: the program is not being run."));
944 if (non_stop)
945 error (_("Process record target can't debug inferior in non-stop mode "
946 "(non-stop)."));
947
99d9c3b9 948 if (!gdbarch_process_record_p (current_inferior ()->arch ()))
d02ed0bb
MM
949 error (_("Process record: the current architecture doesn't support "
950 "record function."));
951
02980c56 952 current_inferior ()->push_target (&record_full_ops);
d02ed0bb
MM
953}
954
88d1aa9d 955static void record_full_init_record_breakpoints (void);
d02ed0bb 956
d9f719f1 957/* Open the process record target. */
d02ed0bb 958
d9f719f1
PA
959static void
960record_full_open (const char *name, int from_tty)
d02ed0bb 961{
d02ed0bb 962 if (record_debug)
6cb06a8c 963 gdb_printf (gdb_stdlog, "Process record: record_full_open\n");
d02ed0bb 964
8213266a 965 record_preopen ();
d02ed0bb 966
d02ed0bb 967 /* Reset */
88d1aa9d
MM
968 record_full_insn_num = 0;
969 record_full_insn_count = 0;
970 record_full_list = &record_full_first;
971 record_full_list->next = NULL;
d02ed0bb 972
d02ed0bb 973 if (core_bfd)
88d1aa9d 974 record_full_core_open_1 (name, from_tty);
d02ed0bb 975 else
88d1aa9d 976 record_full_open_1 (name, from_tty);
d02ed0bb
MM
977
978 /* Register extra event sources in the event loop. */
88d1aa9d
MM
979 record_full_async_inferior_event_token
980 = create_async_event_handler (record_full_async_inferior_event_handler,
db20ebdf 981 NULL, "record-full");
d02ed0bb 982
88d1aa9d 983 record_full_init_record_breakpoints ();
d02ed0bb 984
44fbffc6 985 interps_notify_record_changed (current_inferior (), 1, "full", NULL);
d02ed0bb
MM
986}
987
f6ac5f3d 988/* "close" target method. Close the process record target. */
d02ed0bb 989
f6ac5f3d
PA
990void
991record_full_base_target::close ()
d02ed0bb 992{
88d1aa9d 993 struct record_full_core_buf_entry *entry;
d02ed0bb
MM
994
995 if (record_debug)
6cb06a8c 996 gdb_printf (gdb_stdlog, "Process record: record_full_close\n");
d02ed0bb 997
88d1aa9d 998 record_full_list_release (record_full_list);
d02ed0bb 999
88d1aa9d
MM
1000 /* Release record_full_core_regbuf. */
1001 if (record_full_core_regbuf)
d02ed0bb 1002 {
c8ec2f33 1003 delete record_full_core_regbuf;
88d1aa9d 1004 record_full_core_regbuf = NULL;
d02ed0bb
MM
1005 }
1006
88d1aa9d 1007 /* Release record_full_core_buf_list. */
ec70d8db 1008 while (record_full_core_buf_list)
d02ed0bb 1009 {
ec70d8db
PW
1010 entry = record_full_core_buf_list;
1011 record_full_core_buf_list = record_full_core_buf_list->prev;
1012 xfree (entry);
d02ed0bb
MM
1013 }
1014
88d1aa9d
MM
1015 if (record_full_async_inferior_event_token)
1016 delete_async_event_handler (&record_full_async_inferior_event_token);
d02ed0bb
MM
1017}
1018
f6ac5f3d 1019/* "async" target method. */
b7d2e916 1020
f6ac5f3d 1021void
4a570176 1022record_full_base_target::async (bool enable)
b7d2e916 1023{
6a3753b3 1024 if (enable)
b7d2e916
PA
1025 mark_async_event_handler (record_full_async_inferior_event_token);
1026 else
1027 clear_async_event_handler (record_full_async_inferior_event_token);
1028
b6a8c27b 1029 beneath ()->async (enable);
b7d2e916
PA
1030}
1031
ec506636
PA
1032/* The PTID and STEP arguments last passed to
1033 record_full_target::resume. */
1034static ptid_t record_full_resume_ptid = null_ptid;
88d1aa9d 1035static int record_full_resume_step = 0;
d02ed0bb 1036
88d1aa9d
MM
1037/* True if we've been resumed, and so each record_full_wait call should
1038 advance execution. If this is false, record_full_wait will return a
d02ed0bb 1039 TARGET_WAITKIND_IGNORE. */
88d1aa9d 1040static int record_full_resumed = 0;
d02ed0bb
MM
1041
1042/* The execution direction of the last resume we got. This is
1043 necessary for async mode. Vis (order is not strictly accurate):
1044
1045 1. user has the global execution direction set to forward
1046 2. user does a reverse-step command
88d1aa9d 1047 3. record_full_resume is called with global execution direction
d02ed0bb
MM
1048 temporarily switched to reverse
1049 4. GDB's execution direction is reverted back to forward
1050 5. target record notifies event loop there's an event to handle
1051 6. infrun asks the target which direction was it going, and switches
1052 the global execution direction accordingly (to reverse)
1053 7. infrun polls an event out of the record target, and handles it
1054 8. GDB goes back to the event loop, and goto #4.
1055*/
88d1aa9d 1056static enum exec_direction_kind record_full_execution_dir = EXEC_FORWARD;
d02ed0bb 1057
f6ac5f3d 1058/* "resume" target method. Resume the process record target. */
d02ed0bb 1059
f6ac5f3d
PA
1060void
1061record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
d02ed0bb 1062{
ec506636 1063 record_full_resume_ptid = inferior_ptid;
88d1aa9d
MM
1064 record_full_resume_step = step;
1065 record_full_resumed = 1;
f6ac5f3d 1066 record_full_execution_dir = ::execution_direction;
d02ed0bb 1067
88d1aa9d 1068 if (!RECORD_FULL_IS_REPLAY)
d02ed0bb
MM
1069 {
1070 struct gdbarch *gdbarch = target_thread_architecture (ptid);
1071
9c742269 1072 record_full_message (get_thread_regcache (inferior_thread ()), signal);
d02ed0bb
MM
1073
1074 if (!step)
dda83cd7
SM
1075 {
1076 /* This is not hard single step. */
1077 if (!gdbarch_software_single_step_p (gdbarch))
1078 {
1079 /* This is a normal continue. */
1080 step = 1;
1081 }
1082 else
1083 {
1084 /* This arch supports soft single step. */
1085 if (thread_has_single_step_breakpoints_set (inferior_thread ()))
1086 {
1087 /* This is a soft single step. */
1088 record_full_resume_step = 1;
1089 }
1090 else
93f9a11f 1091 step = !insert_single_step_breakpoints (gdbarch);
dda83cd7
SM
1092 }
1093 }
d02ed0bb
MM
1094
1095 /* Make sure the target beneath reports all signals. */
adc6a863 1096 target_pass_signals ({});
d02ed0bb 1097
2a740b3b
SM
1098 /* Disable range-stepping, forcing the process target to report stops for
1099 all executed instructions, so we can record them all. */
1100 process_stratum_target *proc_target
1101 = current_inferior ()->process_target ();
1102 for (thread_info *thread : all_non_exited_threads (proc_target, ptid))
1103 thread->control.may_range_step = 0;
1104
b6a8c27b 1105 this->beneath ()->resume (ptid, step, signal);
d02ed0bb 1106 }
d02ed0bb
MM
1107}
1108
88d1aa9d 1109static int record_full_get_sig = 0;
d02ed0bb 1110
f6ac5f3d 1111/* SIGINT signal handler, registered by "wait" method. */
d02ed0bb
MM
1112
1113static void
88d1aa9d 1114record_full_sig_handler (int signo)
d02ed0bb
MM
1115{
1116 if (record_debug)
6cb06a8c 1117 gdb_printf (gdb_stdlog, "Process record: get a signal\n");
d02ed0bb
MM
1118
1119 /* It will break the running inferior in replay mode. */
88d1aa9d 1120 record_full_resume_step = 1;
d02ed0bb 1121
88d1aa9d 1122 /* It will let record_full_wait set inferior status to get the signal
d02ed0bb 1123 SIGINT. */
88d1aa9d 1124 record_full_get_sig = 1;
d02ed0bb
MM
1125}
1126
f6ac5f3d 1127/* "wait" target method for process record target.
d02ed0bb
MM
1128
1129 In record mode, the target is always run in singlestep mode
f6ac5f3d 1130 (even when gdb says to continue). The wait method intercepts
d02ed0bb
MM
1131 the stop events and determines which ones are to be passed on to
1132 gdb. Most stop events are just singlestep events that gdb is not
f6ac5f3d 1133 to know about, so the wait method just records them and keeps
d02ed0bb
MM
1134 singlestepping.
1135
1136 In replay mode, this function emulates the recorded execution log,
1137 one instruction at a time (forward or backward), and determines
1138 where to stop. */
1139
1140static ptid_t
88d1aa9d
MM
1141record_full_wait_1 (struct target_ops *ops,
1142 ptid_t ptid, struct target_waitstatus *status,
b60cea74 1143 target_wait_flags options)
d02ed0bb 1144{
07036511
TT
1145 scoped_restore restore_operation_disable
1146 = record_full_gdb_operation_disable_set ();
d02ed0bb
MM
1147
1148 if (record_debug)
6cb06a8c
TT
1149 gdb_printf (gdb_stdlog,
1150 "Process record: record_full_wait "
1151 "record_full_resume_step = %d, "
1152 "record_full_resumed = %d, direction=%s\n",
1153 record_full_resume_step, record_full_resumed,
1154 record_full_execution_dir == EXEC_FORWARD
1155 ? "forward" : "reverse");
88d1aa9d
MM
1156
1157 if (!record_full_resumed)
d02ed0bb
MM
1158 {
1159 gdb_assert ((options & TARGET_WNOHANG) != 0);
1160
1161 /* No interesting event. */
183be222 1162 status->set_ignore ();
d02ed0bb
MM
1163 return minus_one_ptid;
1164 }
1165
88d1aa9d
MM
1166 record_full_get_sig = 0;
1167 signal (SIGINT, record_full_sig_handler);
d02ed0bb 1168
9e8915c6
PA
1169 record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
1170
88d1aa9d 1171 if (!RECORD_FULL_IS_REPLAY && ops != &record_full_core_ops)
d02ed0bb 1172 {
88d1aa9d 1173 if (record_full_resume_step)
d02ed0bb
MM
1174 {
1175 /* This is a single step. */
b6a8c27b 1176 return ops->beneath ()->wait (ptid, status, options);
d02ed0bb
MM
1177 }
1178 else
1179 {
1180 /* This is not a single step. */
1181 ptid_t ret;
1182 CORE_ADDR tmp_pc;
ec506636
PA
1183 struct gdbarch *gdbarch
1184 = target_thread_architecture (record_full_resume_ptid);
d02ed0bb
MM
1185
1186 while (1)
1187 {
b6a8c27b 1188 ret = ops->beneath ()->wait (ptid, status, options);
183be222 1189 if (status->kind () == TARGET_WAITKIND_IGNORE)
d02ed0bb
MM
1190 {
1191 if (record_debug)
6cb06a8c
TT
1192 gdb_printf (gdb_stdlog,
1193 "Process record: record_full_wait "
1194 "target beneath not done yet\n");
d02ed0bb
MM
1195 return ret;
1196 }
1197
08036331 1198 for (thread_info *tp : all_non_exited_threads ())
dda83cd7 1199 delete_single_step_breakpoints (tp);
d02ed0bb 1200
88d1aa9d 1201 if (record_full_resume_step)
d02ed0bb
MM
1202 return ret;
1203
1204 /* Is this a SIGTRAP? */
183be222
SM
1205 if (status->kind () == TARGET_WAITKIND_STOPPED
1206 && status->sig () == GDB_SIGNAL_TRAP)
d02ed0bb
MM
1207 {
1208 struct regcache *regcache;
9e8915c6
PA
1209 enum target_stop_reason *stop_reason_p
1210 = &record_full_stop_reason;
d02ed0bb
MM
1211
1212 /* Yes -- this is likely our single-step finishing,
1213 but check if there's any reason the core would be
1214 interested in the event. */
1215
1216 registers_changed ();
5b6d1e4f
PA
1217 switch_to_thread (current_inferior ()->process_target (),
1218 ret);
9c742269 1219 regcache = get_thread_regcache (inferior_thread ());
d02ed0bb 1220 tmp_pc = regcache_read_pc (regcache);
f9582a22
TV
1221 const address_space *aspace
1222 = current_inferior ()->aspace.get ();
d02ed0bb
MM
1223
1224 if (target_stopped_by_watchpoint ())
1225 {
1226 /* Always interested in watchpoints. */
1227 }
9e8915c6
PA
1228 else if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
1229 stop_reason_p))
d02ed0bb
MM
1230 {
1231 /* There is a breakpoint here. Let the core
1232 handle it. */
d02ed0bb
MM
1233 }
1234 else
1235 {
1236 /* This is a single-step trap. Record the
dda83cd7
SM
1237 insn and issue another step.
1238 FIXME: this part can be a random SIGTRAP too.
1239 But GDB cannot handle it. */
1240 int step = 1;
d02ed0bb 1241
88d1aa9d
MM
1242 if (!record_full_message_wrapper_safe (regcache,
1243 GDB_SIGNAL_0))
24b21115 1244 {
183be222 1245 status->set_stopped (GDB_SIGNAL_0);
dda83cd7 1246 break;
24b21115 1247 }
d02ed0bb 1248
1192f124
SM
1249 process_stratum_target *proc_target
1250 = current_inferior ()->process_target ();
1251
dda83cd7 1252 if (gdbarch_software_single_step_p (gdbarch))
d02ed0bb
MM
1253 {
1254 /* Try to insert the software single step breakpoint.
1255 If insert success, set step to 0. */
719546c4 1256 set_executing (proc_target, inferior_ptid, false);
391c90ee
AB
1257 SCOPE_EXIT
1258 {
1259 set_executing (proc_target, inferior_ptid, true);
1260 };
93f9a11f 1261
391c90ee 1262 reinit_frame_cache ();
93f9a11f 1263 step = !insert_single_step_breakpoints (gdbarch);
d02ed0bb
MM
1264 }
1265
1266 if (record_debug)
6cb06a8c
TT
1267 gdb_printf (gdb_stdlog,
1268 "Process record: record_full_wait "
1269 "issuing one more step in the "
1270 "target beneath\n");
b6a8c27b 1271 ops->beneath ()->resume (ptid, step, GDB_SIGNAL_0);
1192f124
SM
1272 proc_target->commit_resumed_state = true;
1273 proc_target->commit_resumed ();
1274 proc_target->commit_resumed_state = false;
d02ed0bb
MM
1275 continue;
1276 }
1277 }
1278
1279 /* The inferior is broken by a breakpoint or a signal. */
1280 break;
1281 }
1282
1283 return ret;
1284 }
1285 }
1286 else
1287 {
5b6d1e4f
PA
1288 switch_to_thread (current_inferior ()->process_target (),
1289 record_full_resume_ptid);
9c742269 1290 regcache *regcache = get_thread_regcache (inferior_thread ());
ac7936df 1291 struct gdbarch *gdbarch = regcache->arch ();
f9582a22 1292 const address_space *aspace = current_inferior ()->aspace.get ();
d02ed0bb 1293 int continue_flag = 1;
88d1aa9d 1294 int first_record_full_end = 1;
d02ed0bb 1295
a70b8144 1296 try
d02ed0bb 1297 {
1ddbba9d 1298 CORE_ADDR tmp_pc;
d02ed0bb 1299
1ddbba9d 1300 record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON;
183be222 1301 status->set_stopped (GDB_SIGNAL_0);
d02ed0bb 1302
1ddbba9d
TT
1303 /* Check breakpoint when forward execute. */
1304 if (execution_direction == EXEC_FORWARD)
d02ed0bb 1305 {
1ddbba9d
TT
1306 tmp_pc = regcache_read_pc (regcache);
1307 if (record_check_stopped_by_breakpoint (aspace, tmp_pc,
1308 &record_full_stop_reason))
1309 {
1310 if (record_debug)
6cb06a8c
TT
1311 gdb_printf (gdb_stdlog,
1312 "Process record: break at %s.\n",
1313 paddress (gdbarch, tmp_pc));
1ddbba9d
TT
1314 goto replay_out;
1315 }
d02ed0bb
MM
1316 }
1317
1ddbba9d
TT
1318 /* If GDB is in terminal_inferior mode, it will not get the
1319 signal. And in GDB replay mode, GDB doesn't need to be
1320 in terminal_inferior mode, because inferior will not
1321 executed. Then set it to terminal_ours to make GDB get
1322 the signal. */
1323 target_terminal::ours ();
1324
1325 /* In EXEC_FORWARD mode, record_full_list points to the tail of prev
1326 instruction. */
1327 if (execution_direction == EXEC_FORWARD && record_full_list->next)
1328 record_full_list = record_full_list->next;
1329
1330 /* Loop over the record_full_list, looking for the next place to
1331 stop. */
1332 do
d02ed0bb 1333 {
1ddbba9d
TT
1334 /* Check for beginning and end of log. */
1335 if (execution_direction == EXEC_REVERSE
1336 && record_full_list == &record_full_first)
d02ed0bb 1337 {
1ddbba9d 1338 /* Hit beginning of record log in reverse. */
183be222 1339 status->set_no_history ();
1ddbba9d 1340 break;
d02ed0bb 1341 }
1ddbba9d
TT
1342 if (execution_direction != EXEC_REVERSE
1343 && !record_full_list->next)
1344 {
1345 /* Hit end of record log going forward. */
183be222 1346 status->set_no_history ();
1ddbba9d
TT
1347 break;
1348 }
1349
1350 record_full_exec_insn (regcache, gdbarch, record_full_list);
1351
1352 if (record_full_list->type == record_full_end)
d02ed0bb 1353 {
1ddbba9d 1354 if (record_debug > 1)
6cb06a8c 1355 gdb_printf
1ddbba9d
TT
1356 (gdb_stdlog,
1357 "Process record: record_full_end %s to "
1358 "inferior.\n",
1359 host_address_to_string (record_full_list));
1360
1361 if (first_record_full_end
1362 && execution_direction == EXEC_REVERSE)
d02ed0bb 1363 {
85102364 1364 /* When reverse execute, the first
1ddbba9d
TT
1365 record_full_end is the part of current
1366 instruction. */
1367 first_record_full_end = 0;
d02ed0bb 1368 }
1ddbba9d 1369 else
d02ed0bb 1370 {
1ddbba9d
TT
1371 /* In EXEC_REVERSE mode, this is the
1372 record_full_end of prev instruction. In
1373 EXEC_FORWARD mode, this is the
1374 record_full_end of current instruction. */
1375 /* step */
1376 if (record_full_resume_step)
1377 {
1378 if (record_debug > 1)
6cb06a8c
TT
1379 gdb_printf (gdb_stdlog,
1380 "Process record: step.\n");
1ddbba9d
TT
1381 continue_flag = 0;
1382 }
9e8915c6 1383
1ddbba9d
TT
1384 /* check breakpoint */
1385 tmp_pc = regcache_read_pc (regcache);
1386 if (record_check_stopped_by_breakpoint
1387 (aspace, tmp_pc, &record_full_stop_reason))
1388 {
1389 if (record_debug)
6cb06a8c
TT
1390 gdb_printf (gdb_stdlog,
1391 "Process record: break "
1392 "at %s.\n",
1393 paddress (gdbarch, tmp_pc));
d02ed0bb 1394
1ddbba9d
TT
1395 continue_flag = 0;
1396 }
1397
1398 if (record_full_stop_reason
1399 == TARGET_STOPPED_BY_WATCHPOINT)
1400 {
1401 if (record_debug)
6cb06a8c
TT
1402 gdb_printf (gdb_stdlog,
1403 "Process record: hit hw "
1404 "watchpoint.\n");
1ddbba9d
TT
1405 continue_flag = 0;
1406 }
1407 /* Check target signal */
1408 if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
1409 /* FIXME: better way to check */
1410 continue_flag = 0;
d02ed0bb 1411 }
d02ed0bb 1412 }
d02ed0bb 1413
1ddbba9d 1414 if (continue_flag)
d02ed0bb 1415 {
1ddbba9d
TT
1416 if (execution_direction == EXEC_REVERSE)
1417 {
1418 if (record_full_list->prev)
1419 record_full_list = record_full_list->prev;
1420 }
1421 else
1422 {
1423 if (record_full_list->next)
1424 record_full_list = record_full_list->next;
1425 }
d02ed0bb
MM
1426 }
1427 }
1ddbba9d
TT
1428 while (continue_flag);
1429
1430 replay_out:
183be222
SM
1431 if (status->kind () == TARGET_WAITKIND_STOPPED)
1432 {
1433 if (record_full_get_sig)
1434 status->set_stopped (GDB_SIGNAL_INT);
1435 else if (record_full_list->u.end.sigval != GDB_SIGNAL_0)
1436 /* FIXME: better way to check */
1437 status->set_stopped (record_full_list->u.end.sigval);
1438 else
1439 status->set_stopped (GDB_SIGNAL_TRAP);
1440 }
d02ed0bb 1441 }
230d2906 1442 catch (const gdb_exception &ex)
1ddbba9d
TT
1443 {
1444 if (execution_direction == EXEC_REVERSE)
1445 {
1446 if (record_full_list->next)
1447 record_full_list = record_full_list->next;
1448 }
1449 else
1450 record_full_list = record_full_list->prev;
d02ed0bb 1451
eedc3f4f 1452 throw;
1ddbba9d 1453 }
d02ed0bb
MM
1454 }
1455
1456 signal (SIGINT, handle_sigint);
1457
d02ed0bb
MM
1458 return inferior_ptid;
1459}
1460
f6ac5f3d
PA
1461ptid_t
1462record_full_base_target::wait (ptid_t ptid, struct target_waitstatus *status,
b60cea74 1463 target_wait_flags options)
d02ed0bb
MM
1464{
1465 ptid_t return_ptid;
1466
fdbc5215
SM
1467 clear_async_event_handler (record_full_async_inferior_event_token);
1468
f6ac5f3d 1469 return_ptid = record_full_wait_1 (this, ptid, status, options);
183be222 1470 if (status->kind () != TARGET_WAITKIND_IGNORE)
d02ed0bb
MM
1471 {
1472 /* We're reporting a stop. Make sure any spurious
1473 target_wait(WNOHANG) doesn't advance the target until the
1474 core wants us resumed again. */
88d1aa9d 1475 record_full_resumed = 0;
d02ed0bb
MM
1476 }
1477 return return_ptid;
1478}
1479
57810aa7 1480bool
f6ac5f3d 1481record_full_base_target::stopped_by_watchpoint ()
d02ed0bb 1482{
88d1aa9d 1483 if (RECORD_FULL_IS_REPLAY)
9e8915c6 1484 return record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
d02ed0bb 1485 else
b6a8c27b 1486 return beneath ()->stopped_by_watchpoint ();
d02ed0bb
MM
1487}
1488
57810aa7 1489bool
f6ac5f3d 1490record_full_base_target::stopped_data_address (CORE_ADDR *addr_p)
d02ed0bb 1491{
88d1aa9d 1492 if (RECORD_FULL_IS_REPLAY)
57810aa7 1493 return false;
d02ed0bb 1494 else
b6a8c27b 1495 return this->beneath ()->stopped_data_address (addr_p);
d02ed0bb
MM
1496}
1497
f6ac5f3d 1498/* The stopped_by_sw_breakpoint method of target record-full. */
9e8915c6 1499
57810aa7 1500bool
f6ac5f3d 1501record_full_base_target::stopped_by_sw_breakpoint ()
9e8915c6
PA
1502{
1503 return record_full_stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
1504}
1505
f6ac5f3d 1506/* The supports_stopped_by_sw_breakpoint method of target
9e8915c6
PA
1507 record-full. */
1508
57810aa7 1509bool
f6ac5f3d 1510record_full_base_target::supports_stopped_by_sw_breakpoint ()
9e8915c6 1511{
57810aa7 1512 return true;
9e8915c6
PA
1513}
1514
f6ac5f3d 1515/* The stopped_by_hw_breakpoint method of target record-full. */
9e8915c6 1516
57810aa7 1517bool
f6ac5f3d 1518record_full_base_target::stopped_by_hw_breakpoint ()
9e8915c6
PA
1519{
1520 return record_full_stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
1521}
1522
f6ac5f3d 1523/* The supports_stopped_by_sw_breakpoint method of target
9e8915c6
PA
1524 record-full. */
1525
57810aa7 1526bool
f6ac5f3d 1527record_full_base_target::supports_stopped_by_hw_breakpoint ()
9e8915c6 1528{
57810aa7 1529 return true;
9e8915c6
PA
1530}
1531
d02ed0bb
MM
1532/* Record registers change (by user or by GDB) to list as an instruction. */
1533
1534static void
88d1aa9d 1535record_full_registers_change (struct regcache *regcache, int regnum)
d02ed0bb 1536{
88d1aa9d 1537 /* Check record_full_insn_num. */
651ce16a 1538 record_full_check_insn_num ();
d02ed0bb 1539
88d1aa9d
MM
1540 record_full_arch_list_head = NULL;
1541 record_full_arch_list_tail = NULL;
d02ed0bb
MM
1542
1543 if (regnum < 0)
1544 {
1545 int i;
1546
ac7936df 1547 for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++)
d02ed0bb 1548 {
25ea693b 1549 if (record_full_arch_list_add_reg (regcache, i))
d02ed0bb 1550 {
88d1aa9d 1551 record_full_list_release (record_full_arch_list_tail);
d02ed0bb
MM
1552 error (_("Process record: failed to record execution log."));
1553 }
1554 }
1555 }
1556 else
1557 {
25ea693b 1558 if (record_full_arch_list_add_reg (regcache, regnum))
d02ed0bb 1559 {
88d1aa9d 1560 record_full_list_release (record_full_arch_list_tail);
d02ed0bb
MM
1561 error (_("Process record: failed to record execution log."));
1562 }
1563 }
25ea693b 1564 if (record_full_arch_list_add_end ())
d02ed0bb 1565 {
88d1aa9d 1566 record_full_list_release (record_full_arch_list_tail);
d02ed0bb
MM
1567 error (_("Process record: failed to record execution log."));
1568 }
88d1aa9d
MM
1569 record_full_list->next = record_full_arch_list_head;
1570 record_full_arch_list_head->prev = record_full_list;
1571 record_full_list = record_full_arch_list_tail;
d02ed0bb 1572
7ee70bf5 1573 if (record_full_insn_num == record_full_insn_max_num)
88d1aa9d 1574 record_full_list_release_first ();
d02ed0bb 1575 else
88d1aa9d 1576 record_full_insn_num++;
d02ed0bb
MM
1577}
1578
f6ac5f3d 1579/* "store_registers" method for process record target. */
d02ed0bb 1580
f6ac5f3d
PA
1581void
1582record_full_target::store_registers (struct regcache *regcache, int regno)
d02ed0bb 1583{
88d1aa9d 1584 if (!record_full_gdb_operation_disable)
d02ed0bb 1585 {
88d1aa9d 1586 if (RECORD_FULL_IS_REPLAY)
d02ed0bb
MM
1587 {
1588 int n;
1589
1590 /* Let user choose if he wants to write register or not. */
1591 if (regno < 0)
1592 n =
1593 query (_("Because GDB is in replay mode, changing the "
1594 "value of a register will make the execution "
1595 "log unusable from this point onward. "
1596 "Change all registers?"));
1597 else
1598 n =
1599 query (_("Because GDB is in replay mode, changing the value "
1600 "of a register will make the execution log unusable "
1601 "from this point onward. Change register %s?"),
ac7936df 1602 gdbarch_register_name (regcache->arch (),
d02ed0bb
MM
1603 regno));
1604
1605 if (!n)
1606 {
1607 /* Invalidate the value of regcache that was set in function
dda83cd7 1608 "regcache_raw_write". */
d02ed0bb
MM
1609 if (regno < 0)
1610 {
1611 int i;
1612
1613 for (i = 0;
ac7936df 1614 i < gdbarch_num_regs (regcache->arch ());
d02ed0bb 1615 i++)
6aa7d724 1616 regcache->invalidate (i);
d02ed0bb
MM
1617 }
1618 else
6aa7d724 1619 regcache->invalidate (regno);
d02ed0bb
MM
1620
1621 error (_("Process record canceled the operation."));
1622 }
1623
1624 /* Destroy the record from here forward. */
88d1aa9d 1625 record_full_list_release_following (record_full_list);
d02ed0bb
MM
1626 }
1627
88d1aa9d 1628 record_full_registers_change (regcache, regno);
d02ed0bb 1629 }
b6a8c27b 1630 this->beneath ()->store_registers (regcache, regno);
d02ed0bb
MM
1631}
1632
f6ac5f3d 1633/* "xfer_partial" method. Behavior is conditional on
88d1aa9d 1634 RECORD_FULL_IS_REPLAY.
d02ed0bb
MM
1635 In replay mode, we cannot write memory unles we are willing to
1636 invalidate the record/replay log from this point forward. */
1637
f6ac5f3d
PA
1638enum target_xfer_status
1639record_full_target::xfer_partial (enum target_object object,
1640 const char *annex, gdb_byte *readbuf,
1641 const gdb_byte *writebuf, ULONGEST offset,
1642 ULONGEST len, ULONGEST *xfered_len)
d02ed0bb 1643{
88d1aa9d 1644 if (!record_full_gdb_operation_disable
d02ed0bb
MM
1645 && (object == TARGET_OBJECT_MEMORY
1646 || object == TARGET_OBJECT_RAW_MEMORY) && writebuf)
1647 {
88d1aa9d 1648 if (RECORD_FULL_IS_REPLAY)
d02ed0bb
MM
1649 {
1650 /* Let user choose if he wants to write memory or not. */
1651 if (!query (_("Because GDB is in replay mode, writing to memory "
dda83cd7
SM
1652 "will make the execution log unusable from this "
1653 "point onward. Write memory at address %s?"),
99d9c3b9 1654 paddress (current_inferior ()->arch (), offset)))
d02ed0bb
MM
1655 error (_("Process record canceled the operation."));
1656
1657 /* Destroy the record from here forward. */
88d1aa9d 1658 record_full_list_release_following (record_full_list);
d02ed0bb
MM
1659 }
1660
88d1aa9d 1661 /* Check record_full_insn_num */
651ce16a 1662 record_full_check_insn_num ();
d02ed0bb
MM
1663
1664 /* Record registers change to list as an instruction. */
88d1aa9d
MM
1665 record_full_arch_list_head = NULL;
1666 record_full_arch_list_tail = NULL;
25ea693b 1667 if (record_full_arch_list_add_mem (offset, len))
d02ed0bb 1668 {
88d1aa9d 1669 record_full_list_release (record_full_arch_list_tail);
d02ed0bb 1670 if (record_debug)
6cb06a8c
TT
1671 gdb_printf (gdb_stdlog,
1672 "Process record: failed to record "
1673 "execution log.");
2ed4b548 1674 return TARGET_XFER_E_IO;
d02ed0bb 1675 }
25ea693b 1676 if (record_full_arch_list_add_end ())
d02ed0bb 1677 {
88d1aa9d 1678 record_full_list_release (record_full_arch_list_tail);
d02ed0bb 1679 if (record_debug)
6cb06a8c
TT
1680 gdb_printf (gdb_stdlog,
1681 "Process record: failed to record "
1682 "execution log.");
2ed4b548 1683 return TARGET_XFER_E_IO;
d02ed0bb 1684 }
88d1aa9d
MM
1685 record_full_list->next = record_full_arch_list_head;
1686 record_full_arch_list_head->prev = record_full_list;
1687 record_full_list = record_full_arch_list_tail;
d02ed0bb 1688
7ee70bf5 1689 if (record_full_insn_num == record_full_insn_max_num)
88d1aa9d 1690 record_full_list_release_first ();
d02ed0bb 1691 else
88d1aa9d 1692 record_full_insn_num++;
d02ed0bb
MM
1693 }
1694
b6a8c27b
PA
1695 return this->beneath ()->xfer_partial (object, annex, readbuf, writebuf,
1696 offset, len, xfered_len);
d02ed0bb
MM
1697}
1698
1699/* This structure represents a breakpoint inserted while the record
1700 target is active. We use this to know when to install/remove
1701 breakpoints in/from the target beneath. For example, a breakpoint
1702 may be inserted while recording, but removed when not replaying nor
1703 recording. In that case, the breakpoint had not been inserted on
1704 the target beneath, so we should not try to remove it there. */
1705
88d1aa9d 1706struct record_full_breakpoint
d02ed0bb 1707{
219605fd
TT
1708 record_full_breakpoint (struct address_space *address_space_,
1709 CORE_ADDR addr_,
1710 bool in_target_beneath_)
1711 : address_space (address_space_),
1712 addr (addr_),
1713 in_target_beneath (in_target_beneath_)
1714 {
1715 }
1716
d02ed0bb
MM
1717 /* The address and address space the breakpoint was set at. */
1718 struct address_space *address_space;
1719 CORE_ADDR addr;
1720
1721 /* True when the breakpoint has been also installed in the target
1722 beneath. This will be false for breakpoints set during replay or
1723 when recording. */
219605fd 1724 bool in_target_beneath;
d02ed0bb
MM
1725};
1726
d02ed0bb
MM
1727/* The list of breakpoints inserted while the record target is
1728 active. */
219605fd 1729static std::vector<record_full_breakpoint> record_full_breakpoints;
d02ed0bb 1730
88d1aa9d 1731/* Sync existing breakpoints to record_full_breakpoints. */
d02ed0bb
MM
1732
1733static void
88d1aa9d 1734record_full_init_record_breakpoints (void)
d02ed0bb 1735{
219605fd 1736 record_full_breakpoints.clear ();
d02ed0bb 1737
055c879f
SM
1738 for (bp_location *loc : all_bp_locations ())
1739 {
1740 if (loc->loc_type != bp_loc_software_breakpoint)
1741 continue;
1742
1743 if (loc->inserted)
1744 record_full_breakpoints.emplace_back
1745 (loc->target_info.placed_address_space,
1746 loc->target_info.placed_address, 1);
1747 }
d02ed0bb
MM
1748}
1749
88d1aa9d 1750/* Behavior is conditional on RECORD_FULL_IS_REPLAY. We will not actually
d02ed0bb
MM
1751 insert or remove breakpoints in the real target when replaying, nor
1752 when recording. */
1753
f6ac5f3d
PA
1754int
1755record_full_target::insert_breakpoint (struct gdbarch *gdbarch,
1756 struct bp_target_info *bp_tgt)
d02ed0bb 1757{
219605fd 1758 bool in_target_beneath = false;
d02ed0bb 1759
88d1aa9d 1760 if (!RECORD_FULL_IS_REPLAY)
d02ed0bb
MM
1761 {
1762 /* When recording, we currently always single-step, so we don't
1763 really need to install regular breakpoints in the inferior.
1764 However, we do have to insert software single-step
1765 breakpoints, in case the target can't hardware step. To keep
f99bd5f2 1766 things simple, we always insert. */
d02ed0bb 1767
07036511
TT
1768 scoped_restore restore_operation_disable
1769 = record_full_gdb_operation_disable_set ();
d02ed0bb 1770
b6a8c27b 1771 int ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt);
d02ed0bb
MM
1772 if (ret != 0)
1773 return ret;
1774
219605fd 1775 in_target_beneath = true;
d02ed0bb
MM
1776 }
1777
e390720b
YQ
1778 /* Use the existing entries if found in order to avoid duplication
1779 in record_full_breakpoints. */
1780
19f3f25f 1781 for (const record_full_breakpoint &bp : record_full_breakpoints)
e390720b 1782 {
219605fd
TT
1783 if (bp.addr == bp_tgt->placed_address
1784 && bp.address_space == bp_tgt->placed_address_space)
e390720b 1785 {
219605fd 1786 gdb_assert (bp.in_target_beneath == in_target_beneath);
e390720b
YQ
1787 return 0;
1788 }
1789 }
1790
219605fd
TT
1791 record_full_breakpoints.emplace_back (bp_tgt->placed_address_space,
1792 bp_tgt->placed_address,
1793 in_target_beneath);
d02ed0bb
MM
1794 return 0;
1795}
1796
f6ac5f3d 1797/* "remove_breakpoint" method for process record target. */
d02ed0bb 1798
f6ac5f3d
PA
1799int
1800record_full_target::remove_breakpoint (struct gdbarch *gdbarch,
1801 struct bp_target_info *bp_tgt,
1802 enum remove_bp_reason reason)
d02ed0bb 1803{
219605fd
TT
1804 for (auto iter = record_full_breakpoints.begin ();
1805 iter != record_full_breakpoints.end ();
1806 ++iter)
d02ed0bb 1807 {
219605fd
TT
1808 struct record_full_breakpoint &bp = *iter;
1809
1810 if (bp.addr == bp_tgt->placed_address
1811 && bp.address_space == bp_tgt->placed_address_space)
d02ed0bb 1812 {
219605fd 1813 if (bp.in_target_beneath)
d02ed0bb 1814 {
07036511
TT
1815 scoped_restore restore_operation_disable
1816 = record_full_gdb_operation_disable_set ();
f6ac5f3d 1817
b6a8c27b
PA
1818 int ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt,
1819 reason);
d02ed0bb
MM
1820 if (ret != 0)
1821 return ret;
1822 }
1823
01d3dedf 1824 if (reason == REMOVE_BREAKPOINT)
219605fd 1825 unordered_remove (record_full_breakpoints, iter);
d02ed0bb
MM
1826 return 0;
1827 }
1828 }
1829
1830 gdb_assert_not_reached ("removing unknown breakpoint");
1831}
1832
f6ac5f3d 1833/* "can_execute_reverse" method for process record target. */
d02ed0bb 1834
57810aa7 1835bool
f6ac5f3d 1836record_full_base_target::can_execute_reverse ()
d02ed0bb 1837{
57810aa7 1838 return true;
d02ed0bb
MM
1839}
1840
f6ac5f3d 1841/* "get_bookmark" method for process record and prec over core. */
d02ed0bb 1842
f6ac5f3d
PA
1843gdb_byte *
1844record_full_base_target::get_bookmark (const char *args, int from_tty)
d02ed0bb 1845{
0f928d68 1846 char *ret = NULL;
d02ed0bb
MM
1847
1848 /* Return stringified form of instruction count. */
88d1aa9d
MM
1849 if (record_full_list && record_full_list->type == record_full_end)
1850 ret = xstrdup (pulongest (record_full_list->u.end.insn_num));
d02ed0bb
MM
1851
1852 if (record_debug)
1853 {
1854 if (ret)
6cb06a8c
TT
1855 gdb_printf (gdb_stdlog,
1856 "record_full_get_bookmark returns %s\n", ret);
d02ed0bb 1857 else
6cb06a8c
TT
1858 gdb_printf (gdb_stdlog,
1859 "record_full_get_bookmark returns NULL\n");
d02ed0bb 1860 }
0f928d68 1861 return (gdb_byte *) ret;
d02ed0bb
MM
1862}
1863
f6ac5f3d 1864/* "goto_bookmark" method for process record and prec over core. */
d02ed0bb 1865
f6ac5f3d
PA
1866void
1867record_full_base_target::goto_bookmark (const gdb_byte *raw_bookmark,
1868 int from_tty)
d02ed0bb 1869{
c2bcbb1d 1870 const char *bookmark = (const char *) raw_bookmark;
0f928d68 1871
d02ed0bb 1872 if (record_debug)
6cb06a8c
TT
1873 gdb_printf (gdb_stdlog,
1874 "record_full_goto_bookmark receives %s\n", bookmark);
d02ed0bb 1875
a2b2bc12 1876 std::string name_holder;
d02ed0bb
MM
1877 if (bookmark[0] == '\'' || bookmark[0] == '\"')
1878 {
1879 if (bookmark[strlen (bookmark) - 1] != bookmark[0])
1880 error (_("Unbalanced quotes: %s"), bookmark);
1881
a2b2bc12
TT
1882 name_holder = std::string (bookmark + 1, strlen (bookmark) - 2);
1883 bookmark = name_holder.c_str ();
d02ed0bb
MM
1884 }
1885
c2bcbb1d 1886 record_goto (bookmark);
d02ed0bb
MM
1887}
1888
f6ac5f3d
PA
1889enum exec_direction_kind
1890record_full_base_target::execution_direction ()
d02ed0bb 1891{
88d1aa9d 1892 return record_full_execution_dir;
d02ed0bb
MM
1893}
1894
f6ac5f3d 1895/* The record_method method of target record-full. */
b158a20f
TW
1896
1897enum record_method
f6ac5f3d 1898record_full_base_target::record_method (ptid_t ptid)
b158a20f
TW
1899{
1900 return RECORD_METHOD_FULL;
1901}
1902
f6ac5f3d
PA
1903void
1904record_full_base_target::info_record ()
d02ed0bb 1905{
88d1aa9d 1906 struct record_full_entry *p;
d02ed0bb 1907
88d1aa9d 1908 if (RECORD_FULL_IS_REPLAY)
6cb06a8c 1909 gdb_printf (_("Replay mode:\n"));
d02ed0bb 1910 else
6cb06a8c 1911 gdb_printf (_("Record mode:\n"));
d02ed0bb
MM
1912
1913 /* Find entry for first actual instruction in the log. */
88d1aa9d
MM
1914 for (p = record_full_first.next;
1915 p != NULL && p->type != record_full_end;
d02ed0bb
MM
1916 p = p->next)
1917 ;
1918
1919 /* Do we have a log at all? */
88d1aa9d 1920 if (p != NULL && p->type == record_full_end)
d02ed0bb
MM
1921 {
1922 /* Display instruction number for first instruction in the log. */
6cb06a8c
TT
1923 gdb_printf (_("Lowest recorded instruction number is %s.\n"),
1924 pulongest (p->u.end.insn_num));
d02ed0bb
MM
1925
1926 /* If in replay mode, display where we are in the log. */
88d1aa9d 1927 if (RECORD_FULL_IS_REPLAY)
6cb06a8c
TT
1928 gdb_printf (_("Current instruction number is %s.\n"),
1929 pulongest (record_full_list->u.end.insn_num));
d02ed0bb
MM
1930
1931 /* Display instruction number for last instruction in the log. */
6cb06a8c
TT
1932 gdb_printf (_("Highest recorded instruction number is %s.\n"),
1933 pulongest (record_full_insn_count));
d02ed0bb
MM
1934
1935 /* Display log count. */
6cb06a8c
TT
1936 gdb_printf (_("Log contains %u instructions.\n"),
1937 record_full_insn_num);
d02ed0bb
MM
1938 }
1939 else
6cb06a8c 1940 gdb_printf (_("No instructions have been logged.\n"));
d02ed0bb
MM
1941
1942 /* Display max log size. */
6cb06a8c
TT
1943 gdb_printf (_("Max logged instructions is %u.\n"),
1944 record_full_insn_max_num);
d02ed0bb
MM
1945}
1946
f6ac5f3d
PA
1947bool
1948record_full_base_target::supports_delete_record ()
1949{
1950 return true;
1951}
d02ed0bb 1952
f6ac5f3d
PA
1953/* The "delete_record" target method. */
1954
1955void
1956record_full_base_target::delete_record ()
d02ed0bb 1957{
88d1aa9d 1958 record_full_list_release_following (record_full_list);
d02ed0bb
MM
1959}
1960
f6ac5f3d 1961/* The "record_is_replaying" target method. */
d02ed0bb 1962
57810aa7 1963bool
f6ac5f3d 1964record_full_base_target::record_is_replaying (ptid_t ptid)
d02ed0bb 1965{
88d1aa9d 1966 return RECORD_FULL_IS_REPLAY;
d02ed0bb
MM
1967}
1968
f6ac5f3d 1969/* The "record_will_replay" target method. */
7ff27e9b 1970
57810aa7 1971bool
f6ac5f3d 1972record_full_base_target::record_will_replay (ptid_t ptid, int dir)
7ff27e9b
MM
1973{
1974 /* We can currently only record when executing forwards. Should we be able
1975 to record when executing backwards on targets that support reverse
1976 execution, this needs to be changed. */
1977
1978 return RECORD_FULL_IS_REPLAY || dir == EXEC_REVERSE;
1979}
1980
d02ed0bb
MM
1981/* Go to a specific entry. */
1982
1983static void
88d1aa9d 1984record_full_goto_entry (struct record_full_entry *p)
d02ed0bb
MM
1985{
1986 if (p == NULL)
1987 error (_("Target insn not found."));
88d1aa9d 1988 else if (p == record_full_list)
d02ed0bb 1989 error (_("Already at target insn."));
88d1aa9d 1990 else if (p->u.end.insn_num > record_full_list->u.end.insn_num)
d02ed0bb 1991 {
6cb06a8c
TT
1992 gdb_printf (_("Go forward to insn number %s\n"),
1993 pulongest (p->u.end.insn_num));
88d1aa9d 1994 record_full_goto_insn (p, EXEC_FORWARD);
d02ed0bb
MM
1995 }
1996 else
1997 {
6cb06a8c
TT
1998 gdb_printf (_("Go backward to insn number %s\n"),
1999 pulongest (p->u.end.insn_num));
88d1aa9d 2000 record_full_goto_insn (p, EXEC_REVERSE);
d02ed0bb
MM
2001 }
2002
2003 registers_changed ();
2004 reinit_frame_cache ();
9c742269
SM
2005
2006 thread_info *thr = inferior_thread ();
2007 thr->set_stop_pc (regcache_read_pc (get_thread_regcache (thr)));
08d72866 2008 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
d02ed0bb
MM
2009}
2010
f6ac5f3d 2011/* The "goto_record_begin" target method. */
d02ed0bb 2012
f6ac5f3d
PA
2013void
2014record_full_base_target::goto_record_begin ()
d02ed0bb 2015{
88d1aa9d 2016 struct record_full_entry *p = NULL;
d02ed0bb 2017
88d1aa9d
MM
2018 for (p = &record_full_first; p != NULL; p = p->next)
2019 if (p->type == record_full_end)
d02ed0bb
MM
2020 break;
2021
88d1aa9d 2022 record_full_goto_entry (p);
d02ed0bb
MM
2023}
2024
f6ac5f3d 2025/* The "goto_record_end" target method. */
d02ed0bb 2026
f6ac5f3d
PA
2027void
2028record_full_base_target::goto_record_end ()
d02ed0bb 2029{
88d1aa9d 2030 struct record_full_entry *p = NULL;
d02ed0bb 2031
88d1aa9d 2032 for (p = record_full_list; p->next != NULL; p = p->next)
d02ed0bb
MM
2033 ;
2034 for (; p!= NULL; p = p->prev)
88d1aa9d 2035 if (p->type == record_full_end)
d02ed0bb
MM
2036 break;
2037
88d1aa9d 2038 record_full_goto_entry (p);
d02ed0bb
MM
2039}
2040
f6ac5f3d 2041/* The "goto_record" target method. */
d02ed0bb 2042
f6ac5f3d
PA
2043void
2044record_full_base_target::goto_record (ULONGEST target_insn)
d02ed0bb 2045{
88d1aa9d 2046 struct record_full_entry *p = NULL;
d02ed0bb 2047
88d1aa9d
MM
2048 for (p = &record_full_first; p != NULL; p = p->next)
2049 if (p->type == record_full_end && p->u.end.insn_num == target_insn)
d02ed0bb
MM
2050 break;
2051
88d1aa9d 2052 record_full_goto_entry (p);
d02ed0bb
MM
2053}
2054
f6ac5f3d 2055/* The "record_stop_replaying" target method. */
797094dd 2056
f6ac5f3d
PA
2057void
2058record_full_base_target::record_stop_replaying ()
797094dd 2059{
f6ac5f3d 2060 goto_record_end ();
797094dd
MM
2061}
2062
f6ac5f3d 2063/* "resume" method for prec over corefile. */
d02ed0bb 2064
f6ac5f3d
PA
2065void
2066record_full_core_target::resume (ptid_t ptid, int step,
2067 enum gdb_signal signal)
d02ed0bb 2068{
88d1aa9d
MM
2069 record_full_resume_step = step;
2070 record_full_resumed = 1;
f6ac5f3d 2071 record_full_execution_dir = ::execution_direction;
d02ed0bb
MM
2072}
2073
f6ac5f3d 2074/* "kill" method for prec over corefile. */
d02ed0bb 2075
f6ac5f3d
PA
2076void
2077record_full_core_target::kill ()
d02ed0bb
MM
2078{
2079 if (record_debug)
6cb06a8c 2080 gdb_printf (gdb_stdlog, "Process record: record_full_core_kill\n");
d02ed0bb 2081
fadf6add 2082 current_inferior ()->unpush_target (this);
d02ed0bb
MM
2083}
2084
f6ac5f3d 2085/* "fetch_registers" method for prec over corefile. */
d02ed0bb 2086
f6ac5f3d
PA
2087void
2088record_full_core_target::fetch_registers (struct regcache *regcache,
2089 int regno)
d02ed0bb
MM
2090{
2091 if (regno < 0)
2092 {
ac7936df 2093 int num = gdbarch_num_regs (regcache->arch ());
d02ed0bb
MM
2094 int i;
2095
2096 for (i = 0; i < num; i ++)
c8ec2f33 2097 regcache->raw_supply (i, *record_full_core_regbuf);
d02ed0bb
MM
2098 }
2099 else
c8ec2f33 2100 regcache->raw_supply (regno, *record_full_core_regbuf);
d02ed0bb
MM
2101}
2102
f6ac5f3d 2103/* "prepare_to_store" method for prec over corefile. */
d02ed0bb 2104
f6ac5f3d
PA
2105void
2106record_full_core_target::prepare_to_store (struct regcache *regcache)
d02ed0bb
MM
2107{
2108}
2109
f6ac5f3d 2110/* "store_registers" method for prec over corefile. */
d02ed0bb 2111
f6ac5f3d
PA
2112void
2113record_full_core_target::store_registers (struct regcache *regcache,
2114 int regno)
d02ed0bb 2115{
88d1aa9d 2116 if (record_full_gdb_operation_disable)
c8ec2f33 2117 record_full_core_regbuf->raw_supply (regno, *regcache);
d02ed0bb
MM
2118 else
2119 error (_("You can't do that without a process to debug."));
2120}
2121
f6ac5f3d 2122/* "xfer_partial" method for prec over corefile. */
d02ed0bb 2123
f6ac5f3d
PA
2124enum target_xfer_status
2125record_full_core_target::xfer_partial (enum target_object object,
2126 const char *annex, gdb_byte *readbuf,
2127 const gdb_byte *writebuf, ULONGEST offset,
2128 ULONGEST len, ULONGEST *xfered_len)
d02ed0bb
MM
2129{
2130 if (object == TARGET_OBJECT_MEMORY)
2131 {
88d1aa9d 2132 if (record_full_gdb_operation_disable || !writebuf)
d02ed0bb 2133 {
d7a78e5c 2134 for (target_section &p : record_full_core_sections)
d02ed0bb 2135 {
bb2a6777 2136 if (offset >= p.addr)
d02ed0bb 2137 {
88d1aa9d 2138 struct record_full_core_buf_entry *entry;
d02ed0bb
MM
2139 ULONGEST sec_offset;
2140
bb2a6777 2141 if (offset >= p.endaddr)
d02ed0bb
MM
2142 continue;
2143
bb2a6777
TT
2144 if (offset + len > p.endaddr)
2145 len = p.endaddr - offset;
d02ed0bb 2146
bb2a6777 2147 sec_offset = offset - p.addr;
d02ed0bb
MM
2148
2149 /* Read readbuf or write writebuf p, offset, len. */
2150 /* Check flags. */
bb2a6777
TT
2151 if (p.the_bfd_section->flags & SEC_CONSTRUCTOR
2152 || (p.the_bfd_section->flags & SEC_HAS_CONTENTS) == 0)
d02ed0bb
MM
2153 {
2154 if (readbuf)
2155 memset (readbuf, 0, len);
9b409511
YQ
2156
2157 *xfered_len = len;
2158 return TARGET_XFER_OK;
d02ed0bb 2159 }
88d1aa9d
MM
2160 /* Get record_full_core_buf_entry. */
2161 for (entry = record_full_core_buf_list; entry;
d02ed0bb 2162 entry = entry->prev)
bb2a6777 2163 if (entry->p == &p)
d02ed0bb
MM
2164 break;
2165 if (writebuf)
2166 {
2167 if (!entry)
2168 {
2169 /* Add a new entry. */
8d749320 2170 entry = XNEW (struct record_full_core_buf_entry);
bb2a6777 2171 entry->p = &p;
2b2848e2 2172 if (!bfd_malloc_and_get_section
dda83cd7 2173 (p.the_bfd_section->owner,
bb2a6777 2174 p.the_bfd_section,
2b2848e2 2175 &entry->buf))
d02ed0bb
MM
2176 {
2177 xfree (entry);
9b409511 2178 return TARGET_XFER_EOF;
d02ed0bb 2179 }
88d1aa9d
MM
2180 entry->prev = record_full_core_buf_list;
2181 record_full_core_buf_list = entry;
d02ed0bb
MM
2182 }
2183
2184 memcpy (entry->buf + sec_offset, writebuf,
2185 (size_t) len);
2186 }
2187 else
2188 {
2189 if (!entry)
b6a8c27b
PA
2190 return this->beneath ()->xfer_partial (object, annex,
2191 readbuf, writebuf,
2192 offset, len,
2193 xfered_len);
d02ed0bb
MM
2194
2195 memcpy (readbuf, entry->buf + sec_offset,
2196 (size_t) len);
2197 }
2198
9b409511
YQ
2199 *xfered_len = len;
2200 return TARGET_XFER_OK;
d02ed0bb
MM
2201 }
2202 }
2203
2ed4b548 2204 return TARGET_XFER_E_IO;
d02ed0bb
MM
2205 }
2206 else
2207 error (_("You can't do that without a process to debug."));
2208 }
2209
b6a8c27b
PA
2210 return this->beneath ()->xfer_partial (object, annex,
2211 readbuf, writebuf, offset, len,
2212 xfered_len);
d02ed0bb
MM
2213}
2214
f6ac5f3d 2215/* "insert_breakpoint" method for prec over corefile. */
d02ed0bb 2216
f6ac5f3d
PA
2217int
2218record_full_core_target::insert_breakpoint (struct gdbarch *gdbarch,
2219 struct bp_target_info *bp_tgt)
d02ed0bb
MM
2220{
2221 return 0;
2222}
2223
f6ac5f3d 2224/* "remove_breakpoint" method for prec over corefile. */
d02ed0bb 2225
f6ac5f3d
PA
2226int
2227record_full_core_target::remove_breakpoint (struct gdbarch *gdbarch,
2228 struct bp_target_info *bp_tgt,
2229 enum remove_bp_reason reason)
d02ed0bb
MM
2230{
2231 return 0;
2232}
2233
f6ac5f3d 2234/* "has_execution" method for prec over corefile. */
d02ed0bb 2235
57810aa7 2236bool
5018ce90 2237record_full_core_target::has_execution (inferior *inf)
d02ed0bb 2238{
57810aa7 2239 return true;
d02ed0bb
MM
2240}
2241
d02ed0bb
MM
2242/* Record log save-file format
2243 Version 1 (never released)
2244
2245 Header:
2246 4 bytes: magic number htonl(0x20090829).
2247 NOTE: be sure to change whenever this file format changes!
2248
2249 Records:
88d1aa9d
MM
2250 record_full_end:
2251 1 byte: record type (record_full_end, see enum record_full_type).
2252 record_full_reg:
2253 1 byte: record type (record_full_reg, see enum record_full_type).
d02ed0bb
MM
2254 8 bytes: register id (network byte order).
2255 MAX_REGISTER_SIZE bytes: register value.
88d1aa9d
MM
2256 record_full_mem:
2257 1 byte: record type (record_full_mem, see enum record_full_type).
d02ed0bb
MM
2258 8 bytes: memory length (network byte order).
2259 8 bytes: memory address (network byte order).
2260 n bytes: memory value (n == memory length).
2261
2262 Version 2
2263 4 bytes: magic number netorder32(0x20091016).
2264 NOTE: be sure to change whenever this file format changes!
2265
2266 Records:
88d1aa9d
MM
2267 record_full_end:
2268 1 byte: record type (record_full_end, see enum record_full_type).
d02ed0bb
MM
2269 4 bytes: signal
2270 4 bytes: instruction count
88d1aa9d
MM
2271 record_full_reg:
2272 1 byte: record type (record_full_reg, see enum record_full_type).
d02ed0bb
MM
2273 4 bytes: register id (network byte order).
2274 n bytes: register value (n == actual register size).
dda83cd7 2275 (eg. 4 bytes for x86 general registers).
88d1aa9d
MM
2276 record_full_mem:
2277 1 byte: record type (record_full_mem, see enum record_full_type).
d02ed0bb
MM
2278 4 bytes: memory length (network byte order).
2279 8 bytes: memory address (network byte order).
2280 n bytes: memory value (n == memory length).
2281
2282*/
2283
2284/* bfdcore_read -- read bytes from a core file section. */
2285
2286static inline void
2287bfdcore_read (bfd *obfd, asection *osec, void *buf, int len, int *offset)
2288{
2289 int ret = bfd_get_section_contents (obfd, osec, buf, *offset, len);
2290
2291 if (ret)
2292 *offset += len;
2293 else
2294 error (_("Failed to read %d bytes from core file %s ('%s')."),
2295 len, bfd_get_filename (obfd),
2296 bfd_errmsg (bfd_get_error ()));
2297}
2298
2299static inline uint64_t
2300netorder64 (uint64_t input)
2301{
2302 uint64_t ret;
2303
2304 store_unsigned_integer ((gdb_byte *) &ret, sizeof (ret),
2305 BFD_ENDIAN_BIG, input);
2306 return ret;
2307}
2308
2309static inline uint32_t
2310netorder32 (uint32_t input)
2311{
2312 uint32_t ret;
2313
d02ed0bb
MM
2314 store_unsigned_integer ((gdb_byte *) &ret, sizeof (ret),
2315 BFD_ENDIAN_BIG, input);
2316 return ret;
2317}
2318
2319/* Restore the execution log from a core_bfd file. */
2320static void
88d1aa9d 2321record_full_restore (void)
d02ed0bb
MM
2322{
2323 uint32_t magic;
88d1aa9d 2324 struct record_full_entry *rec;
d02ed0bb
MM
2325 asection *osec;
2326 uint32_t osec_size;
2327 int bfd_offset = 0;
d02ed0bb
MM
2328
2329 /* We restore the execution log from the open core bfd,
2330 if there is one. */
2331 if (core_bfd == NULL)
2332 return;
2333
88d1aa9d
MM
2334 /* "record_full_restore" can only be called when record list is empty. */
2335 gdb_assert (record_full_first.next == NULL);
d02ed0bb
MM
2336
2337 if (record_debug)
6cb06a8c 2338 gdb_printf (gdb_stdlog, "Restoring recording from core file.\n");
d02ed0bb
MM
2339
2340 /* Now need to find our special note section. */
2341 osec = bfd_get_section_by_name (core_bfd, "null0");
2342 if (record_debug)
6cb06a8c
TT
2343 gdb_printf (gdb_stdlog, "Find precord section %s.\n",
2344 osec ? "succeeded" : "failed");
d02ed0bb
MM
2345 if (osec == NULL)
2346 return;
fd361982 2347 osec_size = bfd_section_size (osec);
d02ed0bb 2348 if (record_debug)
6cb06a8c 2349 gdb_printf (gdb_stdlog, "%s", bfd_section_name (osec));
d02ed0bb
MM
2350
2351 /* Check the magic code. */
2352 bfdcore_read (core_bfd, osec, &magic, sizeof (magic), &bfd_offset);
88d1aa9d 2353 if (magic != RECORD_FULL_FILE_MAGIC)
d02ed0bb
MM
2354 error (_("Version mis-match or file format error in core file %s."),
2355 bfd_get_filename (core_bfd));
2356 if (record_debug)
6cb06a8c
TT
2357 gdb_printf (gdb_stdlog,
2358 " Reading 4-byte magic cookie "
2359 "RECORD_FULL_FILE_MAGIC (0x%s)\n",
2360 phex_nz (netorder32 (magic), 4));
d02ed0bb 2361
88d1aa9d
MM
2362 /* Restore the entries in recfd into record_full_arch_list_head and
2363 record_full_arch_list_tail. */
2364 record_full_arch_list_head = NULL;
2365 record_full_arch_list_tail = NULL;
2366 record_full_insn_num = 0;
d02ed0bb 2367
a70b8144 2368 try
d02ed0bb 2369 {
9c742269 2370 regcache *regcache = get_thread_regcache (inferior_thread ());
1ddbba9d
TT
2371
2372 while (1)
2373 {
2374 uint8_t rectype;
2375 uint32_t regnum, len, signal, count;
2376 uint64_t addr;
d02ed0bb 2377
1ddbba9d
TT
2378 /* We are finished when offset reaches osec_size. */
2379 if (bfd_offset >= osec_size)
2380 break;
2381 bfdcore_read (core_bfd, osec, &rectype, sizeof (rectype), &bfd_offset);
d02ed0bb 2382
1ddbba9d
TT
2383 switch (rectype)
2384 {
2385 case record_full_reg: /* reg */
2386 /* Get register number to regnum. */
2387 bfdcore_read (core_bfd, osec, &regnum,
2388 sizeof (regnum), &bfd_offset);
2389 regnum = netorder32 (regnum);
d02ed0bb 2390
1ddbba9d 2391 rec = record_full_reg_alloc (regcache, regnum);
d02ed0bb 2392
1ddbba9d
TT
2393 /* Get val. */
2394 bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
2395 rec->u.reg.len, &bfd_offset);
d02ed0bb 2396
1ddbba9d 2397 if (record_debug)
6cb06a8c
TT
2398 gdb_printf (gdb_stdlog,
2399 " Reading register %d (1 "
2400 "plus %lu plus %d bytes)\n",
2401 rec->u.reg.num,
2402 (unsigned long) sizeof (regnum),
2403 rec->u.reg.len);
1ddbba9d 2404 break;
d02ed0bb 2405
1ddbba9d
TT
2406 case record_full_mem: /* mem */
2407 /* Get len. */
2408 bfdcore_read (core_bfd, osec, &len,
2409 sizeof (len), &bfd_offset);
2410 len = netorder32 (len);
d02ed0bb 2411
1ddbba9d
TT
2412 /* Get addr. */
2413 bfdcore_read (core_bfd, osec, &addr,
2414 sizeof (addr), &bfd_offset);
2415 addr = netorder64 (addr);
2416
2417 rec = record_full_mem_alloc (addr, len);
2418
2419 /* Get val. */
2420 bfdcore_read (core_bfd, osec, record_full_get_loc (rec),
2421 rec->u.mem.len, &bfd_offset);
2422
2423 if (record_debug)
6cb06a8c
TT
2424 gdb_printf (gdb_stdlog,
2425 " Reading memory %s (1 plus "
2426 "%lu plus %lu plus %d bytes)\n",
2427 paddress (get_current_arch (),
2428 rec->u.mem.addr),
2429 (unsigned long) sizeof (addr),
2430 (unsigned long) sizeof (len),
2431 rec->u.mem.len);
1ddbba9d
TT
2432 break;
2433
2434 case record_full_end: /* end */
2435 rec = record_full_end_alloc ();
2436 record_full_insn_num ++;
2437
2438 /* Get signal value. */
2439 bfdcore_read (core_bfd, osec, &signal,
2440 sizeof (signal), &bfd_offset);
2441 signal = netorder32 (signal);
2442 rec->u.end.sigval = (enum gdb_signal) signal;
2443
2444 /* Get insn count. */
2445 bfdcore_read (core_bfd, osec, &count,
2446 sizeof (count), &bfd_offset);
2447 count = netorder32 (count);
2448 rec->u.end.insn_num = count;
2449 record_full_insn_count = count + 1;
2450 if (record_debug)
6cb06a8c
TT
2451 gdb_printf (gdb_stdlog,
2452 " Reading record_full_end (1 + "
2453 "%lu + %lu bytes), offset == %s\n",
2454 (unsigned long) sizeof (signal),
2455 (unsigned long) sizeof (count),
2456 paddress (get_current_arch (),
2457 bfd_offset));
1ddbba9d
TT
2458 break;
2459
2460 default:
2461 error (_("Bad entry type in core file %s."),
2462 bfd_get_filename (core_bfd));
2463 break;
2464 }
d02ed0bb 2465
1ddbba9d
TT
2466 /* Add rec to record arch list. */
2467 record_full_arch_list_add (rec);
2468 }
2469 }
230d2906 2470 catch (const gdb_exception &ex)
1ddbba9d
TT
2471 {
2472 record_full_list_release (record_full_arch_list_tail);
eedc3f4f 2473 throw;
1ddbba9d 2474 }
d02ed0bb 2475
88d1aa9d
MM
2476 /* Add record_full_arch_list_head to the end of record list. */
2477 record_full_first.next = record_full_arch_list_head;
2478 record_full_arch_list_head->prev = &record_full_first;
2479 record_full_arch_list_tail->next = NULL;
2480 record_full_list = &record_full_first;
d02ed0bb 2481
88d1aa9d
MM
2482 /* Update record_full_insn_max_num. */
2483 if (record_full_insn_num > record_full_insn_max_num)
d02ed0bb 2484 {
88d1aa9d 2485 record_full_insn_max_num = record_full_insn_num;
7ee70bf5 2486 warning (_("Auto increase record/replay buffer limit to %u."),
dda83cd7 2487 record_full_insn_max_num);
d02ed0bb
MM
2488 }
2489
2490 /* Succeeded. */
6cb06a8c
TT
2491 gdb_printf (_("Restored records from core file %s.\n"),
2492 bfd_get_filename (core_bfd));
d02ed0bb 2493
08d72866 2494 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
d02ed0bb
MM
2495}
2496
2497/* bfdcore_write -- write bytes into a core file section. */
2498
2499static inline void
2500bfdcore_write (bfd *obfd, asection *osec, void *buf, int len, int *offset)
2501{
2502 int ret = bfd_set_section_contents (obfd, osec, buf, *offset, len);
2503
2504 if (ret)
2505 *offset += len;
2506 else
2507 error (_("Failed to write %d bytes to core file %s ('%s')."),
2508 len, bfd_get_filename (obfd),
2509 bfd_errmsg (bfd_get_error ()));
2510}
2511
2512/* Restore the execution log from a file. We use a modified elf
2513 corefile format, with an extra section for our data. */
2514
2515static void
41243651 2516cmd_record_full_restore (const char *args, int from_tty)
d02ed0bb
MM
2517{
2518 core_file_command (args, from_tty);
d9f719f1 2519 record_full_open (args, from_tty);
d02ed0bb
MM
2520}
2521
d02ed0bb
MM
2522/* Save the execution log to a file. We use a modified elf corefile
2523 format, with an extra section for our data. */
2524
f6ac5f3d
PA
2525void
2526record_full_base_target::save_record (const char *recfilename)
d02ed0bb 2527{
88d1aa9d 2528 struct record_full_entry *cur_record_full_list;
d02ed0bb 2529 uint32_t magic;
d02ed0bb 2530 struct gdbarch *gdbarch;
d02ed0bb
MM
2531 int save_size = 0;
2532 asection *osec = NULL;
2533 int bfd_offset = 0;
2534
2535 /* Open the save file. */
2536 if (record_debug)
6cb06a8c
TT
2537 gdb_printf (gdb_stdlog, "Saving execution log to core file '%s'\n",
2538 recfilename);
d02ed0bb
MM
2539
2540 /* Open the output file. */
bef155c3
TT
2541 gdb_bfd_ref_ptr obfd (create_gcore_bfd (recfilename));
2542
2543 /* Arrange to remove the output file on failure. */
2544 gdb::unlinker unlink_file (recfilename);
d02ed0bb 2545
88d1aa9d
MM
2546 /* Save the current record entry to "cur_record_full_list". */
2547 cur_record_full_list = record_full_list;
d02ed0bb
MM
2548
2549 /* Get the values of regcache and gdbarch. */
9c742269 2550 regcache *regcache = get_thread_regcache (inferior_thread ());
ac7936df 2551 gdbarch = regcache->arch ();
d02ed0bb
MM
2552
2553 /* Disable the GDB operation record. */
07036511
TT
2554 scoped_restore restore_operation_disable
2555 = record_full_gdb_operation_disable_set ();
d02ed0bb
MM
2556
2557 /* Reverse execute to the begin of record list. */
2558 while (1)
2559 {
2560 /* Check for beginning and end of log. */
88d1aa9d 2561 if (record_full_list == &record_full_first)
dda83cd7 2562 break;
d02ed0bb 2563
88d1aa9d 2564 record_full_exec_insn (regcache, gdbarch, record_full_list);
d02ed0bb 2565
88d1aa9d 2566 if (record_full_list->prev)
dda83cd7 2567 record_full_list = record_full_list->prev;
d02ed0bb
MM
2568 }
2569
2570 /* Compute the size needed for the extra bfd section. */
2571 save_size = 4; /* magic cookie */
88d1aa9d
MM
2572 for (record_full_list = record_full_first.next; record_full_list;
2573 record_full_list = record_full_list->next)
2574 switch (record_full_list->type)
d02ed0bb 2575 {
88d1aa9d 2576 case record_full_end:
d02ed0bb
MM
2577 save_size += 1 + 4 + 4;
2578 break;
88d1aa9d
MM
2579 case record_full_reg:
2580 save_size += 1 + 4 + record_full_list->u.reg.len;
d02ed0bb 2581 break;
88d1aa9d
MM
2582 case record_full_mem:
2583 save_size += 1 + 4 + 8 + record_full_list->u.mem.len;
d02ed0bb
MM
2584 break;
2585 }
2586
2587 /* Make the new bfd section. */
bef155c3 2588 osec = bfd_make_section_anyway_with_flags (obfd.get (), "precord",
dda83cd7
SM
2589 SEC_HAS_CONTENTS
2590 | SEC_READONLY);
d02ed0bb
MM
2591 if (osec == NULL)
2592 error (_("Failed to create 'precord' section for corefile %s: %s"),
2593 recfilename,
dda83cd7 2594 bfd_errmsg (bfd_get_error ()));
fd361982
AM
2595 bfd_set_section_size (osec, save_size);
2596 bfd_set_section_vma (osec, 0);
2597 bfd_set_section_alignment (osec, 0);
d02ed0bb
MM
2598
2599 /* Save corefile state. */
bef155c3 2600 write_gcore_file (obfd.get ());
d02ed0bb
MM
2601
2602 /* Write out the record log. */
2603 /* Write the magic code. */
88d1aa9d 2604 magic = RECORD_FULL_FILE_MAGIC;
d02ed0bb 2605 if (record_debug)
6cb06a8c
TT
2606 gdb_printf (gdb_stdlog,
2607 " Writing 4-byte magic cookie "
2608 "RECORD_FULL_FILE_MAGIC (0x%s)\n",
2609 phex_nz (magic, 4));
bef155c3 2610 bfdcore_write (obfd.get (), osec, &magic, sizeof (magic), &bfd_offset);
d02ed0bb
MM
2611
2612 /* Save the entries to recfd and forward execute to the end of
2613 record list. */
88d1aa9d 2614 record_full_list = &record_full_first;
d02ed0bb
MM
2615 while (1)
2616 {
2617 /* Save entry. */
88d1aa9d 2618 if (record_full_list != &record_full_first)
dda83cd7 2619 {
d02ed0bb
MM
2620 uint8_t type;
2621 uint32_t regnum, len, signal, count;
dda83cd7 2622 uint64_t addr;
d02ed0bb 2623
88d1aa9d 2624 type = record_full_list->type;
dda83cd7 2625 bfdcore_write (obfd.get (), osec, &type, sizeof (type), &bfd_offset);
d02ed0bb 2626
dda83cd7
SM
2627 switch (record_full_list->type)
2628 {
2629 case record_full_reg: /* reg */
d02ed0bb 2630 if (record_debug)
6cb06a8c
TT
2631 gdb_printf (gdb_stdlog,
2632 " Writing register %d (1 "
2633 "plus %lu plus %d bytes)\n",
2634 record_full_list->u.reg.num,
2635 (unsigned long) sizeof (regnum),
2636 record_full_list->u.reg.len);
d02ed0bb 2637
dda83cd7
SM
2638 /* Write regnum. */
2639 regnum = netorder32 (record_full_list->u.reg.num);
2640 bfdcore_write (obfd.get (), osec, &regnum,
d02ed0bb
MM
2641 sizeof (regnum), &bfd_offset);
2642
dda83cd7
SM
2643 /* Write regval. */
2644 bfdcore_write (obfd.get (), osec,
88d1aa9d
MM
2645 record_full_get_loc (record_full_list),
2646 record_full_list->u.reg.len, &bfd_offset);
dda83cd7 2647 break;
d02ed0bb 2648
dda83cd7 2649 case record_full_mem: /* mem */
d02ed0bb 2650 if (record_debug)
6cb06a8c
TT
2651 gdb_printf (gdb_stdlog,
2652 " Writing memory %s (1 plus "
2653 "%lu plus %lu plus %d bytes)\n",
2654 paddress (gdbarch,
2655 record_full_list->u.mem.addr),
2656 (unsigned long) sizeof (addr),
2657 (unsigned long) sizeof (len),
2658 record_full_list->u.mem.len);
d02ed0bb
MM
2659
2660 /* Write memlen. */
88d1aa9d 2661 len = netorder32 (record_full_list->u.mem.len);
bef155c3
TT
2662 bfdcore_write (obfd.get (), osec, &len, sizeof (len),
2663 &bfd_offset);
d02ed0bb
MM
2664
2665 /* Write memaddr. */
88d1aa9d 2666 addr = netorder64 (record_full_list->u.mem.addr);
bef155c3 2667 bfdcore_write (obfd.get (), osec, &addr,
d02ed0bb
MM
2668 sizeof (addr), &bfd_offset);
2669
2670 /* Write memval. */
bef155c3 2671 bfdcore_write (obfd.get (), osec,
88d1aa9d
MM
2672 record_full_get_loc (record_full_list),
2673 record_full_list->u.mem.len, &bfd_offset);
dda83cd7 2674 break;
d02ed0bb 2675
dda83cd7 2676 case record_full_end:
d02ed0bb 2677 if (record_debug)
6cb06a8c
TT
2678 gdb_printf (gdb_stdlog,
2679 " Writing record_full_end (1 + "
2680 "%lu + %lu bytes)\n",
2681 (unsigned long) sizeof (signal),
2682 (unsigned long) sizeof (count));
d02ed0bb 2683 /* Write signal value. */
88d1aa9d 2684 signal = netorder32 (record_full_list->u.end.sigval);
bef155c3 2685 bfdcore_write (obfd.get (), osec, &signal,
d02ed0bb
MM
2686 sizeof (signal), &bfd_offset);
2687
2688 /* Write insn count. */
88d1aa9d 2689 count = netorder32 (record_full_list->u.end.insn_num);
bef155c3 2690 bfdcore_write (obfd.get (), osec, &count,
d02ed0bb 2691 sizeof (count), &bfd_offset);
dda83cd7
SM
2692 break;
2693 }
2694 }
d02ed0bb
MM
2695
2696 /* Execute entry. */
88d1aa9d 2697 record_full_exec_insn (regcache, gdbarch, record_full_list);
d02ed0bb 2698
88d1aa9d 2699 if (record_full_list->next)
dda83cd7 2700 record_full_list = record_full_list->next;
d02ed0bb 2701 else
dda83cd7 2702 break;
d02ed0bb
MM
2703 }
2704
88d1aa9d 2705 /* Reverse execute to cur_record_full_list. */
d02ed0bb
MM
2706 while (1)
2707 {
2708 /* Check for beginning and end of log. */
88d1aa9d 2709 if (record_full_list == cur_record_full_list)
dda83cd7 2710 break;
d02ed0bb 2711
88d1aa9d 2712 record_full_exec_insn (regcache, gdbarch, record_full_list);
d02ed0bb 2713
88d1aa9d 2714 if (record_full_list->prev)
dda83cd7 2715 record_full_list = record_full_list->prev;
d02ed0bb
MM
2716 }
2717
bef155c3 2718 unlink_file.keep ();
d02ed0bb
MM
2719
2720 /* Succeeded. */
6cb06a8c
TT
2721 gdb_printf (_("Saved core file %s with execution log.\n"),
2722 recfilename);
d02ed0bb
MM
2723}
2724
88d1aa9d 2725/* record_full_goto_insn -- rewind the record log (forward or backward,
d02ed0bb
MM
2726 depending on DIR) to the given entry, changing the program state
2727 correspondingly. */
2728
2729static void
88d1aa9d
MM
2730record_full_goto_insn (struct record_full_entry *entry,
2731 enum exec_direction_kind dir)
d02ed0bb 2732{
07036511
TT
2733 scoped_restore restore_operation_disable
2734 = record_full_gdb_operation_disable_set ();
9c742269 2735 regcache *regcache = get_thread_regcache (inferior_thread ());
ac7936df 2736 struct gdbarch *gdbarch = regcache->arch ();
d02ed0bb
MM
2737
2738 /* Assume everything is valid: we will hit the entry,
2739 and we will not hit the end of the recording. */
2740
2741 if (dir == EXEC_FORWARD)
88d1aa9d 2742 record_full_list = record_full_list->next;
d02ed0bb
MM
2743
2744 do
2745 {
88d1aa9d 2746 record_full_exec_insn (regcache, gdbarch, record_full_list);
d02ed0bb 2747 if (dir == EXEC_REVERSE)
88d1aa9d 2748 record_full_list = record_full_list->prev;
d02ed0bb 2749 else
88d1aa9d
MM
2750 record_full_list = record_full_list->next;
2751 } while (record_full_list != entry);
d02ed0bb
MM
2752}
2753
2754/* Alias for "target record-full". */
2755
2756static void
981a3fb3 2757cmd_record_full_start (const char *args, int from_tty)
d02ed0bb 2758{
95a6b0a1 2759 execute_command ("target record-full", from_tty);
d02ed0bb
MM
2760}
2761
2762static void
eb4c3f4a 2763set_record_full_insn_max_num (const char *args, int from_tty,
88d1aa9d 2764 struct cmd_list_element *c)
d02ed0bb 2765{
7ee70bf5 2766 if (record_full_insn_num > record_full_insn_max_num)
d02ed0bb 2767 {
88d1aa9d
MM
2768 /* Count down record_full_insn_num while releasing records from list. */
2769 while (record_full_insn_num > record_full_insn_max_num)
d02ed0bb 2770 {
dda83cd7
SM
2771 record_full_list_release_first ();
2772 record_full_insn_num--;
d02ed0bb
MM
2773 }
2774 }
2775}
2776
e24d337e
BL
2777/* Implement the 'maintenance print record-instruction' command. */
2778
2779static void
2780maintenance_print_record_instruction (const char *args, int from_tty)
2781{
2782 struct record_full_entry *to_print = record_full_list;
2783
2784 if (args != nullptr)
2785 {
2786 int offset = value_as_long (parse_and_eval (args));
2787 if (offset > 0)
2788 {
2789 /* Move forward OFFSET instructions. We know we found the
2790 end of an instruction when to_print->type is record_full_end. */
2791 while (to_print->next != nullptr && offset > 0)
2792 {
2793 to_print = to_print->next;
2794 if (to_print->type == record_full_end)
2795 offset--;
2796 }
2797 if (offset != 0)
2798 error (_("Not enough recorded history"));
2799 }
2800 else
2801 {
2802 while (to_print->prev != nullptr && offset < 0)
2803 {
2804 to_print = to_print->prev;
2805 if (to_print->type == record_full_end)
2806 offset++;
2807 }
2808 if (offset != 0)
2809 error (_("Not enough recorded history"));
2810 }
2811 }
2812 gdb_assert (to_print != nullptr);
2813
99d9c3b9
SM
2814 gdbarch *arch = current_inferior ()->arch ();
2815
e24d337e
BL
2816 /* Go back to the start of the instruction. */
2817 while (to_print->prev != nullptr && to_print->prev->type != record_full_end)
2818 to_print = to_print->prev;
2819
2820 /* if we're in the first record, there are no actual instructions
2821 recorded. Warn the user and leave. */
2822 if (to_print == &record_full_first)
2823 error (_("Not enough recorded history"));
2824
2825 while (to_print->type != record_full_end)
2826 {
2827 switch (to_print->type)
2828 {
2829 case record_full_reg:
2830 {
99d9c3b9 2831 type *regtype = gdbarch_register_type (arch, to_print->u.reg.num);
e24d337e
BL
2832 value *val
2833 = value_from_contents (regtype,
2834 record_full_get_loc (to_print));
2835 gdb_printf ("Register %s changed: ",
99d9c3b9 2836 gdbarch_register_name (arch, to_print->u.reg.num));
e24d337e
BL
2837 struct value_print_options opts;
2838 get_user_print_options (&opts);
2839 opts.raw = true;
2840 value_print (val, gdb_stdout, &opts);
2841 gdb_printf ("\n");
2842 break;
2843 }
2844 case record_full_mem:
2845 {
2846 gdb_byte *b = record_full_get_loc (to_print);
2847 gdb_printf ("%d bytes of memory at address %s changed from:",
2848 to_print->u.mem.len,
99d9c3b9 2849 print_core_address (arch, to_print->u.mem.addr));
e24d337e
BL
2850 for (int i = 0; i < to_print->u.mem.len; i++)
2851 gdb_printf (" %02x", b[i]);
2852 gdb_printf ("\n");
2853 break;
2854 }
2855 }
2856 to_print = to_print->next;
2857 }
2858}
2859
6c265988 2860void _initialize_record_full ();
d02ed0bb 2861void
6c265988 2862_initialize_record_full ()
d02ed0bb
MM
2863{
2864 struct cmd_list_element *c;
2865
88d1aa9d
MM
2866 /* Init record_full_first. */
2867 record_full_first.prev = NULL;
2868 record_full_first.next = NULL;
2869 record_full_first.type = record_full_end;
d02ed0bb 2870
d9f719f1
PA
2871 add_target (record_full_target_info, record_full_open);
2872 add_deprecated_target_alias (record_full_target_info, "record");
2873 add_target (record_full_core_target_info, record_full_open);
d02ed0bb 2874
88d1aa9d 2875 add_prefix_cmd ("full", class_obscure, cmd_record_full_start,
d02ed0bb 2876 _("Start full execution recording."), &record_full_cmdlist,
2f822da5 2877 0, &record_cmdlist);
d02ed0bb 2878
5e84b7ee
SM
2879 cmd_list_element *record_full_restore_cmd
2880 = add_cmd ("restore", class_obscure, cmd_record_full_restore,
d02ed0bb
MM
2881 _("Restore the execution log from a file.\n\
2882Argument is filename. File must be created with 'record save'."),
2883 &record_full_cmdlist);
5e84b7ee 2884 set_cmd_completer (record_full_restore_cmd, filename_completer);
d02ed0bb
MM
2885
2886 /* Deprecate the old version without "full" prefix. */
5e84b7ee 2887 c = add_alias_cmd ("restore", record_full_restore_cmd, class_obscure, 1,
d02ed0bb
MM
2888 &record_cmdlist);
2889 set_cmd_completer (c, filename_completer);
2890 deprecate_cmd (c, "record full restore");
2891
f54bdb6d
SM
2892 add_setshow_prefix_cmd ("full", class_support,
2893 _("Set record options."),
2894 _("Show record options."),
2895 &set_record_full_cmdlist,
2896 &show_record_full_cmdlist,
2897 &set_record_cmdlist,
2898 &show_record_cmdlist);
d02ed0bb
MM
2899
2900 /* Record instructions number limit command. */
5e84b7ee
SM
2901 set_show_commands set_record_full_stop_at_limit_cmds
2902 = add_setshow_boolean_cmd ("stop-at-limit", no_class,
2903 &record_full_stop_at_limit, _("\
d02ed0bb
MM
2904Set whether record/replay stops when record/replay buffer becomes full."), _("\
2905Show whether record/replay stops when record/replay buffer becomes full."),
2906 _("Default is ON.\n\
2907When ON, if the record/replay buffer becomes full, ask user what to do.\n\
2908When OFF, if the record/replay buffer becomes full,\n\
2909delete the oldest recorded instruction to make room for each new one."),
5e84b7ee
SM
2910 NULL, NULL,
2911 &set_record_full_cmdlist,
2912 &show_record_full_cmdlist);
d02ed0bb 2913
5e84b7ee
SM
2914 c = add_alias_cmd ("stop-at-limit",
2915 set_record_full_stop_at_limit_cmds.set, no_class, 1,
d02ed0bb
MM
2916 &set_record_cmdlist);
2917 deprecate_cmd (c, "set record full stop-at-limit");
2918
5e84b7ee
SM
2919 c = add_alias_cmd ("stop-at-limit",
2920 set_record_full_stop_at_limit_cmds.show, no_class, 1,
d02ed0bb
MM
2921 &show_record_cmdlist);
2922 deprecate_cmd (c, "show record full stop-at-limit");
2923
5e84b7ee
SM
2924 set_show_commands record_full_insn_number_max_cmds
2925 = add_setshow_uinteger_cmd ("insn-number-max", no_class,
2926 &record_full_insn_max_num,
2927 _("Set record/replay buffer limit."),
2928 _("Show record/replay buffer limit."), _("\
d02ed0bb 2929Set the maximum number of instructions to be stored in the\n\
f81d1120
PA
2930record/replay buffer. A value of either \"unlimited\" or zero means no\n\
2931limit. Default is 200000."),
5e84b7ee
SM
2932 set_record_full_insn_max_num,
2933 NULL, &set_record_full_cmdlist,
2934 &show_record_full_cmdlist);
d02ed0bb 2935
5e84b7ee
SM
2936 c = add_alias_cmd ("insn-number-max", record_full_insn_number_max_cmds.set,
2937 no_class, 1, &set_record_cmdlist);
d02ed0bb
MM
2938 deprecate_cmd (c, "set record full insn-number-max");
2939
5e84b7ee
SM
2940 c = add_alias_cmd ("insn-number-max", record_full_insn_number_max_cmds.show,
2941 no_class, 1, &show_record_cmdlist);
d02ed0bb
MM
2942 deprecate_cmd (c, "show record full insn-number-max");
2943
5e84b7ee
SM
2944 set_show_commands record_full_memory_query_cmds
2945 = add_setshow_boolean_cmd ("memory-query", no_class,
2946 &record_full_memory_query, _("\
d02ed0bb 2947Set whether query if PREC cannot record memory change of next instruction."),
5e84b7ee 2948 _("\
d02ed0bb 2949Show whether query if PREC cannot record memory change of next instruction."),
5e84b7ee 2950 _("\
d02ed0bb
MM
2951Default is OFF.\n\
2952When ON, query if PREC cannot record memory change of next instruction."),
5e84b7ee
SM
2953 NULL, NULL,
2954 &set_record_full_cmdlist,
2955 &show_record_full_cmdlist);
d02ed0bb 2956
5e84b7ee
SM
2957 c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.set,
2958 no_class, 1, &set_record_cmdlist);
d02ed0bb
MM
2959 deprecate_cmd (c, "set record full memory-query");
2960
5e84b7ee
SM
2961 c = add_alias_cmd ("memory-query", record_full_memory_query_cmds.show,
2962 no_class, 1,&show_record_cmdlist);
d02ed0bb 2963 deprecate_cmd (c, "show record full memory-query");
e24d337e
BL
2964
2965 add_cmd ("record-instruction", class_maintenance,
2966 maintenance_print_record_instruction,
2967 _("\
2968Print a recorded instruction.\n\
2969If no argument is provided, print the last instruction recorded.\n\
2970If a negative argument is given, prints how the nth previous \
2971instruction will be undone.\n\
2972If a positive argument is given, prints \
2973how the nth following instruction will be redone."), &maintenanceprintlist);
d02ed0bb 2974}