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