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