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