/* The find command.
- Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2008-2019 Free Software Foundation, Inc.
This file is part of GDB.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
+#include "arch-utils.h"
#include <ctype.h>
-#include "gdb_string.h"
#include "gdbcmd.h"
#include "value.h"
#include "target.h"
+#include "cli/cli-utils.h"
+#include <algorithm>
+#include "common/byte-vector.h"
/* Copied from bfd_put_bits. */
static void
-put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
+put_bits (bfd_uint64_t data, gdb::byte_vector &buf, int bits, bfd_boolean big_p)
{
int i;
int bytes;
gdb_assert (bits % 8 == 0);
bytes = bits / 8;
+ size_t last = buf.size ();
+ buf.resize (last + bytes);
for (i = 0; i < bytes; i++)
{
int index = big_p ? bytes - i - 1 : i;
- buf[index] = data & 0xff;
+ buf[last + index] = data & 0xff;
data >>= 8;
}
}
/* Subroutine of find_command to simplify it.
Parse the arguments of the "find" command. */
-static void
-parse_find_args (char *args, ULONGEST *max_countp,
- char **pattern_bufp, ULONGEST *pattern_lenp,
- CORE_ADDR *start_addrp, ULONGEST *search_space_lenp)
+static gdb::byte_vector
+parse_find_args (const char *args, ULONGEST *max_countp,
+ CORE_ADDR *start_addrp, ULONGEST *search_space_lenp,
+ bfd_boolean big_p)
{
/* Default to using the specified type. */
char size = '\0';
ULONGEST max_count = ~(ULONGEST) 0;
/* Buffer to hold the search pattern. */
- char *pattern_buf;
- /* Current size of search pattern buffer.
- We realloc space as needed. */
-#define INITIAL_PATTERN_BUF_SIZE 100
- ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
- /* Pointer to one past the last in-use part of pattern_buf. */
- char *pattern_buf_end;
- ULONGEST pattern_len;
+ gdb::byte_vector pattern_buf;
CORE_ADDR start_addr;
ULONGEST search_space_len;
- char *s = args;
- bfd_boolean big_p = gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG;
- struct cleanup *old_cleanups;
+ const char *s = args;
struct value *v;
if (args == NULL)
error (_("Missing search parameters."));
- pattern_buf = xmalloc (pattern_buf_size);
- pattern_buf_end = pattern_buf;
- old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
-
/* Get search granularity and/or max count if specified.
They may be specified in either order, together or separately. */
}
}
- while (isspace (*s))
- ++s;
+ s = skip_spaces (s);
}
/* Get the search range. */
if (*s == ',')
++s;
- while (isspace (*s))
- ++s;
+ s = skip_spaces (s);
if (*s == '+')
{
LONGEST len;
+
++s;
v = parse_to_comma_and_eval (&s);
len = value_as_long (v);
if (len == 0)
{
printf_filtered (_("Empty search range.\n"));
- return;
+ return pattern_buf;
}
if (len < 0)
error (_("Invalid length."));
else
{
CORE_ADDR end_addr;
+
v = parse_to_comma_and_eval (&s);
end_addr = value_as_address (v);
if (start_addr > end_addr)
- error (_("Invalid search space, end preceeds start."));
+ error (_("Invalid search space, end precedes start."));
search_space_len = end_addr - start_addr + 1;
/* We don't support searching all of memory
(i.e. start=0, end = 0xff..ff).
Bail to avoid overflows later on. */
if (search_space_len == 0)
- error (_("Overflow in address range computation, choose smaller range."));
+ error (_("Overflow in address range "
+ "computation, choose smaller range."));
}
if (*s == ',')
while (*s != '\0')
{
LONGEST x;
- int val_bytes;
+ struct type *t;
- while (isspace (*s))
- ++s;
+ s = skip_spaces (s);
v = parse_to_comma_and_eval (&s);
- val_bytes = TYPE_LENGTH (value_type (v));
-
- /* Keep it simple and assume size == 'g' when watching for when we
- need to grow the pattern buf. */
- if ((pattern_buf_end - pattern_buf + max (val_bytes, sizeof (int64_t)))
- > pattern_buf_size)
- {
- size_t current_offset = pattern_buf_end - pattern_buf;
- pattern_buf_size *= 2;
- pattern_buf = xrealloc (pattern_buf, pattern_buf_size);
- pattern_buf_end = pattern_buf + current_offset;
- }
+ t = value_type (v);
if (size != '\0')
{
switch (size)
{
case 'b':
- *pattern_buf_end++ = x;
+ pattern_buf.push_back (x);
break;
case 'h':
- put_bits (x, pattern_buf_end, 16, big_p);
- pattern_buf_end += sizeof (int16_t);
+ put_bits (x, pattern_buf, 16, big_p);
break;
case 'w':
- put_bits (x, pattern_buf_end, 32, big_p);
- pattern_buf_end += sizeof (int32_t);
+ put_bits (x, pattern_buf, 32, big_p);
break;
case 'g':
- put_bits (x, pattern_buf_end, 64, big_p);
- pattern_buf_end += sizeof (int64_t);
+ put_bits (x, pattern_buf, 64, big_p);
break;
}
}
else
{
- memcpy (pattern_buf_end, value_contents_raw (v), val_bytes);
- pattern_buf_end += val_bytes;
+ const gdb_byte *contents = value_contents (v);
+ pattern_buf.insert (pattern_buf.end (), contents,
+ contents + TYPE_LENGTH (t));
}
if (*s == ',')
++s;
- while (isspace (*s))
- ++s;
+ s = skip_spaces (s);
}
- if (pattern_buf_end == pattern_buf)
+ if (pattern_buf.empty ())
error (_("Missing search pattern."));
- pattern_len = pattern_buf_end - pattern_buf;
-
- if (search_space_len < pattern_len)
+ if (search_space_len < pattern_buf.size ())
error (_("Search space too small to contain pattern."));
*max_countp = max_count;
- *pattern_bufp = pattern_buf;
- *pattern_lenp = pattern_len;
*start_addrp = start_addr;
*search_space_lenp = search_space_len;
- /* We successfully parsed the arguments, leave the freeing of PATTERN_BUF
- to the caller now. */
- discard_cleanups (old_cleanups);
+ return pattern_buf;
}
static void
-find_command (char *args, int from_tty)
+find_command (const char *args, int from_tty)
{
+ struct gdbarch *gdbarch = get_current_arch ();
+ bfd_boolean big_p = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG;
/* Command line parameters.
These are initialized to avoid uninitialized warnings from -Wall. */
ULONGEST max_count = 0;
- char *pattern_buf = 0;
- ULONGEST pattern_len = 0;
CORE_ADDR start_addr = 0;
ULONGEST search_space_len = 0;
/* End of command line parameters. */
unsigned int found_count;
CORE_ADDR last_found_addr;
- struct cleanup *old_cleanups;
- parse_find_args (args, &max_count, &pattern_buf, &pattern_len,
- &start_addr, &search_space_len);
-
- old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
+ gdb::byte_vector pattern_buf = parse_find_args (args, &max_count,
+ &start_addr,
+ &search_space_len,
+ big_p);
/* Perform the search. */
found_count = 0;
last_found_addr = 0;
- while (search_space_len >= pattern_len
+ while (search_space_len >= pattern_buf.size ()
&& found_count < max_count)
{
/* Offset from start of this iteration to the next iteration. */
ULONGEST next_iter_incr;
CORE_ADDR found_addr;
int found = target_search_memory (start_addr, search_space_len,
- pattern_buf, pattern_len, &found_addr);
+ pattern_buf.data (),
+ pattern_buf.size (),
+ &found_addr);
if (found <= 0)
break;
- print_address (found_addr, gdb_stdout);
+ print_address (gdbarch, found_addr, gdb_stdout);
printf_filtered ("\n");
++found_count;
last_found_addr = found_addr;
/* Record and print the results. */
- set_internalvar (lookup_internalvar ("numfound"),
- value_from_longest (builtin_type_int32,
- (LONGEST) found_count));
+ set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
if (found_count > 0)
{
- struct gdbarch *gdbarch = current_gdbarch;
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+
set_internalvar (lookup_internalvar ("_"),
value_from_pointer (ptr_type, last_found_addr));
}
else
printf_filtered ("%d pattern%s found.\n", found_count,
found_count > 1 ? "s" : "");
-
- do_cleanups (old_cleanups);
}
void
{
add_cmd ("find", class_vars, find_command, _("\
Search memory for a sequence of bytes.\n\
-Usage:\n\
-find [/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
+Usage:\nfind \
+[/size-char] [/max-count] start-address, end-address, expr1 [, expr2 ...]\n\
find [/size-char] [/max-count] start-address, +length, expr1 [, expr2 ...]\n\
size-char is one of b,h,w,g for 8,16,32,64 bit values respectively,\n\
and if not specified the size is taken from the type of the expression\n\
in the current language.\n\
Note that this means for example that in the case of C-like languages\n\
a search for an untyped 0x42 will search for \"(int) 0x42\"\n\
-which is typically four bytes.\n\
+which is typically four bytes, and a search for a string \"hello\" will\n\
+include the trailing '\\0'. The null terminator can be removed from\n\
+searching by using casts, e.g.: {char[5]}\"hello\".\n\
\n\
The address of the last match is stored as the value of \"$_\".\n\
Convenience variable \"$numfound\" is set to the number of matches."),