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