* remote.c (remote_close): Reset INFERIOR_PTID to NULL_PTID
[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"
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
52 if (dir == EXEC_ERROR)
53 error (_("Target %s does not support this command."), target_shortname);
54
55 if (dir == EXEC_REVERSE)
56 error (_("Already in reverse mode. Use '%s' or 'set exec-dir forward'."),
57 cmd);
58
59 if (!target_can_execute_reverse)
60 error (_("Target %s does not support this command."), target_shortname);
61
62 reverse_command = xstrprintf ("%s %s", cmd, args ? args : "");
63 old_chain = make_cleanup (exec_direction_default, NULL);
64 make_cleanup (xfree, reverse_command);
65 execution_direction = EXEC_REVERSE;
66 execute_command (reverse_command, from_tty);
67 do_cleanups (old_chain);
68}
69
70static void
71reverse_step (char *args, int from_tty)
72{
73 exec_reverse_once ("step", args, from_tty);
74}
75
76static void
77reverse_stepi (char *args, int from_tty)
78{
79 exec_reverse_once ("stepi", args, from_tty);
80}
81
82static void
83reverse_next (char *args, int from_tty)
84{
85 exec_reverse_once ("next", args, from_tty);
86}
87
88static void
89reverse_nexti (char *args, int from_tty)
90{
91 exec_reverse_once ("nexti", args, from_tty);
92}
93
94static void
95reverse_continue (char *args, int from_tty)
96{
97 exec_reverse_once ("continue", args, from_tty);
98}
99
100static void
101reverse_finish (char *args, int from_tty)
102{
103 exec_reverse_once ("finish", args, from_tty);
104}
105
6b04bdb7
MS
106/* Data structures for a bookmark list. */
107
108struct bookmark {
109 struct bookmark *next;
110 int number;
111 CORE_ADDR pc;
112 struct symtab_and_line sal;
113 gdb_byte *opaque_data;
114};
115
116static struct bookmark *bookmark_chain;
117static int bookmark_count;
118
119#define ALL_BOOKMARKS(B) for ((B) = bookmark_chain; (B); (B) = (B)->next)
120
121#define ALL_BOOKMARKS_SAFE(B,TMP) \
122 for ((B) = bookmark_chain; \
123 (B) ? ((TMP) = (B)->next, 1) : 0; \
124 (B) = (TMP))
125
126/* save_bookmark_command -- implement "bookmark" command.
127 Call target method to get a bookmark identifier.
128 Insert bookmark identifier into list.
129
130 Identifier will be a malloc string (gdb_byte *).
131 Up to us to free it as required. */
132
133static void
134save_bookmark_command (char *args, int from_tty)
135{
136 /* Get target's idea of a bookmark. */
137 gdb_byte *bookmark_id = target_get_bookmark (args, from_tty);
138 struct bookmark *b, *b1;
139 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
140
141 /* CR should not cause another identical bookmark. */
142 dont_repeat ();
143
144 if (bookmark_id == NULL)
145 error (_("target_get_bookmark failed."));
146
147 /* Set up a bookmark struct. */
148 b = xcalloc (1, sizeof (struct bookmark));
149 b->number = ++bookmark_count;
150 init_sal (&b->sal);
151 b->pc = regcache_read_pc (get_current_regcache ());
152 b->sal = find_pc_line (b->pc, 0);
153 b->sal.pspace = get_frame_program_space (get_current_frame ());
154 b->opaque_data = bookmark_id;
155 b->next = NULL;
156
157 /* Add this bookmark to the end of the chain, so that a list
158 of bookmarks will come out in order of increasing numbers. */
159
160 b1 = bookmark_chain;
161 if (b1 == 0)
162 bookmark_chain = b;
163 else
164 {
165 while (b1->next)
166 b1 = b1->next;
167 b1->next = b;
168 }
169 printf_filtered (_("Saved bookmark %d at %s\n"), b->number,
170 paddress (gdbarch, b->sal.pc));
171}
172
173/* Implement "delete bookmark" command. */
174
175static int
7d357efd 176delete_one_bookmark (int num)
6b04bdb7 177{
7d357efd
MS
178 struct bookmark *b1, *b;
179
180 /* Find bookmark with corresponding number. */
181 ALL_BOOKMARKS (b)
182 if (b->number == num)
183 break;
6b04bdb7
MS
184
185 /* Special case, first item in list. */
186 if (b == bookmark_chain)
187 bookmark_chain = b->next;
188
189 /* Find bookmark preceeding "marked" one, so we can unlink. */
190 if (b)
191 {
192 ALL_BOOKMARKS (b1)
193 if (b1->next == b)
194 {
195 /* Found designated bookmark. Unlink and delete. */
196 b1->next = b->next;
197 break;
198 }
199 xfree (b->opaque_data);
200 xfree (b);
201 return 1; /* success */
202 }
203 return 0; /* failure */
204}
205
206static void
207delete_all_bookmarks (void)
208{
209 struct bookmark *b, *b1;
210
211 ALL_BOOKMARKS_SAFE (b, b1)
212 {
213 xfree (b->opaque_data);
214 xfree (b);
215 }
216 bookmark_chain = NULL;
217}
218
219static void
220delete_bookmark_command (char *args, int from_tty)
221{
6b4398f7 222 struct bookmark *b;
7d357efd 223 int num;
6b04bdb7
MS
224
225 if (bookmark_chain == NULL)
226 {
227 warning (_("No bookmarks."));
228 return;
229 }
230
231 if (args == NULL || args[0] == '\0')
232 {
233 if (from_tty && !query (_("Delete all bookmarks? ")))
234 return;
235 delete_all_bookmarks ();
236 return;
237 }
238
7d357efd
MS
239 while (args != NULL && *args != '\0')
240 {
241 num = get_number_or_range (&args);
242 if (!delete_one_bookmark (num))
243 /* Not found. */
244 warning (_("No bookmark #%d."), num);
245 }
6b04bdb7
MS
246}
247
248/* Implement "goto-bookmark" command. */
249
250static void
251goto_bookmark_command (char *args, int from_tty)
252{
253 struct bookmark *b;
254 unsigned long num;
255
256 if (args == NULL || args[0] == '\0')
257 error (_("Command requires an argument."));
258
259 if (strncmp (args, "start", strlen ("start")) == 0
260 || strncmp (args, "begin", strlen ("begin")) == 0
261 || strncmp (args, "end", strlen ("end")) == 0)
262 {
263 /* Special case. Give target opportunity to handle. */
264 target_goto_bookmark (args, from_tty);
265 return;
266 }
267
268 if (args[0] == '\'' || args[0] == '\"')
269 {
270 /* Special case -- quoted string. Pass on to target. */
271 if (args[strlen (args) - 1] != args[0])
272 error (_("Unbalanced quotes: %s"), args);
273 target_goto_bookmark (args, from_tty);
274 return;
275 }
276
277 /* General case. Bookmark identified by bookmark number. */
7d357efd 278 num = get_number (&args);
6b04bdb7
MS
279 ALL_BOOKMARKS (b)
280 if (b->number == num)
281 break;
282
283 if (b)
284 {
285 /* Found. Send to target method. */
286 target_goto_bookmark (b->opaque_data, from_tty);
287 return;
288 }
289 /* Not found. */
290 error (_("goto-bookmark: no bookmark found for '%s'."), args);
291}
292
7d357efd
MS
293static int
294bookmark_1 (int bnum)
295{
296 struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
297 struct bookmark *b;
298 int matched = 0;
299
300 ALL_BOOKMARKS (b)
301 {
302 if (bnum == -1 || bnum == b->number)
303 {
304 printf_filtered (" %d %s '%s'\n",
305 b->number,
306 paddress (gdbarch, b->pc),
307 b->opaque_data);
308 matched++;
309 }
310 }
311
312 if (bnum > 0 && matched == 0)
313 printf_filtered ("No bookmark #%d\n", bnum);
314
315 return matched;
316}
317
6b04bdb7
MS
318/* Implement "info bookmarks" command. */
319
320static void
321bookmarks_info (char *args, int from_tty)
322{
6b04bdb7 323 int bnum = -1;
6b04bdb7
MS
324
325 if (!bookmark_chain)
7d357efd
MS
326 printf_filtered (_("No bookmarks.\n"));
327 else if (args == NULL || *args == '\0')
328 bookmark_1 (-1);
329 else
330 while (args != NULL && *args != '\0')
331 {
332 bnum = get_number_or_range (&args);
333 bookmark_1 (bnum);
334 }
6b04bdb7
MS
335}
336
337
2c0b251b
PA
338/* Provide a prototype to silence -Wmissing-prototypes. */
339extern initialize_file_ftype _initialize_reverse;
340
b2175913
MS
341void
342_initialize_reverse (void)
343{
344 add_com ("reverse-step", class_run, reverse_step, _("\
345Step program backward until it reaches the beginning of another source line.\n\
346Argument N means do this N times (or till program stops for another reason).")
347 );
348 add_com_alias ("rs", "reverse-step", class_alias, 1);
349
350 add_com ("reverse-next", class_run, reverse_next, _("\
351Step program backward, proceeding through subroutine calls.\n\
352Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
353when they do, the call is treated as one instruction.\n\
354Argument N means do this N times (or till program stops for another reason).")
355 );
356 add_com_alias ("rn", "reverse-next", class_alias, 1);
357
358 add_com ("reverse-stepi", class_run, reverse_stepi, _("\
359Step backward exactly one instruction.\n\
360Argument N means do this N times (or till program stops for another reason).")
361 );
362 add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
363
364 add_com ("reverse-nexti", class_run, reverse_nexti, _("\
365Step backward one instruction, but proceed through called subroutines.\n\
366Argument N means do this N times (or till program stops for another reason).")
367 );
368 add_com_alias ("rni", "reverse-nexti", class_alias, 0);
369
370 add_com ("reverse-continue", class_run, reverse_continue, _("\
371Continue program being debugged but run it in reverse.\n\
372If proceeding from breakpoint, a number N may be used as an argument,\n\
373which means to set the ignore count of that breakpoint to N - 1 (so that\n\
374the breakpoint won't break until the Nth time it is reached)."));
375 add_com_alias ("rc", "reverse-continue", class_alias, 0);
376
377 add_com ("reverse-finish", class_run, reverse_finish, _("\
378Execute backward until just before selected stack frame is called."));
6b04bdb7
MS
379
380 add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
381Set a bookmark in the program's execution history.\n\
382A bookmark represents a point in the execution history \n\
383that can be returned to at a later point in the debug session."));
384 add_info ("bookmarks", bookmarks_info, _("\
385Status of user-settable bookmarks.\n\
386Bookmarks are user-settable markers representing a point in the \n\
387execution history that can be returned to later in the same debug \n\
388session."));
389 add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
390Delete a bookmark from the bookmark list.\n\
7d357efd
MS
391Argument is a bookmark number or numbers,\n\
392 or no argument to delete all bookmarks.\n"),
6b04bdb7
MS
393 &deletelist);
394 add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
395Go to an earlier-bookmarked point in the program's execution history.\n\
396Argument is the bookmark number of a bookmark saved earlier by using \n\
397the 'bookmark' command, or the special arguments:\n\
398 start (beginning of recording)\n\
399 end (end of recording)\n"));
b2175913 400}
This page took 0.305848 seconds and 4 git commands to generate.