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