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