]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/reverse.c
GDB copyright headers update after running GDB's copyright.py script.
[thirdparty/binutils-gdb.git] / gdb / reverse.c
CommitLineData
b2175913
MS
1/* Reverse execution and reverse debugging.
2
618f726f 3 Copyright (C) 2006-2016 Free Software Foundation, Inc.
b2175913
MS
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
5b1ba0e5 9 the Free Software Foundation; either version 3 of the License, or
b2175913
MS
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
5b1ba0e5 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
b2175913
MS
19
20#include "defs.h"
b2175913
MS
21#include "target.h"
22#include "top.h"
23#include "cli/cli-cmds.h"
24#include "cli/cli-decode.h"
e9cafbcc 25#include "cli/cli-utils.h"
b2175913 26#include "inferior.h"
45741a9c 27#include "infrun.h"
6b04bdb7 28#include "regcache.h"
b2175913
MS
29
30/* User interface:
31 reverse-step, reverse-next etc. */
32
b4f899bb
MS
33static void
34exec_direction_default (void *notused)
b2175913
MS
35{
36 /* Return execution direction to default state. */
37 execution_direction = EXEC_FORWARD;
38}
39
40/* exec_reverse_once -- accepts an arbitrary gdb command (string),
41 and executes it with exec-direction set to 'reverse'.
42
43 Used to implement reverse-next etc. commands. */
44
45static void
46exec_reverse_once (char *cmd, char *args, int from_tty)
47{
48 char *reverse_command;
49 enum exec_direction_kind dir = execution_direction;
50 struct cleanup *old_chain;
51
b2175913
MS
52 if (dir == EXEC_REVERSE)
53 error (_("Already in reverse mode. Use '%s' or 'set exec-dir forward'."),
54 cmd);
55
56 if (!target_can_execute_reverse)
57 error (_("Target %s does not support this command."), target_shortname);
58
59 reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
60 old_chain = make_cleanup (exec_direction_default, NULL);
61 make_cleanup (xfree, reverse_command);
62 execution_direction = EXEC_REVERSE;
63 execute_command (reverse_command, from_tty);
64 do_cleanups (old_chain);
65}
66
67static void
68reverse_step (char *args, int from_tty)
69{
70 exec_reverse_once ("step", args, from_tty);
71}
72
73static void
74reverse_stepi (char *args, int from_tty)
75{
76 exec_reverse_once ("stepi", args, from_tty);
77}
78
79static void
80reverse_next (char *args, int from_tty)
81{
82 exec_reverse_once ("next", args, from_tty);
83}
84
85static void
86reverse_nexti (char *args, int from_tty)
87{
88 exec_reverse_once ("nexti", args, from_tty);
89}
90
91static void
92reverse_continue (char *args, int from_tty)
93{
94 exec_reverse_once ("continue", args, from_tty);
95}
96
97static void
98reverse_finish (char *args, int from_tty)
99{
100 exec_reverse_once ("finish", args, from_tty);
101}
102
6b04bdb7
MS
103/* Data structures for a bookmark list. */
104
105struct bookmark {
106 struct bookmark *next;
107 int number;
108 CORE_ADDR pc;
109 struct symtab_and_line sal;
110 gdb_byte *opaque_data;
111};
112
113static struct bookmark *bookmark_chain;
114static int bookmark_count;
115
116#define ALL_BOOKMARKS(B) for ((B) = bookmark_chain; (B); (B) = (B)->next)
117
118#define ALL_BOOKMARKS_SAFE(B,TMP) \
119 for ((B) = bookmark_chain; \
120 (B) ? ((TMP) = (B)->next, 1) : 0; \
121 (B) = (TMP))
122
123/* save_bookmark_command -- implement "bookmark" command.
124 Call target method to get a bookmark identifier.
125 Insert bookmark identifier into list.
126
127 Identifier will be a malloc string (gdb_byte *).
128 Up to us to free it as required. */
129
130static void
131save_bookmark_command (char *args, int from_tty)
132{
133 /* Get target's idea of a bookmark. */
134 gdb_byte *bookmark_id = target_get_bookmark (args, from_tty);
135 struct bookmark *b, *b1;
136 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
137
138 /* CR should not cause another identical bookmark. */
139 dont_repeat ();
140
141 if (bookmark_id == NULL)
142 error (_("target_get_bookmark failed."));
143
144 /* Set up a bookmark struct. */
8d749320 145 b = XCNEW (struct bookmark);
6b04bdb7
MS
146 b->number = ++bookmark_count;
147 init_sal (&b->sal);
148 b->pc = regcache_read_pc (get_current_regcache ());
149 b->sal = find_pc_line (b->pc, 0);
150 b->sal.pspace = get_frame_program_space (get_current_frame ());
151 b->opaque_data = bookmark_id;
152 b->next = NULL;
153
154 /* Add this bookmark to the end of the chain, so that a list
155 of bookmarks will come out in order of increasing numbers. */
156
157 b1 = bookmark_chain;
158 if (b1 == 0)
159 bookmark_chain = b;
160 else
161 {
162 while (b1->next)
163 b1 = b1->next;
164 b1->next = b;
165 }
166 printf_filtered (_("Saved bookmark %d at %s\n"), b->number,
167 paddress (gdbarch, b->sal.pc));
168}
169
170/* Implement "delete bookmark" command. */
171
172static int
7d357efd 173delete_one_bookmark (int num)
6b04bdb7 174{
7d357efd
MS
175 struct bookmark *b1, *b;
176
177 /* Find bookmark with corresponding number. */
178 ALL_BOOKMARKS (b)
179 if (b->number == num)
180 break;
6b04bdb7
MS
181
182 /* Special case, first item in list. */
183 if (b == bookmark_chain)
184 bookmark_chain = b->next;
185
177b42fe 186 /* Find bookmark preceding "marked" one, so we can unlink. */
6b04bdb7
MS
187 if (b)
188 {
189 ALL_BOOKMARKS (b1)
190 if (b1->next == b)
191 {
192 /* Found designated bookmark. Unlink and delete. */
193 b1->next = b->next;
194 break;
195 }
196 xfree (b->opaque_data);
197 xfree (b);
198 return 1; /* success */
199 }
200 return 0; /* failure */
201}
202
203static void
204delete_all_bookmarks (void)
205{
206 struct bookmark *b, *b1;
207
208 ALL_BOOKMARKS_SAFE (b, b1)
209 {
210 xfree (b->opaque_data);
211 xfree (b);
212 }
213 bookmark_chain = NULL;
214}
215
216static void
217delete_bookmark_command (char *args, int from_tty)
218{
7d357efd 219 int num;
197f0a60 220 struct get_number_or_range_state state;
6b04bdb7
MS
221
222 if (bookmark_chain == NULL)
223 {
224 warning (_("No bookmarks."));
225 return;
226 }
227
228 if (args == NULL || args[0] == '\0')
229 {
230 if (from_tty && !query (_("Delete all bookmarks? ")))
231 return;
232 delete_all_bookmarks ();
233 return;
234 }
235
197f0a60
TT
236 init_number_or_range (&state, args);
237 while (!state.finished)
7d357efd 238 {
197f0a60 239 num = get_number_or_range (&state);
7d357efd
MS
240 if (!delete_one_bookmark (num))
241 /* Not found. */
242 warning (_("No bookmark #%d."), num);
243 }
6b04bdb7
MS
244}
245
246/* Implement "goto-bookmark" command. */
247
248static void
249goto_bookmark_command (char *args, int from_tty)
250{
251 struct bookmark *b;
252 unsigned long num;
0c13193f 253 char *p = args;
6b04bdb7
MS
254
255 if (args == NULL || args[0] == '\0')
256 error (_("Command requires an argument."));
257
61012eef
GB
258 if (startswith (args, "start")
259 || startswith (args, "begin")
260 || startswith (args, "end"))
6b04bdb7
MS
261 {
262 /* Special case. Give target opportunity to handle. */
0f928d68 263 target_goto_bookmark ((gdb_byte *) args, from_tty);
6b04bdb7
MS
264 return;
265 }
266
267 if (args[0] == '\'' || args[0] == '\"')
268 {
269 /* Special case -- quoted string. Pass on to target. */
270 if (args[strlen (args) - 1] != args[0])
271 error (_("Unbalanced quotes: %s"), args);
0f928d68 272 target_goto_bookmark ((gdb_byte *) args, from_tty);
6b04bdb7
MS
273 return;
274 }
275
276 /* General case. Bookmark identified by bookmark number. */
7d357efd 277 num = get_number (&args);
0c13193f
YQ
278
279 if (num == 0)
280 error (_("goto-bookmark: invalid bookmark number '%s'."), p);
281
6b04bdb7
MS
282 ALL_BOOKMARKS (b)
283 if (b->number == num)
284 break;
285
286 if (b)
287 {
288 /* Found. Send to target method. */
289 target_goto_bookmark (b->opaque_data, from_tty);
290 return;
291 }
292 /* Not found. */
0c13193f 293 error (_("goto-bookmark: no bookmark found for '%s'."), p);
6b04bdb7
MS
294}
295
7d357efd
MS
296static int
297bookmark_1 (int bnum)
298{
299 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
300 struct bookmark *b;
301 int matched = 0;
302
303 ALL_BOOKMARKS (b)
304 {
305 if (bnum == -1 || bnum == b->number)
306 {
307 printf_filtered (" %d %s '%s'\n",
308 b->number,
309 paddress (gdbarch, b->pc),
310 b->opaque_data);
311 matched++;
312 }
313 }
314
315 if (bnum > 0 && matched == 0)
316 printf_filtered ("No bookmark #%d\n", bnum);
317
318 return matched;
319}
320
6b04bdb7
MS
321/* Implement "info bookmarks" command. */
322
323static void
324bookmarks_info (char *args, int from_tty)
325{
6b04bdb7 326 int bnum = -1;
6b04bdb7
MS
327
328 if (!bookmark_chain)
7d357efd
MS
329 printf_filtered (_("No bookmarks.\n"));
330 else if (args == NULL || *args == '\0')
331 bookmark_1 (-1);
332 else
197f0a60
TT
333 {
334 struct get_number_or_range_state state;
335
336 init_number_or_range (&state, args);
337 while (!state.finished)
338 {
339 bnum = get_number_or_range (&state);
340 bookmark_1 (bnum);
341 }
342 }
6b04bdb7
MS
343}
344
345
2c0b251b
PA
346/* Provide a prototype to silence -Wmissing-prototypes. */
347extern initialize_file_ftype _initialize_reverse;
348
b2175913
MS
349void
350_initialize_reverse (void)
351{
352 add_com ("reverse-step", class_run, reverse_step, _("\
353Step program backward until it reaches the beginning of another source line.\n\
354Argument N means do this N times (or till program stops for another reason).")
355 );
356 add_com_alias ("rs", "reverse-step", class_alias, 1);
357
358 add_com ("reverse-next", class_run, reverse_next, _("\
359Step program backward, proceeding through subroutine calls.\n\
360Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
361when they do, the call is treated as one instruction.\n\
362Argument N means do this N times (or till program stops for another reason).")
363 );
364 add_com_alias ("rn", "reverse-next", class_alias, 1);
365
366 add_com ("reverse-stepi", class_run, reverse_stepi, _("\
367Step backward exactly one instruction.\n\
368Argument N means do this N times (or till program stops for another reason).")
369 );
370 add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
371
372 add_com ("reverse-nexti", class_run, reverse_nexti, _("\
373Step backward one instruction, but proceed through called subroutines.\n\
374Argument N means do this N times (or till program stops for another reason).")
375 );
376 add_com_alias ("rni", "reverse-nexti", class_alias, 0);
377
378 add_com ("reverse-continue", class_run, reverse_continue, _("\
379Continue program being debugged but run it in reverse.\n\
380If proceeding from breakpoint, a number N may be used as an argument,\n\
381which means to set the ignore count of that breakpoint to N - 1 (so that\n\
382the breakpoint won't break until the Nth time it is reached)."));
383 add_com_alias ("rc", "reverse-continue", class_alias, 0);
384
385 add_com ("reverse-finish", class_run, reverse_finish, _("\
386Execute backward until just before selected stack frame is called."));
6b04bdb7
MS
387
388 add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
389Set a bookmark in the program's execution history.\n\
390A bookmark represents a point in the execution history \n\
391that can be returned to at a later point in the debug session."));
392 add_info ("bookmarks", bookmarks_info, _("\
393Status of user-settable bookmarks.\n\
394Bookmarks are user-settable markers representing a point in the \n\
395execution history that can be returned to later in the same debug \n\
396session."));
397 add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
398Delete a bookmark from the bookmark list.\n\
7d357efd
MS
399Argument is a bookmark number or numbers,\n\
400 or no argument to delete all bookmarks.\n"),
6b04bdb7
MS
401 &deletelist);
402 add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
403Go to an earlier-bookmarked point in the program's execution history.\n\
404Argument is the bookmark number of a bookmark saved earlier by using \n\
405the 'bookmark' command, or the special arguments:\n\
406 start (beginning of recording)\n\
407 end (end of recording)\n"));
b2175913 408}