* i386-tdep.c (i386_frame_prev_register): Unwind SP from memory
[deliverable/binutils-gdb.git] / gdb / reverse.c
CommitLineData
b2175913
MS
1/* Reverse execution and reverse debugging.
2
7b6bb8da
JB
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
b2175913
MS
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
5b1ba0e5 10 the Free Software Foundation; either version 3 of the License, or
b2175913
MS
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
5b1ba0e5 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
b2175913
MS
20
21#include "defs.h"
22#include "gdb_string.h"
23#include "target.h"
24#include "top.h"
25#include "cli/cli-cmds.h"
26#include "cli/cli-decode.h"
e9cafbcc 27#include "cli/cli-utils.h"
b2175913 28#include "inferior.h"
6b04bdb7 29#include "regcache.h"
b2175913
MS
30
31/* User interface:
32 reverse-step, reverse-next etc. */
33
b4f899bb
MS
34static void
35exec_direction_default (void *notused)
b2175913
MS
36{
37 /* Return execution direction to default state. */
38 execution_direction = EXEC_FORWARD;
39}
40
41/* exec_reverse_once -- accepts an arbitrary gdb command (string),
42 and executes it with exec-direction set to 'reverse'.
43
44 Used to implement reverse-next etc. commands. */
45
46static void
47exec_reverse_once (char *cmd, char *args, int from_tty)
48{
49 char *reverse_command;
50 enum exec_direction_kind dir = execution_direction;
51 struct cleanup *old_chain;
52
53 if (dir == EXEC_ERROR)
54 error (_("Target %s does not support this command."), target_shortname);
55
56 if (dir == EXEC_REVERSE)
57 error (_("Already in reverse mode. Use '%s' or 'set exec-dir forward'."),
58 cmd);
59
60 if (!target_can_execute_reverse)
61 error (_("Target %s does not support this command."), target_shortname);
62
63 reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
64 old_chain = make_cleanup (exec_direction_default, NULL);
65 make_cleanup (xfree, reverse_command);
66 execution_direction = EXEC_REVERSE;
67 execute_command (reverse_command, from_tty);
68 do_cleanups (old_chain);
69}
70
71static void
72reverse_step (char *args, int from_tty)
73{
74 exec_reverse_once ("step", args, from_tty);
75}
76
77static void
78reverse_stepi (char *args, int from_tty)
79{
80 exec_reverse_once ("stepi", args, from_tty);
81}
82
83static void
84reverse_next (char *args, int from_tty)
85{
86 exec_reverse_once ("next", args, from_tty);
87}
88
89static void
90reverse_nexti (char *args, int from_tty)
91{
92 exec_reverse_once ("nexti", args, from_tty);
93}
94
95static void
96reverse_continue (char *args, int from_tty)
97{
98 exec_reverse_once ("continue", args, from_tty);
99}
100
101static void
102reverse_finish (char *args, int from_tty)
103{
104 exec_reverse_once ("finish", args, from_tty);
105}
106
6b04bdb7
MS
107/* Data structures for a bookmark list. */
108
109struct bookmark {
110 struct bookmark *next;
111 int number;
112 CORE_ADDR pc;
113 struct symtab_and_line sal;
114 gdb_byte *opaque_data;
115};
116
117static struct bookmark *bookmark_chain;
118static int bookmark_count;
119
120#define ALL_BOOKMARKS(B) for ((B) = bookmark_chain; (B); (B) = (B)->next)
121
122#define ALL_BOOKMARKS_SAFE(B,TMP) \
123 for ((B) = bookmark_chain; \
124 (B) ? ((TMP) = (B)->next, 1) : 0; \
125 (B) = (TMP))
126
127/* save_bookmark_command -- implement "bookmark" command.
128 Call target method to get a bookmark identifier.
129 Insert bookmark identifier into list.
130
131 Identifier will be a malloc string (gdb_byte *).
132 Up to us to free it as required. */
133
134static void
135save_bookmark_command (char *args, int from_tty)
136{
137 /* Get target's idea of a bookmark. */
138 gdb_byte *bookmark_id = target_get_bookmark (args, from_tty);
139 struct bookmark *b, *b1;
140 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
141
142 /* CR should not cause another identical bookmark. */
143 dont_repeat ();
144
145 if (bookmark_id == NULL)
146 error (_("target_get_bookmark failed."));
147
148 /* Set up a bookmark struct. */
149 b = xcalloc (1, sizeof (struct bookmark));
150 b->number = ++bookmark_count;
151 init_sal (&b->sal);
152 b->pc = regcache_read_pc (get_current_regcache ());
153 b->sal = find_pc_line (b->pc, 0);
154 b->sal.pspace = get_frame_program_space (get_current_frame ());
155 b->opaque_data = bookmark_id;
156 b->next = NULL;
157
158 /* Add this bookmark to the end of the chain, so that a list
159 of bookmarks will come out in order of increasing numbers. */
160
161 b1 = bookmark_chain;
162 if (b1 == 0)
163 bookmark_chain = b;
164 else
165 {
166 while (b1->next)
167 b1 = b1->next;
168 b1->next = b;
169 }
170 printf_filtered (_("Saved bookmark %d at %s\n"), b->number,
171 paddress (gdbarch, b->sal.pc));
172}
173
174/* Implement "delete bookmark" command. */
175
176static int
7d357efd 177delete_one_bookmark (int num)
6b04bdb7 178{
7d357efd
MS
179 struct bookmark *b1, *b;
180
181 /* Find bookmark with corresponding number. */
182 ALL_BOOKMARKS (b)
183 if (b->number == num)
184 break;
6b04bdb7
MS
185
186 /* Special case, first item in list. */
187 if (b == bookmark_chain)
188 bookmark_chain = b->next;
189
190 /* Find bookmark preceeding "marked" one, so we can unlink. */
191 if (b)
192 {
193 ALL_BOOKMARKS (b1)
194 if (b1->next == b)
195 {
196 /* Found designated bookmark. Unlink and delete. */
197 b1->next = b->next;
198 break;
199 }
200 xfree (b->opaque_data);
201 xfree (b);
202 return 1; /* success */
203 }
204 return 0; /* failure */
205}
206
207static void
208delete_all_bookmarks (void)
209{
210 struct bookmark *b, *b1;
211
212 ALL_BOOKMARKS_SAFE (b, b1)
213 {
214 xfree (b->opaque_data);
215 xfree (b);
216 }
217 bookmark_chain = NULL;
218}
219
220static void
221delete_bookmark_command (char *args, int from_tty)
222{
6b4398f7 223 struct bookmark *b;
7d357efd 224 int num;
197f0a60 225 struct get_number_or_range_state state;
6b04bdb7
MS
226
227 if (bookmark_chain == NULL)
228 {
229 warning (_("No bookmarks."));
230 return;
231 }
232
233 if (args == NULL || args[0] == '\0')
234 {
235 if (from_tty && !query (_("Delete all bookmarks? ")))
236 return;
237 delete_all_bookmarks ();
238 return;
239 }
240
197f0a60
TT
241 init_number_or_range (&state, args);
242 while (!state.finished)
7d357efd 243 {
197f0a60 244 num = get_number_or_range (&state);
7d357efd
MS
245 if (!delete_one_bookmark (num))
246 /* Not found. */
247 warning (_("No bookmark #%d."), num);
248 }
6b04bdb7
MS
249}
250
251/* Implement "goto-bookmark" command. */
252
253static void
254goto_bookmark_command (char *args, int from_tty)
255{
256 struct bookmark *b;
257 unsigned long num;
258
259 if (args == NULL || args[0] == '\0')
260 error (_("Command requires an argument."));
261
262 if (strncmp (args, "start", strlen ("start")) == 0
263 || strncmp (args, "begin", strlen ("begin")) == 0
264 || strncmp (args, "end", strlen ("end")) == 0)
265 {
266 /* Special case. Give target opportunity to handle. */
267 target_goto_bookmark (args, from_tty);
268 return;
269 }
270
271 if (args[0] == '\'' || args[0] == '\"')
272 {
273 /* Special case -- quoted string. Pass on to target. */
274 if (args[strlen (args) - 1] != args[0])
275 error (_("Unbalanced quotes: %s"), args);
276 target_goto_bookmark (args, from_tty);
277 return;
278 }
279
280 /* General case. Bookmark identified by bookmark number. */
7d357efd 281 num = get_number (&args);
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. */
293 error (_("goto-bookmark: no bookmark found for '%s'."), args);
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}
This page took 0.279995 seconds and 4 git commands to generate.