15796c8dcSSimon Schubert /* The find command.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2008-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "arch-utils.h"
225796c8dcSSimon Schubert #include <ctype.h>
235796c8dcSSimon Schubert #include "gdb_string.h"
245796c8dcSSimon Schubert #include "gdbcmd.h"
255796c8dcSSimon Schubert #include "value.h"
265796c8dcSSimon Schubert #include "target.h"
27*ef5ccd6cSJohn Marino #include "cli/cli-utils.h"
285796c8dcSSimon Schubert
295796c8dcSSimon Schubert /* Copied from bfd_put_bits. */
305796c8dcSSimon Schubert
315796c8dcSSimon Schubert static void
put_bits(bfd_uint64_t data,gdb_byte * buf,int bits,bfd_boolean big_p)32*ef5ccd6cSJohn Marino put_bits (bfd_uint64_t data, gdb_byte *buf, int bits, bfd_boolean big_p)
335796c8dcSSimon Schubert {
345796c8dcSSimon Schubert int i;
355796c8dcSSimon Schubert int bytes;
365796c8dcSSimon Schubert
375796c8dcSSimon Schubert gdb_assert (bits % 8 == 0);
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert bytes = bits / 8;
405796c8dcSSimon Schubert for (i = 0; i < bytes; i++)
415796c8dcSSimon Schubert {
425796c8dcSSimon Schubert int index = big_p ? bytes - i - 1 : i;
435796c8dcSSimon Schubert
445796c8dcSSimon Schubert buf[index] = data & 0xff;
455796c8dcSSimon Schubert data >>= 8;
465796c8dcSSimon Schubert }
475796c8dcSSimon Schubert }
485796c8dcSSimon Schubert
495796c8dcSSimon Schubert /* Subroutine of find_command to simplify it.
505796c8dcSSimon Schubert Parse the arguments of the "find" command. */
515796c8dcSSimon Schubert
525796c8dcSSimon Schubert static void
parse_find_args(char * args,ULONGEST * max_countp,gdb_byte ** pattern_bufp,ULONGEST * pattern_lenp,CORE_ADDR * start_addrp,ULONGEST * search_space_lenp,bfd_boolean big_p)535796c8dcSSimon Schubert parse_find_args (char *args, ULONGEST *max_countp,
54*ef5ccd6cSJohn Marino gdb_byte **pattern_bufp, ULONGEST *pattern_lenp,
555796c8dcSSimon Schubert CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
565796c8dcSSimon Schubert bfd_boolean big_p)
575796c8dcSSimon Schubert {
585796c8dcSSimon Schubert /* Default to using the specified type. */
595796c8dcSSimon Schubert char size = '\0';
605796c8dcSSimon Schubert ULONGEST max_count = ~(ULONGEST) 0;
615796c8dcSSimon Schubert /* Buffer to hold the search pattern. */
62*ef5ccd6cSJohn Marino gdb_byte *pattern_buf;
635796c8dcSSimon Schubert /* Current size of search pattern buffer.
645796c8dcSSimon Schubert We realloc space as needed. */
655796c8dcSSimon Schubert #define INITIAL_PATTERN_BUF_SIZE 100
665796c8dcSSimon Schubert ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
675796c8dcSSimon Schubert /* Pointer to one past the last in-use part of pattern_buf. */
68*ef5ccd6cSJohn Marino gdb_byte *pattern_buf_end;
695796c8dcSSimon Schubert ULONGEST pattern_len;
705796c8dcSSimon Schubert CORE_ADDR start_addr;
715796c8dcSSimon Schubert ULONGEST search_space_len;
72*ef5ccd6cSJohn Marino const char *s = args;
735796c8dcSSimon Schubert struct cleanup *old_cleanups;
745796c8dcSSimon Schubert struct value *v;
755796c8dcSSimon Schubert
765796c8dcSSimon Schubert if (args == NULL)
775796c8dcSSimon Schubert error (_("Missing search parameters."));
785796c8dcSSimon Schubert
795796c8dcSSimon Schubert pattern_buf = xmalloc (pattern_buf_size);
805796c8dcSSimon Schubert pattern_buf_end = pattern_buf;
815796c8dcSSimon Schubert old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
825796c8dcSSimon Schubert
835796c8dcSSimon Schubert /* Get search granularity and/or max count if specified.
845796c8dcSSimon Schubert They may be specified in either order, together or separately. */
855796c8dcSSimon Schubert
865796c8dcSSimon Schubert while (*s == '/')
875796c8dcSSimon Schubert {
885796c8dcSSimon Schubert ++s;
895796c8dcSSimon Schubert
905796c8dcSSimon Schubert while (*s != '\0' && *s != '/' && !isspace (*s))
915796c8dcSSimon Schubert {
925796c8dcSSimon Schubert if (isdigit (*s))
935796c8dcSSimon Schubert {
945796c8dcSSimon Schubert max_count = atoi (s);
955796c8dcSSimon Schubert while (isdigit (*s))
965796c8dcSSimon Schubert ++s;
975796c8dcSSimon Schubert continue;
985796c8dcSSimon Schubert }
995796c8dcSSimon Schubert
1005796c8dcSSimon Schubert switch (*s)
1015796c8dcSSimon Schubert {
1025796c8dcSSimon Schubert case 'b':
1035796c8dcSSimon Schubert case 'h':
1045796c8dcSSimon Schubert case 'w':
1055796c8dcSSimon Schubert case 'g':
1065796c8dcSSimon Schubert size = *s++;
1075796c8dcSSimon Schubert break;
1085796c8dcSSimon Schubert default:
1095796c8dcSSimon Schubert error (_("Invalid size granularity."));
1105796c8dcSSimon Schubert }
1115796c8dcSSimon Schubert }
1125796c8dcSSimon Schubert
113*ef5ccd6cSJohn Marino s = skip_spaces_const (s);
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert
1165796c8dcSSimon Schubert /* Get the search range. */
1175796c8dcSSimon Schubert
1185796c8dcSSimon Schubert v = parse_to_comma_and_eval (&s);
1195796c8dcSSimon Schubert start_addr = value_as_address (v);
1205796c8dcSSimon Schubert
1215796c8dcSSimon Schubert if (*s == ',')
1225796c8dcSSimon Schubert ++s;
123*ef5ccd6cSJohn Marino s = skip_spaces_const (s);
1245796c8dcSSimon Schubert
1255796c8dcSSimon Schubert if (*s == '+')
1265796c8dcSSimon Schubert {
1275796c8dcSSimon Schubert LONGEST len;
128cf7f2e2dSJohn Marino
1295796c8dcSSimon Schubert ++s;
1305796c8dcSSimon Schubert v = parse_to_comma_and_eval (&s);
1315796c8dcSSimon Schubert len = value_as_long (v);
1325796c8dcSSimon Schubert if (len == 0)
1335796c8dcSSimon Schubert {
134a45ae5f8SJohn Marino do_cleanups (old_cleanups);
1355796c8dcSSimon Schubert printf_filtered (_("Empty search range.\n"));
1365796c8dcSSimon Schubert return;
1375796c8dcSSimon Schubert }
1385796c8dcSSimon Schubert if (len < 0)
1395796c8dcSSimon Schubert error (_("Invalid length."));
1405796c8dcSSimon Schubert /* Watch for overflows. */
1415796c8dcSSimon Schubert if (len > CORE_ADDR_MAX
1425796c8dcSSimon Schubert || (start_addr + len - 1) < start_addr)
1435796c8dcSSimon Schubert error (_("Search space too large."));
1445796c8dcSSimon Schubert search_space_len = len;
1455796c8dcSSimon Schubert }
1465796c8dcSSimon Schubert else
1475796c8dcSSimon Schubert {
1485796c8dcSSimon Schubert CORE_ADDR end_addr;
149cf7f2e2dSJohn Marino
1505796c8dcSSimon Schubert v = parse_to_comma_and_eval (&s);
1515796c8dcSSimon Schubert end_addr = value_as_address (v);
1525796c8dcSSimon Schubert if (start_addr > end_addr)
153a45ae5f8SJohn Marino error (_("Invalid search space, end precedes start."));
1545796c8dcSSimon Schubert search_space_len = end_addr - start_addr + 1;
1555796c8dcSSimon Schubert /* We don't support searching all of memory
1565796c8dcSSimon Schubert (i.e. start=0, end = 0xff..ff).
1575796c8dcSSimon Schubert Bail to avoid overflows later on. */
1585796c8dcSSimon Schubert if (search_space_len == 0)
159c50c785cSJohn Marino error (_("Overflow in address range "
160c50c785cSJohn Marino "computation, choose smaller range."));
1615796c8dcSSimon Schubert }
1625796c8dcSSimon Schubert
1635796c8dcSSimon Schubert if (*s == ',')
1645796c8dcSSimon Schubert ++s;
1655796c8dcSSimon Schubert
1665796c8dcSSimon Schubert /* Fetch the search string. */
1675796c8dcSSimon Schubert
1685796c8dcSSimon Schubert while (*s != '\0')
1695796c8dcSSimon Schubert {
1705796c8dcSSimon Schubert LONGEST x;
171*ef5ccd6cSJohn Marino struct type *t;
172*ef5ccd6cSJohn Marino ULONGEST pattern_buf_size_need;
1735796c8dcSSimon Schubert
174*ef5ccd6cSJohn Marino s = skip_spaces_const (s);
1755796c8dcSSimon Schubert
1765796c8dcSSimon Schubert v = parse_to_comma_and_eval (&s);
177*ef5ccd6cSJohn Marino t = value_type (v);
1785796c8dcSSimon Schubert
1795796c8dcSSimon Schubert /* Keep it simple and assume size == 'g' when watching for when we
1805796c8dcSSimon Schubert need to grow the pattern buf. */
181*ef5ccd6cSJohn Marino pattern_buf_size_need = (pattern_buf_end - pattern_buf
182*ef5ccd6cSJohn Marino + max (TYPE_LENGTH (t), sizeof (int64_t)));
183*ef5ccd6cSJohn Marino if (pattern_buf_size_need > pattern_buf_size)
1845796c8dcSSimon Schubert {
1855796c8dcSSimon Schubert size_t current_offset = pattern_buf_end - pattern_buf;
186cf7f2e2dSJohn Marino
187*ef5ccd6cSJohn Marino pattern_buf_size = pattern_buf_size_need * 2;
1885796c8dcSSimon Schubert pattern_buf = xrealloc (pattern_buf, pattern_buf_size);
1895796c8dcSSimon Schubert pattern_buf_end = pattern_buf + current_offset;
1905796c8dcSSimon Schubert }
1915796c8dcSSimon Schubert
1925796c8dcSSimon Schubert if (size != '\0')
1935796c8dcSSimon Schubert {
1945796c8dcSSimon Schubert x = value_as_long (v);
1955796c8dcSSimon Schubert switch (size)
1965796c8dcSSimon Schubert {
1975796c8dcSSimon Schubert case 'b':
1985796c8dcSSimon Schubert *pattern_buf_end++ = x;
1995796c8dcSSimon Schubert break;
2005796c8dcSSimon Schubert case 'h':
2015796c8dcSSimon Schubert put_bits (x, pattern_buf_end, 16, big_p);
2025796c8dcSSimon Schubert pattern_buf_end += sizeof (int16_t);
2035796c8dcSSimon Schubert break;
2045796c8dcSSimon Schubert case 'w':
2055796c8dcSSimon Schubert put_bits (x, pattern_buf_end, 32, big_p);
2065796c8dcSSimon Schubert pattern_buf_end += sizeof (int32_t);
2075796c8dcSSimon Schubert break;
2085796c8dcSSimon Schubert case 'g':
2095796c8dcSSimon Schubert put_bits (x, pattern_buf_end, 64, big_p);
2105796c8dcSSimon Schubert pattern_buf_end += sizeof (int64_t);
2115796c8dcSSimon Schubert break;
2125796c8dcSSimon Schubert }
2135796c8dcSSimon Schubert }
2145796c8dcSSimon Schubert else
2155796c8dcSSimon Schubert {
216*ef5ccd6cSJohn Marino memcpy (pattern_buf_end, value_contents (v), TYPE_LENGTH (t));
217*ef5ccd6cSJohn Marino pattern_buf_end += TYPE_LENGTH (t);
2185796c8dcSSimon Schubert }
2195796c8dcSSimon Schubert
2205796c8dcSSimon Schubert if (*s == ',')
2215796c8dcSSimon Schubert ++s;
222*ef5ccd6cSJohn Marino s = skip_spaces_const (s);
2235796c8dcSSimon Schubert }
2245796c8dcSSimon Schubert
2255796c8dcSSimon Schubert if (pattern_buf_end == pattern_buf)
2265796c8dcSSimon Schubert error (_("Missing search pattern."));
2275796c8dcSSimon Schubert
2285796c8dcSSimon Schubert pattern_len = pattern_buf_end - pattern_buf;
2295796c8dcSSimon Schubert
2305796c8dcSSimon Schubert if (search_space_len < pattern_len)
2315796c8dcSSimon Schubert error (_("Search space too small to contain pattern."));
2325796c8dcSSimon Schubert
2335796c8dcSSimon Schubert *max_countp = max_count;
2345796c8dcSSimon Schubert *pattern_bufp = pattern_buf;
2355796c8dcSSimon Schubert *pattern_lenp = pattern_len;
2365796c8dcSSimon Schubert *start_addrp = start_addr;
2375796c8dcSSimon Schubert *search_space_lenp = search_space_len;
2385796c8dcSSimon Schubert
2395796c8dcSSimon Schubert /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF
2405796c8dcSSimon Schubert to the caller now. */
2415796c8dcSSimon Schubert discard_cleanups (old_cleanups);
2425796c8dcSSimon Schubert }
2435796c8dcSSimon Schubert
2445796c8dcSSimon Schubert static void
find_command(char * args,int from_tty)2455796c8dcSSimon Schubert find_command (char *args, int from_tty)
2465796c8dcSSimon Schubert {
2475796c8dcSSimon Schubert struct gdbarch *gdbarch = get_current_arch ();
2485796c8dcSSimon Schubert bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
2495796c8dcSSimon Schubert /* Command line parameters.
2505796c8dcSSimon Schubert These are initialized to avoid uninitialized warnings from -Wall. */
2515796c8dcSSimon Schubert ULONGEST max_count = 0;
252*ef5ccd6cSJohn Marino gdb_byte *pattern_buf = 0;
2535796c8dcSSimon Schubert ULONGEST pattern_len = 0;
2545796c8dcSSimon Schubert CORE_ADDR start_addr = 0;
2555796c8dcSSimon Schubert ULONGEST search_space_len = 0;
2565796c8dcSSimon Schubert /* End of command line parameters. */
2575796c8dcSSimon Schubert unsigned int found_count;
2585796c8dcSSimon Schubert CORE_ADDR last_found_addr;
2595796c8dcSSimon Schubert struct cleanup *old_cleanups;
2605796c8dcSSimon Schubert
2615796c8dcSSimon Schubert parse_find_args (args, &max_count, &pattern_buf, &pattern_len,
2625796c8dcSSimon Schubert &start_addr, &search_space_len, big_p);
2635796c8dcSSimon Schubert
2645796c8dcSSimon Schubert old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
2655796c8dcSSimon Schubert
2665796c8dcSSimon Schubert /* Perform the search. */
2675796c8dcSSimon Schubert
2685796c8dcSSimon Schubert found_count = 0;
2695796c8dcSSimon Schubert last_found_addr = 0;
2705796c8dcSSimon Schubert
2715796c8dcSSimon Schubert while (search_space_len >= pattern_len
2725796c8dcSSimon Schubert && found_count < max_count)
2735796c8dcSSimon Schubert {
2745796c8dcSSimon Schubert /* Offset from start of this iteration to the next iteration. */
2755796c8dcSSimon Schubert ULONGEST next_iter_incr;
2765796c8dcSSimon Schubert CORE_ADDR found_addr;
2775796c8dcSSimon Schubert int found = target_search_memory (start_addr, search_space_len,
2785796c8dcSSimon Schubert pattern_buf, pattern_len, &found_addr);
2795796c8dcSSimon Schubert
2805796c8dcSSimon Schubert if (found <= 0)
2815796c8dcSSimon Schubert break;
2825796c8dcSSimon Schubert
2835796c8dcSSimon Schubert print_address (gdbarch, found_addr, gdb_stdout);
2845796c8dcSSimon Schubert printf_filtered ("\n");
2855796c8dcSSimon Schubert ++found_count;
2865796c8dcSSimon Schubert last_found_addr = found_addr;
2875796c8dcSSimon Schubert
2885796c8dcSSimon Schubert /* Begin next iteration at one byte past this match. */
2895796c8dcSSimon Schubert next_iter_incr = (found_addr - start_addr) + 1;
2905796c8dcSSimon Schubert
2915796c8dcSSimon Schubert /* For robustness, we don't let search_space_len go -ve here. */
2925796c8dcSSimon Schubert if (search_space_len >= next_iter_incr)
2935796c8dcSSimon Schubert search_space_len -= next_iter_incr;
2945796c8dcSSimon Schubert else
2955796c8dcSSimon Schubert search_space_len = 0;
2965796c8dcSSimon Schubert start_addr += next_iter_incr;
2975796c8dcSSimon Schubert }
2985796c8dcSSimon Schubert
2995796c8dcSSimon Schubert /* Record and print the results. */
3005796c8dcSSimon Schubert
3015796c8dcSSimon Schubert set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
3025796c8dcSSimon Schubert if (found_count > 0)
3035796c8dcSSimon Schubert {
3045796c8dcSSimon Schubert struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
305cf7f2e2dSJohn Marino
3065796c8dcSSimon Schubert set_internalvar (lookup_internalvar ("_"),
3075796c8dcSSimon Schubert value_from_pointer (ptr_type, last_found_addr));
3085796c8dcSSimon Schubert }
3095796c8dcSSimon Schubert
3105796c8dcSSimon Schubert if (found_count == 0)
3115796c8dcSSimon Schubert printf_filtered ("Pattern not found.\n");
3125796c8dcSSimon Schubert else
3135796c8dcSSimon Schubert printf_filtered ("%d pattern%s found.\n", found_count,
3145796c8dcSSimon Schubert found_count > 1 ? "s" : "");
3155796c8dcSSimon Schubert
3165796c8dcSSimon Schubert do_cleanups (old_cleanups);
3175796c8dcSSimon Schubert }
3185796c8dcSSimon Schubert
3195796c8dcSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes. */
3205796c8dcSSimon Schubert extern initialize_file_ftype _initialize_mem_search;
3215796c8dcSSimon Schubert
3225796c8dcSSimon Schubert void
_initialize_mem_search(void)3235796c8dcSSimon Schubert _initialize_mem_search (void)
3245796c8dcSSimon Schubert {
3255796c8dcSSimon Schubert add_cmd ("find", class_vars, find_command, _("\
3265796c8dcSSimon Schubert Search memory for a sequence of bytes.\n\
327c50c785cSJohn Marino Usage:\nfind \
328c50c785cSJohn Marino [/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
3295796c8dcSSimon Schubert find [/size-char] [/max-count] start-address, +length, expr1 [, expr2 ...]\n\
3305796c8dcSSimon Schubert size-char is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
3315796c8dcSSimon Schubert and if not specified the size is taken from the type of the expression\n\
3325796c8dcSSimon Schubert in the current language.\n\
3335796c8dcSSimon Schubert Note that this means for example that in the case of C-like languages\n\
3345796c8dcSSimon Schubert a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
3355796c8dcSSimon Schubert which is typically four bytes.\n\
3365796c8dcSSimon Schubert \n\
3375796c8dcSSimon Schubert The address of the last match is stored as the value of \"$_\".\n\
3385796c8dcSSimon Schubert Convenience variable \"$numfound\" is set to the number of matches."),
3395796c8dcSSimon Schubert &cmdlist);
3405796c8dcSSimon Schubert }
341