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, ®num,
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, ®num,
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