GDB (API)
/home/stan/gdb/src/gdb/findcmd.c
Go to the documentation of this file.
00001 /* The find command.
00002 
00003    Copyright (C) 2008-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "arch-utils.h"
00022 #include <ctype.h>
00023 #include "gdb_string.h"
00024 #include "gdbcmd.h"
00025 #include "value.h"
00026 #include "target.h"
00027 #include "cli/cli-utils.h"
00028 
00029 /* Copied from bfd_put_bits.  */
00030 
00031 static void
00032 put_bits (bfd_uint64_t data, gdb_byte *buf, int bits, bfd_boolean big_p)
00033 {
00034   int i;
00035   int bytes;
00036 
00037   gdb_assert (bits % 8 == 0);
00038 
00039   bytes = bits / 8;
00040   for (i = 0; i < bytes; i++)
00041     {
00042       int index = big_p ? bytes - i - 1 : i;
00043 
00044       buf[index] = data & 0xff;
00045       data >>= 8;
00046     }
00047 }
00048 
00049 /* Subroutine of find_command to simplify it.
00050    Parse the arguments of the "find" command.  */
00051 
00052 static void
00053 parse_find_args (char *args, ULONGEST *max_countp,
00054                  gdb_byte **pattern_bufp, ULONGEST *pattern_lenp,
00055                  CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
00056                  bfd_boolean big_p)
00057 {
00058   /* Default to using the specified type.  */
00059   char size = '\0';
00060   ULONGEST max_count = ~(ULONGEST) 0;
00061   /* Buffer to hold the search pattern.  */
00062   gdb_byte *pattern_buf;
00063   /* Current size of search pattern buffer.
00064      We realloc space as needed.  */
00065 #define INITIAL_PATTERN_BUF_SIZE 100
00066   ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
00067   /* Pointer to one past the last in-use part of pattern_buf.  */
00068   gdb_byte *pattern_buf_end;
00069   ULONGEST pattern_len;
00070   CORE_ADDR start_addr;
00071   ULONGEST search_space_len;
00072   const char *s = args;
00073   struct cleanup *old_cleanups;
00074   struct value *v;
00075 
00076   if (args == NULL)
00077     error (_("Missing search parameters."));
00078 
00079   pattern_buf = xmalloc (pattern_buf_size);
00080   pattern_buf_end = pattern_buf;
00081   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
00082 
00083   /* Get search granularity and/or max count if specified.
00084      They may be specified in either order, together or separately.  */
00085 
00086   while (*s == '/')
00087     {
00088       ++s;
00089 
00090       while (*s != '\0' && *s != '/' && !isspace (*s))
00091         {
00092           if (isdigit (*s))
00093             {
00094               max_count = atoi (s);
00095               while (isdigit (*s))
00096                 ++s;
00097               continue;
00098             }
00099 
00100           switch (*s)
00101             {
00102             case 'b':
00103             case 'h':
00104             case 'w':
00105             case 'g':
00106               size = *s++;
00107               break;
00108             default:
00109               error (_("Invalid size granularity."));
00110             }
00111         }
00112 
00113       s = skip_spaces_const (s);
00114     }
00115 
00116   /* Get the search range.  */
00117 
00118   v = parse_to_comma_and_eval (&s);
00119   start_addr = value_as_address (v);
00120 
00121   if (*s == ',')
00122     ++s;
00123   s = skip_spaces_const (s);
00124 
00125   if (*s == '+')
00126     {
00127       LONGEST len;
00128 
00129       ++s;
00130       v = parse_to_comma_and_eval (&s);
00131       len = value_as_long (v);
00132       if (len == 0)
00133         {
00134           do_cleanups (old_cleanups);
00135           printf_filtered (_("Empty search range.\n"));
00136           return;
00137         }
00138       if (len < 0)
00139         error (_("Invalid length."));
00140       /* Watch for overflows.  */
00141       if (len > CORE_ADDR_MAX
00142           || (start_addr + len - 1) < start_addr)
00143         error (_("Search space too large."));
00144       search_space_len = len;
00145     }
00146   else
00147     {
00148       CORE_ADDR end_addr;
00149 
00150       v = parse_to_comma_and_eval (&s);
00151       end_addr = value_as_address (v);
00152       if (start_addr > end_addr)
00153         error (_("Invalid search space, end precedes start."));
00154       search_space_len = end_addr - start_addr + 1;
00155       /* We don't support searching all of memory
00156          (i.e. start=0, end = 0xff..ff).
00157          Bail to avoid overflows later on.  */
00158       if (search_space_len == 0)
00159         error (_("Overflow in address range "
00160                  "computation, choose smaller range."));
00161     }
00162 
00163   if (*s == ',')
00164     ++s;
00165 
00166   /* Fetch the search string.  */
00167 
00168   while (*s != '\0')
00169     {
00170       LONGEST x;
00171       struct type *t;
00172       ULONGEST pattern_buf_size_need;
00173 
00174       s = skip_spaces_const (s);
00175 
00176       v = parse_to_comma_and_eval (&s);
00177       t = value_type (v);
00178 
00179       /* Keep it simple and assume size == 'g' when watching for when we
00180          need to grow the pattern buf.  */
00181       pattern_buf_size_need = (pattern_buf_end - pattern_buf
00182                                + max (TYPE_LENGTH (t), sizeof (int64_t)));
00183       if (pattern_buf_size_need > pattern_buf_size)
00184         {
00185           size_t current_offset = pattern_buf_end - pattern_buf;
00186 
00187           pattern_buf_size = pattern_buf_size_need * 2;
00188           pattern_buf = xrealloc (pattern_buf, pattern_buf_size);
00189           pattern_buf_end = pattern_buf + current_offset;
00190         }
00191 
00192       if (size != '\0')
00193         {
00194           x = value_as_long (v);
00195           switch (size)
00196             {
00197             case 'b':
00198               *pattern_buf_end++ = x;
00199               break;
00200             case 'h':
00201               put_bits (x, pattern_buf_end, 16, big_p);
00202               pattern_buf_end += sizeof (int16_t);
00203               break;
00204             case 'w':
00205               put_bits (x, pattern_buf_end, 32, big_p);
00206               pattern_buf_end += sizeof (int32_t);
00207               break;
00208             case 'g':
00209               put_bits (x, pattern_buf_end, 64, big_p);
00210               pattern_buf_end += sizeof (int64_t);
00211               break;
00212             }
00213         }
00214       else
00215         {
00216           memcpy (pattern_buf_end, value_contents (v), TYPE_LENGTH (t));
00217           pattern_buf_end += TYPE_LENGTH (t);
00218         }
00219 
00220       if (*s == ',')
00221         ++s;
00222       s = skip_spaces_const (s);
00223     }
00224 
00225   if (pattern_buf_end == pattern_buf)
00226     error (_("Missing search pattern."));
00227 
00228   pattern_len = pattern_buf_end - pattern_buf;
00229 
00230   if (search_space_len < pattern_len)
00231     error (_("Search space too small to contain pattern."));
00232 
00233   *max_countp = max_count;
00234   *pattern_bufp = pattern_buf;
00235   *pattern_lenp = pattern_len;
00236   *start_addrp = start_addr;
00237   *search_space_lenp = search_space_len;
00238 
00239   /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF
00240      to the caller now.  */
00241   discard_cleanups (old_cleanups);
00242 }
00243 
00244 static void
00245 find_command (char *args, int from_tty)
00246 {
00247   struct gdbarch *gdbarch = get_current_arch ();
00248   bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
00249   /* Command line parameters.
00250      These are initialized to avoid uninitialized warnings from -Wall.  */
00251   ULONGEST max_count = 0;
00252   gdb_byte *pattern_buf = 0;
00253   ULONGEST pattern_len = 0;
00254   CORE_ADDR start_addr = 0;
00255   ULONGEST search_space_len = 0;
00256   /* End of command line parameters.  */
00257   unsigned int found_count;
00258   CORE_ADDR last_found_addr;
00259   struct cleanup *old_cleanups;
00260 
00261   parse_find_args (args, &max_count, &pattern_buf, &pattern_len, 
00262                    &start_addr, &search_space_len, big_p);
00263 
00264   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
00265 
00266   /* Perform the search.  */
00267 
00268   found_count = 0;
00269   last_found_addr = 0;
00270 
00271   while (search_space_len >= pattern_len
00272          && found_count < max_count)
00273     {
00274       /* Offset from start of this iteration to the next iteration.  */
00275       ULONGEST next_iter_incr;
00276       CORE_ADDR found_addr;
00277       int found = target_search_memory (start_addr, search_space_len,
00278                                         pattern_buf, pattern_len, &found_addr);
00279 
00280       if (found <= 0)
00281         break;
00282 
00283       print_address (gdbarch, found_addr, gdb_stdout);
00284       printf_filtered ("\n");
00285       ++found_count;
00286       last_found_addr = found_addr;
00287 
00288       /* Begin next iteration at one byte past this match.  */
00289       next_iter_incr = (found_addr - start_addr) + 1;
00290 
00291       /* For robustness, we don't let search_space_len go -ve here.  */
00292       if (search_space_len >= next_iter_incr)
00293         search_space_len -= next_iter_incr;
00294       else
00295         search_space_len = 0;
00296       start_addr += next_iter_incr;
00297     }
00298 
00299   /* Record and print the results.  */
00300 
00301   set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
00302   if (found_count > 0)
00303     {
00304       struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
00305 
00306       set_internalvar (lookup_internalvar ("_"),
00307                        value_from_pointer (ptr_type, last_found_addr));
00308     }
00309 
00310   if (found_count == 0)
00311     printf_filtered ("Pattern not found.\n");
00312   else
00313     printf_filtered ("%d pattern%s found.\n", found_count,
00314                      found_count > 1 ? "s" : "");
00315 
00316   do_cleanups (old_cleanups);
00317 }
00318 
00319 /* Provide a prototype to silence -Wmissing-prototypes.  */
00320 extern initialize_file_ftype _initialize_mem_search;
00321 
00322 void
00323 _initialize_mem_search (void)
00324 {
00325   add_cmd ("find", class_vars, find_command, _("\
00326 Search memory for a sequence of bytes.\n\
00327 Usage:\nfind \
00328 [/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
00329 find [/size-char] [/max-count] start-address, +length, expr1 [, expr2 ...]\n\
00330 size-char is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
00331 and if not specified the size is taken from the type of the expression\n\
00332 in the current language.\n\
00333 Note that this means for example that in the case of C-like languages\n\
00334 a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
00335 which is typically four bytes.\n\
00336 \n\
00337 The address of the last match is stored as the value of \"$_\".\n\
00338 Convenience variable \"$numfound\" is set to the number of matches."),
00339            &cmdlist);
00340 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines