Home | History | Annotate | Line # | Download | only in gdb
findcmd.c revision 1.1
      1  1.1  christos /* The find command.
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 2008-2014 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 <string.h>
     24  1.1  christos #include "gdbcmd.h"
     25  1.1  christos #include "value.h"
     26  1.1  christos #include "target.h"
     27  1.1  christos #include "cli/cli-utils.h"
     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.1  christos   pattern_buf = 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.1  christos 			       + max (TYPE_LENGTH (t), sizeof (int64_t)));
    183  1.1  christos       if (pattern_buf_size_need > pattern_buf_size)
    184  1.1  christos 	{
    185  1.1  christos 	  size_t current_offset = pattern_buf_end - pattern_buf;
    186  1.1  christos 
    187  1.1  christos 	  pattern_buf_size = pattern_buf_size_need * 2;
    188  1.1  christos 	  pattern_buf = xrealloc (pattern_buf, pattern_buf_size);
    189  1.1  christos 	  pattern_buf_end = pattern_buf + current_offset;
    190  1.1  christos 	}
    191  1.1  christos 
    192  1.1  christos       if (size != '\0')
    193  1.1  christos 	{
    194  1.1  christos 	  x = value_as_long (v);
    195  1.1  christos 	  switch (size)
    196  1.1  christos 	    {
    197  1.1  christos 	    case 'b':
    198  1.1  christos 	      *pattern_buf_end++ = x;
    199  1.1  christos 	      break;
    200  1.1  christos 	    case 'h':
    201  1.1  christos 	      put_bits (x, pattern_buf_end, 16, big_p);
    202  1.1  christos 	      pattern_buf_end += sizeof (int16_t);
    203  1.1  christos 	      break;
    204  1.1  christos 	    case 'w':
    205  1.1  christos 	      put_bits (x, pattern_buf_end, 32, big_p);
    206  1.1  christos 	      pattern_buf_end += sizeof (int32_t);
    207  1.1  christos 	      break;
    208  1.1  christos 	    case 'g':
    209  1.1  christos 	      put_bits (x, pattern_buf_end, 64, big_p);
    210  1.1  christos 	      pattern_buf_end += sizeof (int64_t);
    211  1.1  christos 	      break;
    212  1.1  christos 	    }
    213  1.1  christos 	}
    214  1.1  christos       else
    215  1.1  christos 	{
    216  1.1  christos 	  memcpy (pattern_buf_end, value_contents (v), TYPE_LENGTH (t));
    217  1.1  christos 	  pattern_buf_end += TYPE_LENGTH (t);
    218  1.1  christos 	}
    219  1.1  christos 
    220  1.1  christos       if (*s == ',')
    221  1.1  christos 	++s;
    222  1.1  christos       s = skip_spaces_const (s);
    223  1.1  christos     }
    224  1.1  christos 
    225  1.1  christos   if (pattern_buf_end == pattern_buf)
    226  1.1  christos     error (_("Missing search pattern."));
    227  1.1  christos 
    228  1.1  christos   pattern_len = pattern_buf_end - pattern_buf;
    229  1.1  christos 
    230  1.1  christos   if (search_space_len < pattern_len)
    231  1.1  christos     error (_("Search space too small to contain pattern."));
    232  1.1  christos 
    233  1.1  christos   *max_countp = max_count;
    234  1.1  christos   *pattern_bufp = pattern_buf;
    235  1.1  christos   *pattern_lenp = pattern_len;
    236  1.1  christos   *start_addrp = start_addr;
    237  1.1  christos   *search_space_lenp = search_space_len;
    238  1.1  christos 
    239  1.1  christos   /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF
    240  1.1  christos      to the caller now.  */
    241  1.1  christos   discard_cleanups (old_cleanups);
    242  1.1  christos }
    243  1.1  christos 
    244  1.1  christos static void
    245  1.1  christos find_command (char *args, int from_tty)
    246  1.1  christos {
    247  1.1  christos   struct gdbarch *gdbarch = get_current_arch ();
    248  1.1  christos   bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
    249  1.1  christos   /* Command line parameters.
    250  1.1  christos      These are initialized to avoid uninitialized warnings from -Wall.  */
    251  1.1  christos   ULONGEST max_count = 0;
    252  1.1  christos   gdb_byte *pattern_buf = 0;
    253  1.1  christos   ULONGEST pattern_len = 0;
    254  1.1  christos   CORE_ADDR start_addr = 0;
    255  1.1  christos   ULONGEST search_space_len = 0;
    256  1.1  christos   /* End of command line parameters.  */
    257  1.1  christos   unsigned int found_count;
    258  1.1  christos   CORE_ADDR last_found_addr;
    259  1.1  christos   struct cleanup *old_cleanups;
    260  1.1  christos 
    261  1.1  christos   parse_find_args (args, &max_count, &pattern_buf, &pattern_len,
    262  1.1  christos 		   &start_addr, &search_space_len, big_p);
    263  1.1  christos 
    264  1.1  christos   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
    265  1.1  christos 
    266  1.1  christos   /* Perform the search.  */
    267  1.1  christos 
    268  1.1  christos   found_count = 0;
    269  1.1  christos   last_found_addr = 0;
    270  1.1  christos 
    271  1.1  christos   while (search_space_len >= pattern_len
    272  1.1  christos 	 && found_count < max_count)
    273  1.1  christos     {
    274  1.1  christos       /* Offset from start of this iteration to the next iteration.  */
    275  1.1  christos       ULONGEST next_iter_incr;
    276  1.1  christos       CORE_ADDR found_addr;
    277  1.1  christos       int found = target_search_memory (start_addr, search_space_len,
    278  1.1  christos 					pattern_buf, pattern_len, &found_addr);
    279  1.1  christos 
    280  1.1  christos       if (found <= 0)
    281  1.1  christos 	break;
    282  1.1  christos 
    283  1.1  christos       print_address (gdbarch, found_addr, gdb_stdout);
    284  1.1  christos       printf_filtered ("\n");
    285  1.1  christos       ++found_count;
    286  1.1  christos       last_found_addr = found_addr;
    287  1.1  christos 
    288  1.1  christos       /* Begin next iteration at one byte past this match.  */
    289  1.1  christos       next_iter_incr = (found_addr - start_addr) + 1;
    290  1.1  christos 
    291  1.1  christos       /* For robustness, we don't let search_space_len go -ve here.  */
    292  1.1  christos       if (search_space_len >= next_iter_incr)
    293  1.1  christos 	search_space_len -= next_iter_incr;
    294  1.1  christos       else
    295  1.1  christos 	search_space_len = 0;
    296  1.1  christos       start_addr += next_iter_incr;
    297  1.1  christos     }
    298  1.1  christos 
    299  1.1  christos   /* Record and print the results.  */
    300  1.1  christos 
    301  1.1  christos   set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
    302  1.1  christos   if (found_count > 0)
    303  1.1  christos     {
    304  1.1  christos       struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
    305  1.1  christos 
    306  1.1  christos       set_internalvar (lookup_internalvar ("_"),
    307  1.1  christos 		       value_from_pointer (ptr_type, last_found_addr));
    308  1.1  christos     }
    309  1.1  christos 
    310  1.1  christos   if (found_count == 0)
    311  1.1  christos     printf_filtered ("Pattern not found.\n");
    312  1.1  christos   else
    313  1.1  christos     printf_filtered ("%d pattern%s found.\n", found_count,
    314  1.1  christos 		     found_count > 1 ? "s" : "");
    315  1.1  christos 
    316  1.1  christos   do_cleanups (old_cleanups);
    317  1.1  christos }
    318  1.1  christos 
    319  1.1  christos /* Provide a prototype to silence -Wmissing-prototypes.  */
    320  1.1  christos extern initialize_file_ftype _initialize_mem_search;
    321  1.1  christos 
    322  1.1  christos void
    323  1.1  christos _initialize_mem_search (void)
    324  1.1  christos {
    325  1.1  christos   add_cmd ("find", class_vars, find_command, _("\
    326  1.1  christos Search memory for a sequence of bytes.\n\
    327  1.1  christos Usage:\nfind \
    328  1.1  christos [/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
    329  1.1  christos find [/size-char] [/max-count] start-address, +length, expr1 [, expr2 ...]\n\
    330  1.1  christos size-char is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
    331  1.1  christos and if not specified the size is taken from the type of the expression\n\
    332  1.1  christos in the current language.\n\
    333  1.1  christos Note that this means for example that in the case of C-like languages\n\
    334  1.1  christos a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
    335  1.1  christos which is typically four bytes.\n\
    336  1.1  christos \n\
    337  1.1  christos The address of the last match is stored as the value of \"$_\".\n\
    338  1.1  christos Convenience variable \"$numfound\" is set to the number of matches."),
    339  1.1  christos 	   &cmdlist);
    340  1.1  christos }
    341