]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/reverse.c
-Wwrite-strings: The Rest
[thirdparty/binutils-gdb.git] / gdb / reverse.c
CommitLineData
b2175913
MS
1/* Reverse execution and reverse debugging.
2
61baf725 3 Copyright (C) 2006-2017 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
a121b7c1 46exec_reverse_once (const char *cmd, char *args, int from_tty)
b2175913
MS
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{
6b04bdb7
MS
219 if (bookmark_chain == NULL)
220 {
221 warning (_("No bookmarks."));
222 return;
223 }
224
225 if (args == NULL || args[0] == '\0')
226 {
227 if (from_tty && !query (_("Delete all bookmarks? ")))
228 return;
229 delete_all_bookmarks ();
230 return;
231 }
232
bfd28288
PA
233 number_or_range_parser parser (args);
234 while (!parser.finished ())
7d357efd 235 {
bfd28288 236 int num = parser.get_number ();
7d357efd
MS
237 if (!delete_one_bookmark (num))
238 /* Not found. */
239 warning (_("No bookmark #%d."), num);
240 }
6b04bdb7
MS
241}
242
243/* Implement "goto-bookmark" command. */
244
245static void
246goto_bookmark_command (char *args, int from_tty)
247{
248 struct bookmark *b;
249 unsigned long num;
0c13193f 250 char *p = args;
6b04bdb7
MS
251
252 if (args == NULL || args[0] == '\0')
253 error (_("Command requires an argument."));
254
61012eef
GB
255 if (startswith (args, "start")
256 || startswith (args, "begin")
257 || startswith (args, "end"))
6b04bdb7
MS
258 {
259 /* Special case. Give target opportunity to handle. */
0f928d68 260 target_goto_bookmark ((gdb_byte *) args, from_tty);
6b04bdb7
MS
261 return;
262 }
263
264 if (args[0] == '\'' || args[0] == '\"')
265 {
266 /* Special case -- quoted string. Pass on to target. */
267 if (args[strlen (args) - 1] != args[0])
268 error (_("Unbalanced quotes: %s"), args);
0f928d68 269 target_goto_bookmark ((gdb_byte *) args, from_tty);
6b04bdb7
MS
270 return;
271 }
272
273 /* General case. Bookmark identified by bookmark number. */
7d357efd 274 num = get_number (&args);
0c13193f
YQ
275
276 if (num == 0)
277 error (_("goto-bookmark: invalid bookmark number '%s'."), p);
278
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. */
0c13193f 290 error (_("goto-bookmark: no bookmark found for '%s'."), p);
6b04bdb7
MS
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 if (!bookmark_chain)
7d357efd
MS
324 printf_filtered (_("No bookmarks.\n"));
325 else if (args == NULL || *args == '\0')
326 bookmark_1 (-1);
327 else
197f0a60 328 {
bfd28288
PA
329 number_or_range_parser parser (args);
330 while (!parser.finished ())
197f0a60 331 {
bfd28288 332 int bnum = parser.get_number ();
197f0a60
TT
333 bookmark_1 (bnum);
334 }
335 }
6b04bdb7
MS
336}
337
338
2c0b251b
PA
339/* Provide a prototype to silence -Wmissing-prototypes. */
340extern initialize_file_ftype _initialize_reverse;
341
b2175913
MS
342void
343_initialize_reverse (void)
344{
345 add_com ("reverse-step", class_run, reverse_step, _("\
346Step program backward until it reaches the beginning of another source line.\n\
347Argument N means do this N times (or till program stops for another reason).")
348 );
349 add_com_alias ("rs", "reverse-step", class_alias, 1);
350
351 add_com ("reverse-next", class_run, reverse_next, _("\
352Step program backward, proceeding through subroutine calls.\n\
353Like the \"reverse-step\" command as long as subroutine calls do not happen;\n\
354when they do, the call is treated as one instruction.\n\
355Argument N means do this N times (or till program stops for another reason).")
356 );
357 add_com_alias ("rn", "reverse-next", class_alias, 1);
358
359 add_com ("reverse-stepi", class_run, reverse_stepi, _("\
360Step backward exactly one instruction.\n\
361Argument N means do this N times (or till program stops for another reason).")
362 );
363 add_com_alias ("rsi", "reverse-stepi", class_alias, 0);
364
365 add_com ("reverse-nexti", class_run, reverse_nexti, _("\
366Step backward one instruction, but proceed through called subroutines.\n\
367Argument N means do this N times (or till program stops for another reason).")
368 );
369 add_com_alias ("rni", "reverse-nexti", class_alias, 0);
370
371 add_com ("reverse-continue", class_run, reverse_continue, _("\
372Continue program being debugged but run it in reverse.\n\
373If proceeding from breakpoint, a number N may be used as an argument,\n\
374which means to set the ignore count of that breakpoint to N - 1 (so that\n\
375the breakpoint won't break until the Nth time it is reached)."));
376 add_com_alias ("rc", "reverse-continue", class_alias, 0);
377
378 add_com ("reverse-finish", class_run, reverse_finish, _("\
379Execute backward until just before selected stack frame is called."));
6b04bdb7
MS
380
381 add_com ("bookmark", class_bookmark, save_bookmark_command, _("\
382Set a bookmark in the program's execution history.\n\
383A bookmark represents a point in the execution history \n\
384that can be returned to at a later point in the debug session."));
385 add_info ("bookmarks", bookmarks_info, _("\
386Status of user-settable bookmarks.\n\
387Bookmarks are user-settable markers representing a point in the \n\
388execution history that can be returned to later in the same debug \n\
389session."));
390 add_cmd ("bookmark", class_bookmark, delete_bookmark_command, _("\
391Delete a bookmark from the bookmark list.\n\
7d357efd
MS
392Argument is a bookmark number or numbers,\n\
393 or no argument to delete all bookmarks.\n"),
6b04bdb7
MS
394 &deletelist);
395 add_com ("goto-bookmark", class_bookmark, goto_bookmark_command, _("\
396Go to an earlier-bookmarked point in the program's execution history.\n\
397Argument is the bookmark number of a bookmark saved earlier by using \n\
398the 'bookmark' command, or the special arguments:\n\
399 start (beginning of recording)\n\
400 end (end of recording)\n"));
b2175913 401}