gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / findcmd.c
CommitLineData
08388c79
DE
1/* The find command.
2
b811d2c2 3 Copyright (C) 2008-2020 Free Software Foundation, Inc.
08388c79
DE
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
9 the Free Software Foundation; either version 3 of the License, or
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
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
d55e5aa6 21#include "arch-utils.h"
4de283e4 22#include <ctype.h>
d55e5aa6 23#include "gdbcmd.h"
d55e5aa6 24#include "value.h"
4de283e4
TT
25#include "target.h"
26#include "cli/cli-utils.h"
27#include <algorithm>
268a13a5 28#include "gdbsupport/byte-vector.h"
08388c79
DE
29
30/* Copied from bfd_put_bits. */
31
32static void
d6b9b80f 33put_bits (bfd_uint64_t data, gdb::byte_vector &buf, int bits, bfd_boolean big_p)
08388c79
DE
34{
35 int i;
36 int bytes;
37
38 gdb_assert (bits % 8 == 0);
39
40 bytes = bits / 8;
d6b9b80f
TT
41 size_t last = buf.size ();
42 buf.resize (last + bytes);
08388c79
DE
43 for (i = 0; i < bytes; i++)
44 {
45 int index = big_p ? bytes - i - 1 : i;
46
d6b9b80f 47 buf[last + index] = data & 0xff;
08388c79
DE
48 data >>= 8;
49 }
50}
51
52/* Subroutine of find_command to simplify it.
53 Parse the arguments of the "find" command. */
54
d6b9b80f
TT
55static gdb::byte_vector
56parse_find_args (const char *args, ULONGEST *max_countp,
e17c207e
UW
57 CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
58 bfd_boolean big_p)
08388c79
DE
59{
60 /* Default to using the specified type. */
61 char size = '\0';
62 ULONGEST max_count = ~(ULONGEST) 0;
63 /* Buffer to hold the search pattern. */
d6b9b80f 64 gdb::byte_vector pattern_buf;
08388c79
DE
65 CORE_ADDR start_addr;
66 ULONGEST search_space_len;
bbc13ae3 67 const char *s = args;
08388c79
DE
68 struct value *v;
69
70 if (args == NULL)
5e1471f5 71 error (_("Missing search parameters."));
08388c79 72
08388c79
DE
73 /* Get search granularity and/or max count if specified.
74 They may be specified in either order, together or separately. */
75
76 while (*s == '/')
77 {
78 ++s;
79
80 while (*s != '\0' && *s != '/' && !isspace (*s))
81 {
82 if (isdigit (*s))
83 {
84 max_count = atoi (s);
85 while (isdigit (*s))
86 ++s;
87 continue;
88 }
89
90 switch (*s)
91 {
92 case 'b':
93 case 'h':
94 case 'w':
95 case 'g':
96 size = *s++;
97 break;
98 default:
5e1471f5 99 error (_("Invalid size granularity."));
08388c79
DE
100 }
101 }
102
f1735a53 103 s = skip_spaces (s);
08388c79
DE
104 }
105
106 /* Get the search range. */
107
108 v = parse_to_comma_and_eval (&s);
109 start_addr = value_as_address (v);
110
111 if (*s == ',')
112 ++s;
f1735a53 113 s = skip_spaces (s);
08388c79
DE
114
115 if (*s == '+')
116 {
117 LONGEST len;
bb9bcb69 118
08388c79
DE
119 ++s;
120 v = parse_to_comma_and_eval (&s);
121 len = value_as_long (v);
122 if (len == 0)
123 {
5e1471f5 124 printf_filtered (_("Empty search range.\n"));
d6b9b80f 125 return pattern_buf;
08388c79
DE
126 }
127 if (len < 0)
5e1471f5 128 error (_("Invalid length."));
08388c79
DE
129 /* Watch for overflows. */
130 if (len > CORE_ADDR_MAX
131 || (start_addr + len - 1) < start_addr)
5e1471f5 132 error (_("Search space too large."));
08388c79
DE
133 search_space_len = len;
134 }
135 else
136 {
137 CORE_ADDR end_addr;
bb9bcb69 138
08388c79
DE
139 v = parse_to_comma_and_eval (&s);
140 end_addr = value_as_address (v);
141 if (start_addr > end_addr)
177b42fe 142 error (_("Invalid search space, end precedes start."));
08388c79
DE
143 search_space_len = end_addr - start_addr + 1;
144 /* We don't support searching all of memory
145 (i.e. start=0, end = 0xff..ff).
146 Bail to avoid overflows later on. */
147 if (search_space_len == 0)
3e43a32a
MS
148 error (_("Overflow in address range "
149 "computation, choose smaller range."));
08388c79
DE
150 }
151
152 if (*s == ',')
153 ++s;
154
155 /* Fetch the search string. */
156
157 while (*s != '\0')
158 {
159 LONGEST x;
744a8059 160 struct type *t;
08388c79 161
f1735a53 162 s = skip_spaces (s);
08388c79
DE
163
164 v = parse_to_comma_and_eval (&s);
744a8059 165 t = value_type (v);
08388c79 166
08388c79
DE
167 if (size != '\0')
168 {
169 x = value_as_long (v);
170 switch (size)
171 {
172 case 'b':
d6b9b80f 173 pattern_buf.push_back (x);
08388c79
DE
174 break;
175 case 'h':
d6b9b80f 176 put_bits (x, pattern_buf, 16, big_p);
08388c79
DE
177 break;
178 case 'w':
d6b9b80f 179 put_bits (x, pattern_buf, 32, big_p);
08388c79
DE
180 break;
181 case 'g':
d6b9b80f 182 put_bits (x, pattern_buf, 64, big_p);
08388c79
DE
183 break;
184 }
185 }
186 else
187 {
d6b9b80f
TT
188 const gdb_byte *contents = value_contents (v);
189 pattern_buf.insert (pattern_buf.end (), contents,
190 contents + TYPE_LENGTH (t));
08388c79
DE
191 }
192
193 if (*s == ',')
194 ++s;
f1735a53 195 s = skip_spaces (s);
08388c79
DE
196 }
197
d6b9b80f 198 if (pattern_buf.empty ())
5e1471f5 199 error (_("Missing search pattern."));
08388c79 200
d6b9b80f 201 if (search_space_len < pattern_buf.size ())
5e1471f5 202 error (_("Search space too small to contain pattern."));
08388c79
DE
203
204 *max_countp = max_count;
08388c79
DE
205 *start_addrp = start_addr;
206 *search_space_lenp = search_space_len;
207
d6b9b80f 208 return pattern_buf;
08388c79
DE
209}
210
211static void
f21b4d5c 212find_command (const char *args, int from_tty)
08388c79 213{
e17c207e
UW
214 struct gdbarch *gdbarch = get_current_arch ();
215 bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
08388c79
DE
216 /* Command line parameters.
217 These are initialized to avoid uninitialized warnings from -Wall. */
218 ULONGEST max_count = 0;
08388c79
DE
219 CORE_ADDR start_addr = 0;
220 ULONGEST search_space_len = 0;
221 /* End of command line parameters. */
222 unsigned int found_count;
223 CORE_ADDR last_found_addr;
08388c79 224
d6b9b80f
TT
225 gdb::byte_vector pattern_buf = parse_find_args (args, &max_count,
226 &start_addr,
227 &search_space_len,
228 big_p);
08388c79
DE
229
230 /* Perform the search. */
231
232 found_count = 0;
233 last_found_addr = 0;
234
d6b9b80f 235 while (search_space_len >= pattern_buf.size ()
08388c79
DE
236 && found_count < max_count)
237 {
238 /* Offset from start of this iteration to the next iteration. */
239 ULONGEST next_iter_incr;
240 CORE_ADDR found_addr;
241 int found = target_search_memory (start_addr, search_space_len,
d6b9b80f
TT
242 pattern_buf.data (),
243 pattern_buf.size (),
244 &found_addr);
08388c79
DE
245
246 if (found <= 0)
247 break;
248
5af949e3 249 print_address (gdbarch, found_addr, gdb_stdout);
08388c79
DE
250 printf_filtered ("\n");
251 ++found_count;
252 last_found_addr = found_addr;
253
254 /* Begin next iteration at one byte past this match. */
255 next_iter_incr = (found_addr - start_addr) + 1;
256
257 /* For robustness, we don't let search_space_len go -ve here. */
258 if (search_space_len >= next_iter_incr)
259 search_space_len -= next_iter_incr;
260 else
261 search_space_len = 0;
262 start_addr += next_iter_incr;
263 }
264
265 /* Record and print the results. */
266
4fa62494 267 set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
08388c79
DE
268 if (found_count > 0)
269 {
8b9b9e1a 270 struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
bb9bcb69 271
08388c79 272 set_internalvar (lookup_internalvar ("_"),
8b9b9e1a 273 value_from_pointer (ptr_type, last_found_addr));
08388c79
DE
274 }
275
276 if (found_count == 0)
5e1471f5 277 printf_filtered ("Pattern not found.\n");
08388c79 278 else
5e1471f5 279 printf_filtered ("%d pattern%s found.\n", found_count,
08388c79 280 found_count > 1 ? "s" : "");
08388c79
DE
281}
282
6c265988 283void _initialize_mem_search ();
08388c79 284void
6c265988 285_initialize_mem_search ()
08388c79
DE
286{
287 add_cmd ("find", class_vars, find_command, _("\
288Search memory for a sequence of bytes.\n\
3e43a32a 289Usage:\nfind \
c763b894
TT
290[/SIZE-CHAR] [/MAX-COUNT] START-ADDRESS, END-ADDRESS, EXPR1 [, EXPR2 ...]\n\
291find [/SIZE-CHAR] [/MAX-COUNT] START-ADDRESS, +LENGTH, EXPR1 [, EXPR2 ...]\n\
292SIZE-CHAR is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
08388c79
DE
293and if not specified the size is taken from the type of the expression\n\
294in the current language.\n\
295Note that this means for example that in the case of C-like languages\n\
296a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
ee9a09e9
DC
297which is typically four bytes, and a search for a string \"hello\" will\n\
298include the trailing '\\0'. The null terminator can be removed from\n\
299searching by using casts, e.g.: {char[5]}\"hello\".\n\
08388c79
DE
300\n\
301The address of the last match is stored as the value of \"$_\".\n\
302Convenience variable \"$numfound\" is set to the number of matches."),
303 &cmdlist);
304}
This page took 0.933508 seconds and 4 git commands to generate.