findcmd.c revision 1.7 1 1.1 christos /* The find command.
2 1.1 christos
3 1.7 christos Copyright (C) 2008-2017 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include "defs.h"
21 1.1 christos #include "arch-utils.h"
22 1.1 christos #include <ctype.h>
23 1.1 christos #include "gdbcmd.h"
24 1.1 christos #include "value.h"
25 1.1 christos #include "target.h"
26 1.1 christos #include "cli/cli-utils.h"
27 1.7 christos #include <algorithm>
28 1.1 christos
29 1.1 christos /* Copied from bfd_put_bits. */
30 1.1 christos
31 1.1 christos static void
32 1.1 christos put_bits (bfd_uint64_t data, gdb_byte *buf, int bits, bfd_boolean big_p)
33 1.1 christos {
34 1.1 christos int i;
35 1.1 christos int bytes;
36 1.1 christos
37 1.1 christos gdb_assert (bits % 8 == 0);
38 1.1 christos
39 1.1 christos bytes = bits / 8;
40 1.1 christos for (i = 0; i < bytes; i++)
41 1.1 christos {
42 1.1 christos int index = big_p ? bytes - i - 1 : i;
43 1.1 christos
44 1.1 christos buf[index] = data & 0xff;
45 1.1 christos data >>= 8;
46 1.1 christos }
47 1.1 christos }
48 1.1 christos
49 1.1 christos /* Subroutine of find_command to simplify it.
50 1.1 christos Parse the arguments of the "find" command. */
51 1.1 christos
52 1.1 christos static void
53 1.1 christos parse_find_args (char *args, ULONGEST *max_countp,
54 1.1 christos gdb_byte **pattern_bufp, ULONGEST *pattern_lenp,
55 1.1 christos CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
56 1.1 christos bfd_boolean big_p)
57 1.1 christos {
58 1.1 christos /* Default to using the specified type. */
59 1.1 christos char size = '\0';
60 1.1 christos ULONGEST max_count = ~(ULONGEST) 0;
61 1.1 christos /* Buffer to hold the search pattern. */
62 1.1 christos gdb_byte *pattern_buf;
63 1.1 christos /* Current size of search pattern buffer.
64 1.1 christos We realloc space as needed. */
65 1.1 christos #define INITIAL_PATTERN_BUF_SIZE 100
66 1.1 christos ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
67 1.1 christos /* Pointer to one past the last in-use part of pattern_buf. */
68 1.1 christos gdb_byte *pattern_buf_end;
69 1.1 christos ULONGEST pattern_len;
70 1.1 christos CORE_ADDR start_addr;
71 1.1 christos ULONGEST search_space_len;
72 1.1 christos const char *s = args;
73 1.1 christos struct cleanup *old_cleanups;
74 1.1 christos struct value *v;
75 1.1 christos
76 1.1 christos if (args == NULL)
77 1.1 christos error (_("Missing search parameters."));
78 1.1 christos
79 1.6 christos pattern_buf = (gdb_byte *) xmalloc (pattern_buf_size);
80 1.1 christos pattern_buf_end = pattern_buf;
81 1.1 christos old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
82 1.1 christos
83 1.1 christos /* Get search granularity and/or max count if specified.
84 1.1 christos They may be specified in either order, together or separately. */
85 1.1 christos
86 1.1 christos while (*s == '/')
87 1.1 christos {
88 1.1 christos ++s;
89 1.1 christos
90 1.1 christos while (*s != '\0' && *s != '/' && !isspace (*s))
91 1.1 christos {
92 1.1 christos if (isdigit (*s))
93 1.1 christos {
94 1.1 christos max_count = atoi (s);
95 1.1 christos while (isdigit (*s))
96 1.1 christos ++s;
97 1.1 christos continue;
98 1.1 christos }
99 1.1 christos
100 1.1 christos switch (*s)
101 1.1 christos {
102 1.1 christos case 'b':
103 1.1 christos case 'h':
104 1.1 christos case 'w':
105 1.1 christos case 'g':
106 1.1 christos size = *s++;
107 1.1 christos break;
108 1.1 christos default:
109 1.1 christos error (_("Invalid size granularity."));
110 1.1 christos }
111 1.1 christos }
112 1.1 christos
113 1.1 christos s = skip_spaces_const (s);
114 1.1 christos }
115 1.1 christos
116 1.1 christos /* Get the search range. */
117 1.1 christos
118 1.1 christos v = parse_to_comma_and_eval (&s);
119 1.1 christos start_addr = value_as_address (v);
120 1.1 christos
121 1.1 christos if (*s == ',')
122 1.1 christos ++s;
123 1.1 christos s = skip_spaces_const (s);
124 1.1 christos
125 1.1 christos if (*s == '+')
126 1.1 christos {
127 1.1 christos LONGEST len;
128 1.1 christos
129 1.1 christos ++s;
130 1.1 christos v = parse_to_comma_and_eval (&s);
131 1.1 christos len = value_as_long (v);
132 1.1 christos if (len == 0)
133 1.1 christos {
134 1.1 christos do_cleanups (old_cleanups);
135 1.1 christos printf_filtered (_("Empty search range.\n"));
136 1.1 christos return;
137 1.1 christos }
138 1.1 christos if (len < 0)
139 1.1 christos error (_("Invalid length."));
140 1.1 christos /* Watch for overflows. */
141 1.1 christos if (len > CORE_ADDR_MAX
142 1.1 christos || (start_addr + len - 1) < start_addr)
143 1.1 christos error (_("Search space too large."));
144 1.1 christos search_space_len = len;
145 1.1 christos }
146 1.1 christos else
147 1.1 christos {
148 1.1 christos CORE_ADDR end_addr;
149 1.1 christos
150 1.1 christos v = parse_to_comma_and_eval (&s);
151 1.1 christos end_addr = value_as_address (v);
152 1.1 christos if (start_addr > end_addr)
153 1.1 christos error (_("Invalid search space, end precedes start."));
154 1.1 christos search_space_len = end_addr - start_addr + 1;
155 1.1 christos /* We don't support searching all of memory
156 1.1 christos (i.e. start=0, end = 0xff..ff).
157 1.1 christos Bail to avoid overflows later on. */
158 1.1 christos if (search_space_len == 0)
159 1.1 christos error (_("Overflow in address range "
160 1.1 christos "computation, choose smaller range."));
161 1.1 christos }
162 1.1 christos
163 1.1 christos if (*s == ',')
164 1.1 christos ++s;
165 1.1 christos
166 1.1 christos /* Fetch the search string. */
167 1.1 christos
168 1.1 christos while (*s != '\0')
169 1.1 christos {
170 1.1 christos LONGEST x;
171 1.1 christos struct type *t;
172 1.1 christos ULONGEST pattern_buf_size_need;
173 1.1 christos
174 1.1 christos s = skip_spaces_const (s);
175 1.1 christos
176 1.1 christos v = parse_to_comma_and_eval (&s);
177 1.1 christos t = value_type (v);
178 1.1 christos
179 1.1 christos /* Keep it simple and assume size == 'g' when watching for when we
180 1.1 christos need to grow the pattern buf. */
181 1.1 christos pattern_buf_size_need = (pattern_buf_end - pattern_buf
182 1.7 christos + std::max (TYPE_LENGTH (t),
183 1.7 christos (unsigned) sizeof (int64_t)));
184 1.1 christos if (pattern_buf_size_need > pattern_buf_size)
185 1.1 christos {
186 1.1 christos size_t current_offset = pattern_buf_end - pattern_buf;
187 1.1 christos
188 1.1 christos pattern_buf_size = pattern_buf_size_need * 2;
189 1.6 christos pattern_buf = (gdb_byte *) xrealloc (pattern_buf, pattern_buf_size);
190 1.1 christos pattern_buf_end = pattern_buf + current_offset;
191 1.1 christos }
192 1.1 christos
193 1.1 christos if (size != '\0')
194 1.1 christos {
195 1.1 christos x = value_as_long (v);
196 1.1 christos switch (size)
197 1.1 christos {
198 1.1 christos case 'b':
199 1.1 christos *pattern_buf_end++ = x;
200 1.1 christos break;
201 1.1 christos case 'h':
202 1.1 christos put_bits (x, pattern_buf_end, 16, big_p);
203 1.1 christos pattern_buf_end += sizeof (int16_t);
204 1.1 christos break;
205 1.1 christos case 'w':
206 1.1 christos put_bits (x, pattern_buf_end, 32, big_p);
207 1.1 christos pattern_buf_end += sizeof (int32_t);
208 1.1 christos break;
209 1.1 christos case 'g':
210 1.1 christos put_bits (x, pattern_buf_end, 64, big_p);
211 1.1 christos pattern_buf_end += sizeof (int64_t);
212 1.1 christos break;
213 1.1 christos }
214 1.1 christos }
215 1.1 christos else
216 1.1 christos {
217 1.1 christos memcpy (pattern_buf_end, value_contents (v), TYPE_LENGTH (t));
218 1.1 christos pattern_buf_end += TYPE_LENGTH (t);
219 1.1 christos }
220 1.1 christos
221 1.1 christos if (*s == ',')
222 1.1 christos ++s;
223 1.1 christos s = skip_spaces_const (s);
224 1.1 christos }
225 1.1 christos
226 1.1 christos if (pattern_buf_end == pattern_buf)
227 1.1 christos error (_("Missing search pattern."));
228 1.1 christos
229 1.1 christos pattern_len = pattern_buf_end - pattern_buf;
230 1.1 christos
231 1.1 christos if (search_space_len < pattern_len)
232 1.1 christos error (_("Search space too small to contain pattern."));
233 1.1 christos
234 1.1 christos *max_countp = max_count;
235 1.1 christos *pattern_bufp = pattern_buf;
236 1.1 christos *pattern_lenp = pattern_len;
237 1.1 christos *start_addrp = start_addr;
238 1.1 christos *search_space_lenp = search_space_len;
239 1.1 christos
240 1.1 christos /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF
241 1.1 christos to the caller now. */
242 1.1 christos discard_cleanups (old_cleanups);
243 1.1 christos }
244 1.1 christos
245 1.1 christos static void
246 1.1 christos find_command (char *args, int from_tty)
247 1.1 christos {
248 1.1 christos struct gdbarch *gdbarch = get_current_arch ();
249 1.1 christos bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
250 1.1 christos /* Command line parameters.
251 1.1 christos These are initialized to avoid uninitialized warnings from -Wall. */
252 1.1 christos ULONGEST max_count = 0;
253 1.1 christos gdb_byte *pattern_buf = 0;
254 1.1 christos ULONGEST pattern_len = 0;
255 1.1 christos CORE_ADDR start_addr = 0;
256 1.1 christos ULONGEST search_space_len = 0;
257 1.1 christos /* End of command line parameters. */
258 1.1 christos unsigned int found_count;
259 1.1 christos CORE_ADDR last_found_addr;
260 1.1 christos struct cleanup *old_cleanups;
261 1.1 christos
262 1.1 christos parse_find_args (args, &max_count, &pattern_buf, &pattern_len,
263 1.1 christos &start_addr, &search_space_len, big_p);
264 1.1 christos
265 1.1 christos old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
266 1.1 christos
267 1.1 christos /* Perform the search. */
268 1.1 christos
269 1.1 christos found_count = 0;
270 1.1 christos last_found_addr = 0;
271 1.1 christos
272 1.1 christos while (search_space_len >= pattern_len
273 1.1 christos && found_count < max_count)
274 1.1 christos {
275 1.1 christos /* Offset from start of this iteration to the next iteration. */
276 1.1 christos ULONGEST next_iter_incr;
277 1.1 christos CORE_ADDR found_addr;
278 1.1 christos int found = target_search_memory (start_addr, search_space_len,
279 1.1 christos pattern_buf, pattern_len, &found_addr);
280 1.1 christos
281 1.1 christos if (found <= 0)
282 1.1 christos break;
283 1.1 christos
284 1.1 christos print_address (gdbarch, found_addr, gdb_stdout);
285 1.1 christos printf_filtered ("\n");
286 1.1 christos ++found_count;
287 1.1 christos last_found_addr = found_addr;
288 1.1 christos
289 1.1 christos /* Begin next iteration at one byte past this match. */
290 1.1 christos next_iter_incr = (found_addr - start_addr) + 1;
291 1.1 christos
292 1.1 christos /* For robustness, we don't let search_space_len go -ve here. */
293 1.1 christos if (search_space_len >= next_iter_incr)
294 1.1 christos search_space_len -= next_iter_incr;
295 1.1 christos else
296 1.1 christos search_space_len = 0;
297 1.1 christos start_addr += next_iter_incr;
298 1.1 christos }
299 1.1 christos
300 1.1 christos /* Record and print the results. */
301 1.1 christos
302 1.1 christos set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
303 1.1 christos if (found_count > 0)
304 1.1 christos {
305 1.1 christos struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
306 1.1 christos
307 1.1 christos set_internalvar (lookup_internalvar ("_"),
308 1.1 christos value_from_pointer (ptr_type, last_found_addr));
309 1.1 christos }
310 1.1 christos
311 1.1 christos if (found_count == 0)
312 1.1 christos printf_filtered ("Pattern not found.\n");
313 1.1 christos else
314 1.1 christos printf_filtered ("%d pattern%s found.\n", found_count,
315 1.1 christos found_count > 1 ? "s" : "");
316 1.1 christos
317 1.1 christos do_cleanups (old_cleanups);
318 1.1 christos }
319 1.1 christos
320 1.1 christos /* Provide a prototype to silence -Wmissing-prototypes. */
321 1.1 christos extern initialize_file_ftype _initialize_mem_search;
322 1.1 christos
323 1.1 christos void
324 1.1 christos _initialize_mem_search (void)
325 1.1 christos {
326 1.1 christos add_cmd ("find", class_vars, find_command, _("\
327 1.1 christos Search memory for a sequence of bytes.\n\
328 1.1 christos Usage:\nfind \
329 1.1 christos [/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
330 1.1 christos find [/size-char] [/max-count] start-address, +length, expr1 [, expr2 ...]\n\
331 1.1 christos size-char is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
332 1.1 christos and if not specified the size is taken from the type of the expression\n\
333 1.1 christos in the current language.\n\
334 1.1 christos Note that this means for example that in the case of C-like languages\n\
335 1.1 christos a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
336 1.1 christos which is typically four bytes.\n\
337 1.1 christos \n\
338 1.1 christos The address of the last match is stored as the value of \"$_\".\n\
339 1.1 christos Convenience variable \"$numfound\" is set to the number of matches."),
340 1.1 christos &cmdlist);
341 1.1 christos }
342