GDB (xrefs)
Loading...
Searching...
No Matches
findcmd.c
Go to the documentation of this file.
1/* The find command.
2
3 Copyright (C) 2008-2023 Free Software Foundation, Inc.
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"
21#include "arch-utils.h"
22#include <ctype.h>
23#include "gdbcmd.h"
24#include "value.h"
25#include "target.h"
26#include "cli/cli-utils.h"
27#include <algorithm>
28#include "gdbsupport/byte-vector.h"
29
30/* Copied from bfd_put_bits. */
31
32static void
33put_bits (uint64_t data, gdb::byte_vector &buf, int bits, bfd_boolean big_p)
34{
35 int i;
36 int bytes;
37
38 gdb_assert (bits % 8 == 0);
39
40 bytes = bits / 8;
41 size_t last = buf.size ();
42 buf.resize (last + bytes);
43 for (i = 0; i < bytes; i++)
44 {
45 int index = big_p ? bytes - i - 1 : i;
46
47 buf[last + index] = data & 0xff;
48 data >>= 8;
49 }
50}
51
52/* Subroutine of find_command to simplify it.
53 Parse the arguments of the "find" command. */
54
55static gdb::byte_vector
56parse_find_args (const char *args, ULONGEST *max_countp,
57 CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
58 bfd_boolean big_p)
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. */
64 gdb::byte_vector pattern_buf;
65 CORE_ADDR start_addr;
66 ULONGEST search_space_len;
67 const char *s = args;
68 struct value *v;
69
70 if (args == NULL)
71 error (_("Missing search parameters."));
72
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:
99 error (_("Invalid size granularity."));
100 }
101 }
102
103 s = skip_spaces (s);
104 }
105
106 /* Get the search range. */
107
109 start_addr = value_as_address (v);
110
111 if (*s == ',')
112 ++s;
113 s = skip_spaces (s);
114
115 if (*s == '+')
116 {
117 LONGEST len;
118
119 ++s;
121 len = value_as_long (v);
122 if (len == 0)
123 {
124 gdb_printf (_("Empty search range.\n"));
125 return pattern_buf;
126 }
127 if (len < 0)
128 error (_("Invalid length."));
129 /* Watch for overflows. */
130 if (len > CORE_ADDR_MAX
131 || (start_addr + len - 1) < start_addr)
132 error (_("Search space too large."));
133 search_space_len = len;
134 }
135 else
136 {
137 CORE_ADDR end_addr;
138
140 end_addr = value_as_address (v);
141 if (start_addr > end_addr)
142 error (_("Invalid search space, end precedes start."));
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)
148 error (_("Overflow in address range "
149 "computation, choose smaller range."));
150 }
151
152 if (*s == ',')
153 ++s;
154
155 /* Fetch the search string. */
156
157 while (*s != '\0')
158 {
159 LONGEST x;
160 struct type *t;
161
162 s = skip_spaces (s);
163
165 t = v->type ();
166
167 if (size != '\0')
168 {
169 x = value_as_long (v);
170 switch (size)
171 {
172 case 'b':
173 pattern_buf.push_back (x);
174 break;
175 case 'h':
176 put_bits (x, pattern_buf, 16, big_p);
177 break;
178 case 'w':
179 put_bits (x, pattern_buf, 32, big_p);
180 break;
181 case 'g':
182 put_bits (x, pattern_buf, 64, big_p);
183 break;
184 }
185 }
186 else
187 {
188 const gdb_byte *contents = v->contents ().data ();
189 pattern_buf.insert (pattern_buf.end (), contents,
190 contents + t->length ());
191 }
192
193 if (*s == ',')
194 ++s;
195 s = skip_spaces (s);
196 }
197
198 if (pattern_buf.empty ())
199 error (_("Missing search pattern."));
200
201 if (search_space_len < pattern_buf.size ())
202 error (_("Search space too small to contain pattern."));
203
204 *max_countp = max_count;
205 *start_addrp = start_addr;
206 *search_space_lenp = search_space_len;
207
208 return pattern_buf;
209}
210
211static void
212find_command (const char *args, int from_tty)
213{
214 struct gdbarch *gdbarch = get_current_arch ();
215 bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
216 /* Command line parameters.
217 These are initialized to avoid uninitialized warnings from -Wall. */
218 ULONGEST max_count = 0;
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;
224
225 gdb::byte_vector pattern_buf = parse_find_args (args, &max_count,
226 &start_addr,
227 &search_space_len,
228 big_p);
229
230 /* Perform the search. */
231
232 found_count = 0;
233 last_found_addr = 0;
234
235 while (search_space_len >= pattern_buf.size ()
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,
242 pattern_buf.data (),
243 pattern_buf.size (),
244 &found_addr);
245
246 if (found <= 0)
247 break;
248
249 print_address (gdbarch, found_addr, gdb_stdout);
250 gdb_printf ("\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
267 set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
268 if (found_count > 0)
269 {
270 struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
271
273 value_from_pointer (ptr_type, last_found_addr));
274 }
275
276 if (found_count == 0)
277 gdb_printf ("Pattern not found.\n");
278 else
279 gdb_printf ("%d pattern%s found.\n", found_count,
280 found_count > 1 ? "s" : "");
281}
282
284void
286{
287 add_cmd ("find", class_vars, find_command, _("\
288Search memory for a sequence of bytes.\n\
289Usage:\nfind \
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\
293and if not specified the size is taken from the type of the expression\n\
294in the current language.\n\
295The two-address form specifies an inclusive range.\n\
296Note that this means for example that in the case of C-like languages\n\
297a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
298which is typically four bytes, and a search for a string \"hello\" will\n\
299include the trailing '\\0'. The null terminator can be removed from\n\
300searching by using casts, e.g.: {char[5]}\"hello\".\n\
301\n\
302The address of the last match is stored as the value of \"$_\".\n\
303Convenience variable \"$numfound\" is set to the number of matches."),
304 &cmdlist);
305}
#define bits(obj, st, fn)
struct gdbarch * get_current_arch(void)
Definition arch-utils.c:846
struct cmd_list_element * cmdlist
Definition cli-cmds.c:87
struct cmd_list_element * add_cmd(const char *name, enum command_class theclass, const char *doc, struct cmd_list_element **list)
Definition cli-decode.c:233
@ class_vars
Definition command.h:55
void print_address(struct gdbarch *, CORE_ADDR, struct ui_file *)
Definition printcmd.c:739
struct value * parse_to_comma_and_eval(const char **expp)
Definition eval.c:82
static gdb::byte_vector parse_find_args(const char *args, ULONGEST *max_countp, CORE_ADDR *start_addrp, ULONGEST *search_space_lenp, bfd_boolean big_p)
Definition findcmd.c:56
static void put_bits(uint64_t data, gdb::byte_vector &buf, int bits, bfd_boolean big_p)
Definition findcmd.c:33
void _initialize_mem_search()
Definition findcmd.c:285
static void find_command(const char *args, int from_tty)
Definition findcmd.c:212
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition gdbarch.c:1396
const struct builtin_type * builtin_type(struct gdbarch *gdbarch)
Definition gdbtypes.c:6168
size_t size
Definition go32-nat.c:239
struct type * builtin_data_ptr
Definition gdbtypes.h:2135
ULONGEST length() const
Definition gdbtypes.h:983
Definition value.h:130
gdb::array_view< const gdb_byte > contents()
Definition value.c:1262
struct type * type() const
Definition value.h:180
int target_search_memory(CORE_ADDR start_addr, ULONGEST search_space_len, const gdb_byte *pattern, ULONGEST pattern_len, CORE_ADDR *found_addrp)
Definition target.c:2807
void gdb_printf(struct ui_file *stream, const char *format,...)
Definition utils.c:1886
#define gdb_stdout
Definition utils.h:182
CORE_ADDR value_as_address(struct value *val)
Definition value.c:2636
void set_internalvar(struct internalvar *var, struct value *val)
Definition value.c:2171
struct internalvar * lookup_internalvar(const char *name)
Definition value.c:2001
LONGEST value_as_long(struct value *val)
Definition value.c:2554
void set_internalvar_integer(struct internalvar *var, LONGEST l)
Definition value.c:2232
struct value * value_from_pointer(struct type *type, CORE_ADDR addr)
Definition value.c:3500