daily update
[deliverable/binutils-gdb.git] / gdb / reverse.c
CommitLineData
b2175913
MS
1/* Reverse execution and reverse debugging.
2
0b302171 3 Copyright (C) 2006-2012 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"
21#include "gdb_string.h"
22#include "target.h"
23#include "top.h"
24#include "cli/cli-cmds.h"
25#include "cli/cli-decode.h"
e9cafbcc 26#include "cli/cli-utils.h"
b2175913 27#include "inferior.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. */
145 b = xcalloc (1, sizeof (struct bookmark));
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{
6b4398f7 219 struct bookmark *b;
7d357efd 220 int num;
197f0a60 221 struct get_number_or_range_state state;
6b04bdb7
MS
222
223 if (bookmark_chain == NULL)
224 {
225 warning (_("No bookmarks."));
226 return;
227 }
228
229 if (args == NULL || args[0] == '\0')
230 {
231 if (from_tty && !query (_("Delete all bookmarks? ")))
232 return;
233 delete_all_bookmarks ();
234 return;
235 }
236
197f0a60
TT
237 init_number_or_range (&state, args);
238 while (!state.finished)
7d357efd 239 {
197f0a60 240 num = get_number_or_range (&state);
7d357efd
MS
241 if (!delete_one_bookmark (num))
242 /* Not found. */
243 warning (_("No bookmark #%d."), num);
244 }
6b04bdb7
MS
245}
246
247/* Implement "goto-bookmark" command. */
248
249static void
250goto_bookmark_command (char *args, int from_tty)
251{
252 struct bookmark *b;
253 unsigned long num;
254
255 if (args == NULL || args[0] == '\0')
256 error (_("Command requires an argument."));
257
258 if (strncmp (args, "start", strlen ("start")) == 0
259 || strncmp (args, "begin", strlen ("begin")) == 0
260 || strncmp (args, "end", strlen ("end")) == 0)
261 {
262 /* Special case. Give target opportunity to handle. */
263 target_goto_bookmark (args, from_tty);
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);
272 target_goto_bookmark (args, from_tty);
273 return;
274 }
275
276 /* General case. Bookmark identified by bookmark number. */
7d357efd 277 num = get_number (&args);
6b04bdb7
MS
278 ALL_BOOKMARKS (b)
279 if (b->number == num)
280 break;
281
282 if (b)
283 {
284 /* Found. Send to target method. */
285 target_goto_bookmark (b->opaque_data, from_tty);
286 return;
287 }
288 /* Not found. */
289 error (_("goto-bookmark: no bookmark found for '%s'."), args);
290}
291
7d357efd
MS
292static int
293bookmark_1 (int bnum)
294{
295 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
296 struct bookmark *b;
297 int matched = 0;
298
299 ALL_BOOKMARKS (b)
300 {
301 if (bnum == -1 || bnum == b->number)
302 {
303 printf_filtered (" %d %s '%s'\n",
304 b->number,
305 paddress (gdbarch, b->pc),
306 b->opaque_data);
307 matched++;
308 }
309 }
310
311 if (bnum > 0 && matched == 0)
312 printf_filtered ("No bookmark #%d\n", bnum);
313
314 return matched;
315}
316
6b04bdb7
MS
317/* Implement "info bookmarks" command. */
318
319static void
320bookmarks_info (char *args, int from_tty)
321{
6b04bdb7 322 int bnum = -1;
6b04bdb7
MS
323
324 if (!bookmark_chain)
7d357efd
MS
325 printf_filtered (_("No bookmarks.\n"));
326 else if (args == NULL || *args == '\0')
327 bookmark_1 (-1);
328 else
197f0a60
TT
329 {
330 struct get_number_or_range_state state;
331
332 init_number_or_range (&state, args);
333 while (!state.finished)
334 {
335 bnum = get_number_or_range (&state);
336 bookmark_1 (bnum);
337 }
338 }
6b04bdb7
MS
339}
340
341
2c0b251b
PA
342/* Provide a prototype to silence -Wmissing-prototypes. */
343extern initialize_file_ftype _initialize_reverse;
344
b2175913
MS
345void
346_initialize_reverse (void)
347{
348 add_com ("reverse-step", class_run, reverse_step, _("\
349Step program backward until it reaches the beginning of another source line.\n\
350Argument N means do this N times (or till program stops for another reason).")
351 );
352 add_com_alias ("rs", "reverse-step", class_alias, 1);
353
354 add_com ("reverse-next", class_run, reverse_next, _("\
355Step program backward, proceeding through subroutine calls.\n\
356Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
357when they do, the call is treated as one instruction.\n\
358Argument N means do this N times (or till program stops for another reason).")
359 );
360 add_com_alias ("rn", "reverse-next", class_alias, 1);
361
362 add_com ("reverse-stepi", class_run, reverse_stepi, _("\
363Step backward exactly one instruction.\n\
364Argument N means do this N times (or till program stops for another reason).")
365 );
366 add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
367
368 add_com ("reverse-nexti", class_run, reverse_nexti, _("\
369Step backward one instruction, but proceed through called subroutines.\n\
370Argument N means do this N times (or till program stops for another reason).")
371 );
372 add_com_alias ("rni", "reverse-nexti", class_alias, 0);
373
374 add_com ("reverse-continue", class_run, reverse_continue, _("\
375Continue program being debugged but run it in reverse.\n\
376If proceeding from breakpoint, a number N may be used as an argument,\n\
377which means to set the ignore count of that breakpoint to N - 1 (so that\n\
378the breakpoint won't break until the Nth time it is reached)."));
379 add_com_alias ("rc", "reverse-continue", class_alias, 0);
380
381 add_com ("reverse-finish", class_run, reverse_finish, _("\
382Execute backward until just before selected stack frame is called."));
6b04bdb7
MS
383
384 add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
385Set a bookmark in the program's execution history.\n\
386A bookmark represents a point in the execution history \n\
387that can be returned to at a later point in the debug session."));
388 add_info ("bookmarks", bookmarks_info, _("\
389Status of user-settable bookmarks.\n\
390Bookmarks are user-settable markers representing a point in the \n\
391execution history that can be returned to later in the same debug \n\
392session."));
393 add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
394Delete a bookmark from the bookmark list.\n\
7d357efd
MS
395Argument is a bookmark number or numbers,\n\
396 or no argument to delete all bookmarks.\n"),
6b04bdb7
MS
397 &deletelist);
398 add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
399Go to an earlier-bookmarked point in the program's execution history.\n\
400Argument is the bookmark number of a bookmark saved earlier by using \n\
401the 'bookmark' command, or the special arguments:\n\
402 start (beginning of recording)\n\
403 end (end of recording)\n"));
b2175913 404}
This page took 0.423497 seconds and 4 git commands to generate.