public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* [python] Implement gdb.search_memory.
@ 2009-02-20 22:03 Thiago Jung Bauermann
  2009-02-23 19:28 ` Jan Kratochvil
  2009-02-24  1:06 ` [PATCH] Fix double-free crash in gdbpy_search_memory Jan Kratochvil
  0 siblings, 2 replies; 10+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-20 22:03 UTC (permalink / raw)
  To: archer ml

Hi,

This patch implents gdb.search_memory, exposing the functionality of the
'find' CLI command. Just pushed it to the branch.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


gdb/
2009-02-20  Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* findcmd.c (put_bits): Remove static attribute.
	(allocate_pattern_buffer): New function, factored out of
	parse_find_args.
	(increase_pattern_buffer): Likewise.
	(search_memory): Likewise
	(parse_find_args): Use allocate_pattern_buffer and
	increase_pattern_buffer.
	(find_command): Use search_memory.
	* python/python-internal.h (gdbpy_is_value_object): Add prototype.
	(get_addr_from_python): Likewise.
	* python/python-utils.c (get_addr_from_python): New function.
	* python/python-value.c (builtin_type_upylong): New define.
	(convert_value_from_python): If an overflow occurs when converting
	to long long, try to convert as unsigned.
	(gdbpy_is_value_object): New function.
	* python/python.c (add_value_pattern): New function.
	(add_pattern_element): Likewise.
	(get_search_pattern): Likewise.
	(gdbpy_search_memory): Likewise.
	(GdbMethods): Add `search_memory' entry.
	* target.h (allocate_pattern_buffer): Add prototype.
	(increase_pattern_buffer): Likewise.
	(search_memory): Likewise.
	(put_bits): Likewise.
	* value.c (pack_unsigned_long): New function.
	(value_from_ulongest): Likewise.
	(value.h): Add prototype.

gdb/testsuite/
2009-02-20  Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* gdb.python/find.exp: New file.
	* gdb.python/find.c: New file.

gdb/doc/

2009-02-20  Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* gdb.texinfo (Basic Python): Document `gdb.search_memory'
---
 gdb/doc/gdb.texinfo               |   17 +++
 gdb/findcmd.c                     |  111 +++++++++++++-----
 gdb/python/python-internal.h      |    4 +
 gdb/python/python-utils.c         |   46 +++++++
 gdb/python/python-value.c         |   41 ++++++-
 gdb/python/python.c               |  238 +++++++++++++++++++++++++++++++++++++
 gdb/target.h                      |   14 ++
 gdb/testsuite/gdb.python/find.c   |   64 ++++++++++
 gdb/testsuite/gdb.python/find.exp |  186 +++++++++++++++++++++++++++++
 gdb/value.c                       |   48 ++++++++
 gdb/value.h                       |    1 +
 11 files changed, 740 insertions(+), 30 deletions(-)
 create mode 100644 gdb/testsuite/gdb.python/find.c
 create mode 100644 gdb/testsuite/gdb.python/find.exp

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4408635..91114a1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18280,6 +18280,23 @@ protocol, i.e., a string, an array or the object returned from
 @var{length} determines the number of bytes from @var{buffer} to be written.
 @end defun
 
+@findex gdb.search_memory
+@defun search_memory @var{address} @var{length} @var{pattern} @r{[}@var{size}@r{]} @r{[}@var{max_count}@r{]}
+Search a region of the inferior memory starting at @var{address} with the given
+@var{length}.  @var{pattern} can be a string, a byte array, a buffer object,
+a number, a @code{gdb.Value} object (@pxref{Values From Inferior}) or a list
+or tuple with elements in any combination of those types.  If @var{size} is
+given and is non-zero, it specifies the size in bytes of a Python scalar or
+@code{gdb.Value} in the search pattern.  If @var{size} is zero or not specified,
+ it is taken from the value's type in the current language.
+This is useful when one wants to specify the search
+pattern as a mixture of types.
+Note that this means, for example, that in the case of C-like languages
+a search for an untyped 0x42 will search for @samp{(int) 0x42}
+which is typically four bytes.  @var{max_count} is the highest number of matches
+to search for.
+@end defun
+
 @node Exception Handling
 @subsubsection Exception Handling
 @cindex python exceptions
diff --git a/gdb/findcmd.c b/gdb/findcmd.c
index 4e7fa09..f912dcf 100644
--- a/gdb/findcmd.c
+++ b/gdb/findcmd.c
@@ -26,7 +26,7 @@
 
 /* Copied from bfd_put_bits.  */
 
-static void
+void
 put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
 {
   int i;
@@ -44,6 +44,41 @@ put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
     }
 }
 
+/* Allocates a buffer in *PATTERN_BUF, with a hard-coded initial size which
+   will be returned in *PATTERN_BUF_SIZE. *PATTERN_BUF_END points to the same
+   place as *PATTERN_BUF, indicating that the buffer is initially empty.  */
+
+void
+allocate_pattern_buffer (char **pattern_buf, char **pattern_buf_end,
+			 ULONGEST *pattern_buf_size)
+{
+#define INITIAL_PATTERN_BUF_SIZE 100
+  *pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
+  *pattern_buf = xmalloc (*pattern_buf_size);
+  *pattern_buf_end = *pattern_buf;
+}
+
+/* Grows *PATTERN_BUF by a factor of two if it's not large enough to hold
+   VAL_BYTES more bytes  or a 64-bit value, whichever is larger.
+   *PATTERN_BUF_END is updated as necessary.  */
+
+void
+increase_pattern_buffer (char **pattern_buf, char **pattern_buf_end,
+			 ULONGEST *pattern_buf_size, int val_bytes)
+{
+    /* 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;
+      }
+}
+
 /* Subroutine of find_command to simplify it.
    Parse the arguments of the "find" command.  */
 
@@ -59,8 +94,7 @@ parse_find_args (char *args, ULONGEST *max_countp,
   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;
+  ULONGEST pattern_buf_size;
   /* Pointer to one past the last in-use part of pattern_buf.  */
   char *pattern_buf_end;
   ULONGEST pattern_len;
@@ -74,8 +108,7 @@ parse_find_args (char *args, ULONGEST *max_countp,
   if (args == NULL)
     error (_("Missing search parameters."));
 
-  pattern_buf = xmalloc (pattern_buf_size);
-  pattern_buf_end = pattern_buf;
+  allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size);
   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
 
   /* Get search granularity and/or max count if specified.
@@ -172,16 +205,8 @@ parse_find_args (char *args, ULONGEST *max_countp,
       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;
-	}
+      increase_pattern_buffer (&pattern_buf, &pattern_buf_end,
+			       &pattern_buf_size, val_bytes);
 
       if (size != '\0')
 	{
@@ -236,6 +261,45 @@ parse_find_args (char *args, ULONGEST *max_countp,
   discard_cleanups (old_cleanups);
 }
 
+/* Drives target_search_memory to sweep through the specified search space,
+   possibly in several iterations (with one call to this function for each
+   iteration).  *START_ADDR is the address where the search starts, and is
+   updated to the next starting address to continue the search.
+   *SEARCH_SPACE_LEN is the amount of bytes which will be searched, and is
+   updated for the next iteration. PATTERN_BUF holds the pattern to be searched
+   for, PATTERN_LEN is the size of the pattern in bytes.  If a match is found,
+   it's address is put in *FOUND_ADDR.
+
+   Returns 1 if found, 0 if not found, and -1 if there was an error requiring
+   halting of the search (e.g. memory read error).  */
+
+int
+search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len,
+	       const char *pattern_buf, ULONGEST pattern_len,
+	       CORE_ADDR *found_addr)
+{
+  /* Offset from start of this iteration to the next iteration.  */
+  ULONGEST next_iter_incr;
+  int found;
+    
+  found = target_search_memory (*start_addr, *search_space_len,
+				pattern_buf, pattern_len, found_addr);
+  if (found <= 0)
+    return found;
+
+  /* Begin next iteration at one byte past this match.  */
+  next_iter_incr = (*found_addr - *start_addr) + 1;
+
+  /* For robustness, we don't let search_space_len go -ve here.  */
+  if (*search_space_len >= next_iter_incr)
+    *search_space_len -= next_iter_incr;
+  else
+    *search_space_len = 0;
+  *start_addr += next_iter_incr;
+
+  return found;
+}
+
 static void
 find_command (char *args, int from_tty)
 {
@@ -264,12 +328,11 @@ find_command (char *args, int from_tty)
   while (search_space_len >= pattern_len
 	 && 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);
+      int found;
 
+      found = search_memory (&start_addr, &search_space_len, pattern_buf,
+			     pattern_len, &found_addr);
       if (found <= 0)
 	break;
 
@@ -277,16 +340,6 @@ find_command (char *args, int from_tty)
       printf_filtered ("\n");
       ++found_count;
       last_found_addr = found_addr;
-
-      /* Begin next iteration at one byte past this match.  */
-      next_iter_incr = (found_addr - start_addr) + 1;
-
-      /* For robustness, we don't let search_space_len go -ve here.  */
-      if (search_space_len >= next_iter_incr)
-	search_space_len -= next_iter_incr;
-      else
-	search_space_len = 0;
-      start_addr += next_iter_incr;
     }
 
   /* Record and print the results.  */
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index afdf821..0608330 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -157,6 +157,8 @@ char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
 
+int gdbpy_is_value_object (PyObject *obj);
+
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
 char *apply_varobj_pretty_printer (PyObject *print_obj, struct value *value,
@@ -170,4 +172,6 @@ extern PyObject *gdbpy_to_string_cst;
 extern PyObject *gdbpy_display_hint_cst;
 extern PyObject *gdbpy_doc_cst;
 
+int get_addr_from_python (PyObject *obj, CORE_ADDR *addr);
+
 #endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index 1e6d952..c6c305f 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -19,6 +19,7 @@
 
 #include "defs.h"
 #include "charset.h"
+#include "value.h"
 #include "python-internal.h"
 

@@ -181,3 +182,48 @@ gdbpy_is_string (PyObject *obj)
 {
   return PyString_Check (obj) || PyUnicode_Check (obj);
 }
+
+/* Converts OBJ to a CORE_ADDR value.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+int
+get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
+{
+  if (gdbpy_is_value_object (obj))
+    *addr = value_as_address (value_object_to_value (obj));
+  else if (PyLong_Check (obj))
+    {
+      /* Assume CORE_ADDR corresponds to unsigned long.  */
+      *addr = PyLong_AsUnsignedLong (obj);
+      if (PyErr_Occurred () != NULL)
+	return 0;
+    }
+  else if (PyInt_Check (obj))
+    {
+      long val;
+
+      /* Assume CORE_ADDR corresponds to unsigned long.  */
+      val = PyInt_AsLong (obj);
+
+      if (val >= 0)
+	*addr = val;
+      else
+      {
+	/* If no error ocurred, VAL is indeed negative.  */
+	if (PyErr_Occurred () != NULL)
+	  return 0;
+
+	PyErr_SetString (PyExc_ValueError, "negative address");
+	return 0;
+      }
+    }
+  else
+    {
+      PyErr_SetString (PyExc_TypeError, "invalid type for address");
+      return 0;
+    }
+
+  return 1;
+}
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 55361d6..ca29f46 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -52,6 +52,10 @@ struct value *values_in_python = NULL;
 /* Python's long type corresponds to C's long long type.  */
 #define builtin_type_pylong builtin_type (current_gdbarch)->builtin_long_long
 
+/* Python's long type corresponds to C's long long type.  Unsigned version.  */
+#define builtin_type_upylong builtin_type \
+  (current_gdbarch)->builtin_unsigned_long_long
+
 #define builtin_type_pybool \
   language_bool_type (current_language, current_gdbarch)
 
@@ -798,7 +802,34 @@ convert_value_from_python (PyObject *obj)
 	{
 	  LONGEST l = PyLong_AsLongLong (obj);
 
-	  if (! PyErr_Occurred ())
+	  if (PyErr_Occurred ())
+	    {
+	      /* If the error was an overflow, we can try converting to
+	         ULONGEST instead.  */
+	      if (PyErr_ExceptionMatches (PyExc_OverflowError))
+		{
+		  PyObject *etype, *evalue, *etraceback, *zero;
+
+		  PyErr_Fetch (&etype, &evalue, &etraceback);
+		  zero = PyInt_FromLong (0);
+
+		  /* Check whether obj is positive.  */
+		  if (PyObject_RichCompareBool (obj, zero, Py_GT) > 0)
+		    {
+		      ULONGEST ul;
+
+		      ul = PyLong_AsUnsignedLongLong (obj);
+		      if (! PyErr_Occurred ())
+			value = value_from_ulongest (builtin_type_upylong, ul);
+		    }
+		  else
+		    /* There's nothing we can do.  */
+		    PyErr_Restore (etype, evalue, etraceback);
+
+		  Py_DECREF (zero);
+		}
+	    }
+	  else
 	    value = value_from_longest (builtin_type_pylong, l);
 	}
       else if (PyFloat_Check (obj))
@@ -857,6 +888,14 @@ gdbpy_history (PyObject *self, PyObject *args)
   return value_to_value_object (res_val);
 }
 
+/* Returns 1 in OBJ is a gdb.Value object, 0 otherwise.  */
+
+int
+gdbpy_is_value_object (PyObject *obj)
+{
+  return PyObject_TypeCheck (obj, &value_object_type);
+}
+
 void
 gdbpy_initialize_values (void)
 {
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8677da6..5836a15 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -326,6 +326,241 @@ gdbpy_find_pc_function (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
+/* Adds GDB value V to the pattern buffer in *PATTERN_BUF.  If SIZE is not zero,
+   it specifies the number of bytes from V to copy to *PATTERN_BUF.  The
+   function increases the size of *PATTERN_BUF as necessary, adjusting
+   *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process.  */
+
+static void
+add_value_pattern (struct value *v, int size, char **pattern_buf,
+		   char **pattern_buf_end, ULONGEST *pattern_buf_size)
+{
+  int val_bytes;
+
+  if (size)
+    {
+      LONGEST x = value_as_long (v);
+
+      if (size == 1)
+	*(*pattern_buf_end)++ = x;
+      else
+	{
+	  put_bits (x, *pattern_buf_end, size * 8,
+		    gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG);
+	  *pattern_buf_end += size;
+	}
+    }
+  else
+   {
+     val_bytes = TYPE_LENGTH (value_type (v));
+
+     increase_pattern_buffer (pattern_buf, pattern_buf_end,
+			      pattern_buf_size, val_bytes);
+
+     memcpy (*pattern_buf_end, value_contents_raw (v), val_bytes);
+     *pattern_buf_end += val_bytes;
+   }
+}
+
+/* This function does the actual work of constructing the pattern buffer from
+   OBJ.  If OBJ is an object which implements the read buffer protocol (such
+   as a string, a byte array or gdb.Membuf), then its contents are directly
+   copied to *PATTERN_BUF.  If it is a list, then this function is recursively
+   called for each of its elements.  If OBJ is an object which can be converted
+   to a GDB value, then the contents of the value are copied to PATTERN_BUF.
+   If SIZE is different than zero, then it limits the number of bytes which
+   are copied to the buffer in case OBJ is converted to a GDB value.  That
+   means that SIZE influences only Python scalars and gdb.Value objects.
+   The function increases the size of *PATTERN_BUF as necessary, adjusting
+   *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+static int
+add_pattern_element (PyObject *obj, int size, char **pattern_buf,
+		     char **pattern_buf_end, ULONGEST *pattern_buf_size)
+{
+  if (PyObject_CheckReadBuffer (obj))
+    {
+      /* Handle string, Unicode string, byte array, gdb.Membuf and any other
+         object implementing the buffer protocol.  The SIZE parameter is
+	 ignored in this case.  */
+
+      int val_bytes;
+      const void *buffer;
+
+      if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1)
+	return 0;
+
+      increase_pattern_buffer (pattern_buf, pattern_buf_end,
+			       pattern_buf_size, val_bytes);
+
+      memcpy (*pattern_buf_end, buffer, val_bytes);
+      *pattern_buf_end += val_bytes;
+    }
+  else if (gdbpy_is_value_object (obj))
+    add_value_pattern (value_object_to_value (obj), size, pattern_buf,
+		       pattern_buf_end, pattern_buf_size);
+  else if (PySequence_Check (obj))
+    {
+      /* Handle lists and tuples.  */
+
+      Py_ssize_t i, num_objs;
+
+      num_objs = PySequence_Size (obj);
+      for (i = 0; i < num_objs; i++)
+	if (!add_pattern_element (PySequence_GetItem (obj, i), size,
+				  pattern_buf, pattern_buf_end,
+				  pattern_buf_size))
+	  return 0;
+    }
+  else
+    {
+      /* See if we can convert from a Python object to a GDB value.  */
+
+      struct value *v = convert_value_from_python (obj);
+
+      if (v)
+	add_value_pattern (v, size, pattern_buf, pattern_buf_end,
+			   pattern_buf_size);
+      else
+	return 0;
+    }
+
+  return 1;
+}
+
+/* Constructs the search pattern from OBJ, putting it in *PATTERN_BUFP, and its
+   size in *PATTERN_LENP.  See the function add_pattern_element to learn how
+   the search pattern is obtained from OBJ.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+static int
+get_search_pattern (PyObject *obj, int size, char **pattern_bufp,
+		    ULONGEST *pattern_lenp)
+{
+  /* Buffer to hold the search pattern.  */
+  char *pattern_buf;
+  /* Current size of search pattern buffer.
+     We realloc space as needed.  */
+  ULONGEST pattern_buf_size;
+  /* Pointer to one past the last in-use part of pattern_buf.  */
+  char *pattern_buf_end;
+  struct cleanup *old_cleanups;
+
+  allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size);
+  old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
+
+  if (!add_pattern_element (obj, size, &pattern_buf, &pattern_buf_end,
+			    &pattern_buf_size))
+    {
+      do_cleanups (old_cleanups);
+
+      return 0;
+    }
+
+  *pattern_bufp = pattern_buf;
+  *pattern_lenp = pattern_buf_end - pattern_buf;
+
+  discard_cleanups (old_cleanups);
+
+  return 1;
+}
+
+/* Implementation of
+   gdb.search_memory (start_address, length, pattern|list
+		      [, size] [, max_count]).
+   The third argument may be either a pattern, or a list or tupple of patterns
+   to be searched.  Size is the size in bytes of each search query value, either
+   1, 2, 4 or 8.  Returns a list of the addresses where matches were found.  */
+
+PyObject *
+gdbpy_search_memory (PyObject *self, PyObject *args)
+{
+  int size = 0;
+  long length;
+  unsigned int found_count = 0;
+  long max_count = 0;
+  CORE_ADDR start_addr;
+  char *pattern_buf;
+  ULONGEST pattern_len, search_space_len;
+  PyObject *pattern, *list = NULL, *start_addr_obj;
+  struct cleanup *cleanups = NULL;
+  volatile struct gdb_exception except;
+
+  /* Assume CORE_ADDR corresponds to unsigned long.  */
+  if (! PyArg_ParseTuple (args, "OlO|il", &start_addr_obj, &length, &pattern,
+			  &size, &max_count))
+    return NULL;
+
+  if (!max_count)
+    max_count = LONG_MAX;
+
+  if (!length)
+    {
+      PyErr_SetString (PyExc_ValueError, "empty search range");
+      return NULL;
+    }
+  else if (length < 0)
+    {
+      PyErr_SetString (PyExc_ValueError, "invalid search range");
+      return NULL;
+    }
+  else
+    {
+      /* Watch for overflows.  */
+      if (length > CORE_ADDR_MAX
+	  || (start_addr + length - 1) < start_addr)
+	{
+	  PyErr_SetString (PyExc_ValueError, "search range too large");
+	  return NULL;
+	}
+
+      search_space_len = length;
+    }
+
+  if (size != 0 && size != 1 && size != 2 && size != 4 && size != 8)
+    {
+      PyErr_SetString (PyExc_ValueError, "invalid pattern size");
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (get_addr_from_python (start_addr_obj, &start_addr))
+	{
+	  if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len))
+	    {
+	      cleanups = make_cleanup (xfree, pattern_buf);
+	      list = PyList_New (0);
+
+	      while (search_space_len >= pattern_len && found_count < max_count)
+		{
+		  CORE_ADDR found_addr;
+		  int found;
+
+		  found = search_memory (&start_addr, &search_space_len,
+					 pattern_buf, pattern_len, &found_addr);
+		  if (found <= 0)
+		    break;
+
+		  PyList_Append (list, PyLong_FromUnsignedLong (found_addr));
+		  ++found_count;
+		}
+	    }
+	}
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (cleanups)
+    do_cleanups (cleanups);
+
+  return list;
+}
+
 /* A Python function which is a wrapper for decode_line_1.  */
 
 static PyObject *
@@ -1686,6 +1921,9 @@ Return a buffer object for reading from the inferior's memory." },
   { "write_memory", gdbpy_write_memory, METH_VARARGS,
     "write_memory (address, buffer [, length])\n\
 Write the given buffer object to the inferior's memory." },
+  { "search_memory", gdbpy_search_memory, METH_VARARGS,
+    "search_memory (start_address, length, pattern|list [, size] [, max_count]) -> list\n\
+Return a list with the addresses where matches were found." },
 
   { "write", gdbpy_write, METH_VARARGS,
     "Write a string using gdb's filtered stream." },
diff --git a/gdb/target.h b/gdb/target.h
index caf6384..ee87c17 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1167,6 +1167,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
                                  ULONGEST pattern_len,
                                  CORE_ADDR *found_addrp);
 
+/* Utility functions which can be used by search_memory implementations.  */
+
+void allocate_pattern_buffer (char **pattern_bufp, char **pattern_buf_end,
+			      ULONGEST *pattern_buf_size);
+
+void increase_pattern_buffer (char **pattern_bufp, char **pattern_buf_end,
+			      ULONGEST *pattern_buf_size, int val_bytes);
+
+int search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len,
+		   const char *pattern_buf, ULONGEST pattern_len,
+		   CORE_ADDR *found_addr);
+
+void put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p);
+
 /* Command logging facility.  */
 
 #define target_log_command(p)						\
diff --git a/gdb/testsuite/gdb.python/find.c b/gdb/testsuite/gdb.python/find.c
new file mode 100644
index 0000000..35ddd8c
--- /dev/null
+++ b/gdb/testsuite/gdb.python/find.c
@@ -0,0 +1,64 @@
+/* Testcase for the search_memory Python function.
+   This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   Please email any bugs, comments, and/or additions to this file to:
+   bug-gdb@gnu.org  */
+
+/* Based on the gdb.base/find.c testcase.  */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#define CHUNK_SIZE 16000 /* same as findcmd.c's */
+#define BUF_SIZE (2 * CHUNK_SIZE) /* at least two chunks */
+
+static int8_t int8_search_buf[100];
+static int16_t int16_search_buf[100];
+static int32_t int32_search_buf[100];
+static int64_t int64_search_buf[100];
+
+static char *search_buf;
+static int search_buf_size;
+
+static int x;
+
+static void
+stop_here ()
+{
+  x = 1; // stop here
+}
+
+static void
+init_bufs ()
+{
+  search_buf_size = BUF_SIZE;
+  search_buf = malloc (search_buf_size);
+  if (search_buf == NULL)
+    exit (1);
+  memset (search_buf, 'x', search_buf_size);
+}
+
+int
+main ()
+{
+  init_bufs ();
+
+  stop_here ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.python/find.exp b/gdb/testsuite/gdb.python/find.exp
new file mode 100644
index 0000000..30afe41
--- /dev/null
+++ b/gdb/testsuite/gdb.python/find.exp
@@ -0,0 +1,186 @@
+# Copyright 2008, 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This tests the search_memory Python function.
+# Based on the gdb.base/find.exp testcase.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+    global gdb_prompt
+    foreach {input result} $args {
+	if {[gdb_test_multiple $input "$name - $input" {
+	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+		pass "$name - $input"
+	    }
+	}]} {
+	    return 1
+	}
+    }
+    return 0
+}
+
+set testfile "find"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}] != "" } {
+    untested find.exp
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+    -re "not supported.*$gdb_prompt $"	{
+      unsupported "python support is disabled"
+      return -1
+    }
+    -re "$gdb_prompt $"	{}
+}
+
+gdb_test "break $srcfile:stop_here" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "breakpoint function in file"
+
+gdb_run_cmd
+gdb_expect {
+    -re "Breakpoint \[0-9\]+,.*stop_here.* at .*$srcfile:.*$gdb_prompt $" {
+	pass "run until function breakpoint"
+    }
+    -re "$gdb_prompt $" {
+	fail "run until function breakpoint"
+    }
+    timeout {
+	fail "run until function breakpoint (timeout)"
+    }
+}
+
+# We've now got the target program in a state where we can test "find".
+
+set hex_number {0x[0-9a-fA-F][0-9a-fA-F]*}
+set dec_number {[0-9]+}
+set history_prefix {[$][0-9]* = }
+set newline {[\r\n]+}
+set pattern_not_found "${newline}.]"
+set one_pattern_found "${newline}.${dec_number}L]"
+set two_patterns_found "${newline}.${dec_number}L, ${dec_number}L]"
+
+# Test string pattern.
+
+gdb_test "set *(int32_t*) &int8_search_buf\[10\] = 0x61616161" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('&int8_search_buf\[0\]')" "" ""
+gdb_test "py length = gdb.parse_and_eval ('sizeof (int8_search_buf)')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, length, 'aaa')" \
+  "${two_patterns_found}" "find string pattern"
+
+# Test not finding pattern because search range too small, with
+# potential find at the edge of the range.
+
+gdb_test "py print gdb.search_memory (start_addr, 10+3, 'aaaa')" \
+  "${pattern_not_found}" "pattern not found at end of range"
+
+# Increase the search range by 1 and we should find the pattern.
+
+gdb_test "py print gdb.search_memory (start_addr, 10+3+1, \['a', 'a', 'a', 'a'\])" \
+  "${one_pattern_found}" "pattern found at end of range"
+
+# Test max-count with size-char.
+
+gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], 1, 1)" \
+  "\[\\r\\n\].${dec_number}L]" "size = 1, max_count = 1"
+
+# Test 16-bit pattern.
+
+gdb_test "set int16_search_buf\[10\] = 0x1234" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('&int16_search_buf\[0\]')" "" ""
+gdb_test "py length = gdb.parse_and_eval ('sizeof (int16_search_buf)')" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int16_t) 0x1234')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, length, 0x1234, 2)" \
+  "${one_pattern_found}" "find 16-bit pattern, with python pattern"
+
+gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 16-bit pattern, with value pattern"
+
+# Test 32-bit pattern.
+
+gdb_test "set int32_search_buf\[10\] = 0x12345678" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('&int32_search_buf\[0\]')" "" ""
+gdb_test "py length = gdb.parse_and_eval ('sizeof (int32_search_buf)')" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int32_t) 0x12345678')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, length, 0x12345678, 4)" \
+  "${one_pattern_found}" "find 32-bit pattern, with python pattern"
+gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 32-bit pattern, with value pattern"
+
+# Test 64-bit pattern.
+
+gdb_test "set int64_search_buf\[10\] = 0xfedcba9876543210LL" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('&int64_search_buf\[0\]')" "" ""
+gdb_test "py length = gdb.parse_and_eval ('sizeof (int64_search_buf)')" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int64_t) 0xfedcba9876543210LL')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, length, 0xfedcba9876543210, 8)" \
+  "${one_pattern_found}" "find 64-bit pattern, with python pattern"
+gdb_test "py print gdb.search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 64-bit pattern, with value pattern"
+
+# Test mixed-sized patterns.
+
+gdb_test "set *(int8_t*) &search_buf\[10\] = 0x62" "" ""
+gdb_test "set *(int16_t*) &search_buf\[11\] = 0x6363" "" ""
+gdb_test "set *(int32_t*) &search_buf\[13\] = 0x64646464" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('&search_buf\[0\]')" "" ""
+gdb_test "py pattern1 = gdb.parse_and_eval ('(int8_t) 0x62')" "" ""
+gdb_test "py pattern2 = gdb.parse_and_eval ('(int16_t) 0x6363')" "" ""
+gdb_test "py pattern3 = gdb.parse_and_eval ('(int32_t) 0x64646464')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, 100, \[pattern1, pattern2, pattern3\])" \
+    "${one_pattern_found}" "find mixed-sized pattern"
+
+# Test search spanning a large range, in the particular case of native
+# targets, test the search spanning multiple chunks.
+# Remote targets may implement the search differently.
+
+set CHUNK_SIZE 16000 ;
+
+gdb_test "set *(int32_t*) &search_buf\[0*${CHUNK_SIZE}+100\] = 0x12345678" "" ""
+gdb_test "set *(int32_t*) &search_buf\[1*${CHUNK_SIZE}+100\] = 0x12345678" "" ""
+gdb_test "py start_addr = gdb.parse_and_eval ('search_buf')" "" ""
+gdb_test "py length = gdb.parse_and_eval ('search_buf_size')" "" ""
+
+gdb_test "py print gdb.search_memory (start_addr, length, 0x12345678, 4)" \
+  "${two_patterns_found}" "search spanning large range"
+
+# For native targets, test a pattern straddling a chunk boundary.
+
+if [isnative] {
+    gdb_test "set *(int32_t*) &search_buf\[${CHUNK_SIZE}-1\] = 0xfdb97531" "" ""
+
+    gdb_test "py print gdb.search_memory (start_addr, length, 0xfdb97531, 4)" \
+      "${one_pattern_found}" "find pattern straddling chunk boundary"
+}
diff --git a/gdb/value.c b/gdb/value.c
index 7c66922..ac55685 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1783,6 +1783,41 @@ pack_long (gdb_byte *buf, struct type *type, LONGEST num)
 }
 

+/* Pack NUM into BUF using a target format of TYPE.  */
+
+void
+pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num)
+{
+  int len;
+
+  type = check_typedef (type);
+  len = TYPE_LENGTH (type);
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_INT:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_FLAGS:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_MEMBERPTR:
+      store_unsigned_integer (buf, len, num);
+      break;
+
+    case TYPE_CODE_REF:
+    case TYPE_CODE_PTR:
+      store_typed_address (buf, type, (CORE_ADDR) num);
+      break;
+
+    default:
+      error (_("\
+Unexpected type (%d) encountered for unsigned integer constant."),
+	     TYPE_CODE (type));
+    }
+}
+
+
 /* Convert C numbers into newly allocated values.  */
 
 struct value *
@@ -1796,6 +1831,19 @@ value_from_longest (struct type *type, LONGEST num)
 }
 

+/* Convert C unsigned numbers into newly allocated values.  */
+
+struct value *
+value_from_ulongest (struct type *type, ULONGEST num)
+{
+  struct value *val = allocate_value (type);
+
+  pack_unsigned_long (value_contents_raw (val), type, num);
+
+  return val;
+}
+
+
 /* Create a value representing a pointer of type TYPE to the address
    ADDR.  */
 struct value *
diff --git a/gdb/value.h b/gdb/value.h
index 1caf0c8..c8a4489 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -287,6 +287,7 @@ extern LONGEST unpack_field_as_long (struct type *type,
 extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num);
 
 extern struct value *value_from_longest (struct type *type, LONGEST num);
+extern struct value *value_from_ulongest (struct type *type, ULONGEST num);
 extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
 extern struct value *value_from_double (struct type *type, DOUBLEST num);
 extern struct value *value_from_decfloat (struct type *type,
-- 
1.5.6.5

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-20 22:03 [python] Implement gdb.search_memory Thiago Jung Bauermann
@ 2009-02-23 19:28 ` Jan Kratochvil
  2009-02-24  8:05   ` Phil Muldoon
  2009-02-24  1:06 ` [PATCH] Fix double-free crash in gdbpy_search_memory Jan Kratochvil
  1 sibling, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-02-23 19:28 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: archer ml

On Fri, 20 Feb 2009 23:03:31 +0100, Thiago Jung Bauermann wrote:
> Hi,
> 
> This patch implents gdb.search_memory, exposing the functionality of the
> 'find' CLI command. Just pushed it to the branch.
[...]
> +      if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1)

.././gdb/python/python.c:393: error: passing argument 3 of ‘PyObject_AsReadBuffer’ from incompatible pointer type

python-devel-2.5.2-1.fc10.x86_64

/usr/include/python2.5/abstract.h:
      /*  
	  Checks whether an arbitrary object supports the (character,
	  single segment) buffer interface.  Returns 1 on success, 0
	  on failure.

      */

     PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *obj,
					  const void **buffer,
					  Py_ssize_t *buffer_len);


Could you please check-in something backward/forward compatible?


Thanks,
Jan

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Fix double-free crash in gdbpy_search_memory.
  2009-02-20 22:03 [python] Implement gdb.search_memory Thiago Jung Bauermann
  2009-02-23 19:28 ` Jan Kratochvil
@ 2009-02-24  1:06 ` Jan Kratochvil
  2009-02-26  1:33   ` Thiago Jung Bauermann
  1 sibling, 1 reply; 10+ messages in thread
From: Jan Kratochvil @ 2009-02-24  1:06 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: archer ml

commit 20340ed988af98c24acd5efac0f36b015d3caf6a

Any cleanups get automatically executed on an exception.  Therefore the current
code was executing the cleanup handlers twice causing a crash.  Unreproducible
on archer-tromey-python but it was segfaulting gdb.python/find.exp in a merged
tree.

	* python/python.c (gdbpy_search_memory): Move `cleanups' and its
	execution inside TRY_CATCH.  New comment on `cleanups'.
---
 gdb/python/python.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/gdb/python/python.c b/gdb/python/python.c
index 5836a15..9a2c00c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -488,7 +488,6 @@ gdbpy_search_memory (PyObject *self, PyObject *args)
   char *pattern_buf;
   ULONGEST pattern_len, search_space_len;
   PyObject *pattern, *list = NULL, *start_addr_obj;
-  struct cleanup *cleanups = NULL;
   volatile struct gdb_exception except;
 
   /* Assume CORE_ADDR corresponds to unsigned long.  */
@@ -534,7 +533,9 @@ gdbpy_search_memory (PyObject *self, PyObject *args)
 	{
 	  if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len))
 	    {
-	      cleanups = make_cleanup (xfree, pattern_buf);
+	      /* Any cleanups get automatically executed on an exception.  */
+	      struct cleanup *cleanups = make_cleanup (xfree, pattern_buf);
+
 	      list = PyList_New (0);
 
 	      while (search_space_len >= pattern_len && found_count < max_count)
@@ -550,14 +551,13 @@ gdbpy_search_memory (PyObject *self, PyObject *args)
 		  PyList_Append (list, PyLong_FromUnsignedLong (found_addr));
 		  ++found_count;
 		}
+
+	      do_cleanups (cleanups);
 	    }
 	}
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-  if (cleanups)
-    do_cleanups (cleanups);
-
   return list;
 }
 
-- 
1.6.0.6

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-23 19:28 ` Jan Kratochvil
@ 2009-02-24  8:05   ` Phil Muldoon
  2009-02-26  2:02     ` Thiago Jung Bauermann
  0 siblings, 1 reply; 10+ messages in thread
From: Phil Muldoon @ 2009-02-24  8:05 UTC (permalink / raw)
  To: Jan Kratochvil, Thiago Jung Bauermann; +Cc: archer ml

[-- Attachment #1: Type: text/plain, Size: 1157 bytes --]

Jan Kratochvil wrote:
> On Fri, 20 Feb 2009 23:03:31 +0100, Thiago Jung Bauermann wrote:
>   
>> Hi,
>>
>> This patch implents gdb.search_memory, exposing the functionality of the
>> 'find' CLI command. Just pushed it to the branch.
>>     
> [...]
>   
>> +      if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1)
>>     
>
> .././gdb/python/python.c:393: error: passing argument 3 of ‘PyObject_AsReadBuffer’ from incompatible pointer type
>   

I needed to merge some code over to the archer-tromey-python branch
today and wanted a clean compile before I did so. I checked in these
fixes to the above warning, and one other. Please check the latter case,
I'm not sure if setting the buffer to NULL will lead to correct results
in a failure condition.

I think these warnings happen on this (my) system as the version of
Python is different. For reference:

[pmuldoon@localhost archer]$ rpm -q python
python-2.5.2-1.fc10.x86_64


Regards

Phil

ChangeLog

2009-02-24 Phil Muldoon <pmuldoon@redhat.com>

* python/python-membuf.c (get_char_buffer): Initialize buffer to NULL.
* python/python.c (add_pattern_element): Use Py_ssize_t.



[-- Attachment #2: warnings.patch --]
[-- Type: text/x-patch, Size: 897 bytes --]

diff --git a/gdb/python/python-membuf.c b/gdb/python/python-membuf.c
index d8a8183..04bf3b4 100644
--- a/gdb/python/python-membuf.c
+++ b/gdb/python/python-membuf.c
@@ -165,7 +165,7 @@ get_seg_count (PyObject *self, Py_ssize_t *lenp)
 Py_ssize_t
 get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
 {
-  void *ptr;
+  void *ptr = NULL;
   Py_ssize_t ret;
 
   ret = get_read_buffer (self, segment, &ptr);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 5836a15..83e6c32 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -387,7 +387,7 @@ add_pattern_element (PyObject *obj, int size, char **pattern_buf,
          object implementing the buffer protocol.  The SIZE parameter is
 	 ignored in this case.  */
 
-      int val_bytes;
+      Py_ssize_t val_bytes;
       const void *buffer;
 
       if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Fix double-free crash in gdbpy_search_memory.
  2009-02-24  1:06 ` [PATCH] Fix double-free crash in gdbpy_search_memory Jan Kratochvil
@ 2009-02-26  1:33   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 10+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-26  1:33 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: archer ml

El mar, 24-02-2009 a las 02:06 +0100, Jan Kratochvil escribió:
> Any cleanups get automatically executed on an exception.  Therefore the current
> code was executing the cleanup handlers twice causing a crash.  Unreproducible
> on archer-tromey-python but it was segfaulting gdb.python/find.exp in a merged
> tree.

Ooops, thanks for fixing this. 
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-24  8:05   ` Phil Muldoon
@ 2009-02-26  2:02     ` Thiago Jung Bauermann
  2009-02-26  2:46       ` Jan Kratochvil
  2009-02-26 19:00       ` Tom Tromey
  0 siblings, 2 replies; 10+ messages in thread
From: Thiago Jung Bauermann @ 2009-02-26  2:02 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Jan Kratochvil, archer ml

El mar, 24-02-2009 a las 08:05 +0000, Phil Muldoon escribió:
> Jan Kratochvil wrote:
> > .././gdb/python/python.c:393: error: passing argument 3 of ‘PyObject_AsReadBuffer’ from incompatible pointer type
<snip>   
> > /usr/include/python2.5/abstract.h:
<snip>
> >      PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *obj,
> >                                           const void **buffer,
> >                                           Py_ssize_t *buffer_len);

Strange, I have the same prototype in that header file here (I use
Debian lenny's python2.5-dev version 2.5.2-15, btw) and compilation is
fine here.

The problem seems to be that our compilers have their nitpicking levels
set to different values. Perhaps someone could tell me how I can make my
compiler behave like Fedora's? I'm using:

% gcc --version
gcc (Debian 4.3.3-3) 4.3.3

I have a set of commits which I was just about to push, but I'll hold
off for now to avoid triggering your additional alarms there.

> > Could you please check-in something backward/forward compatible?

This is not the issue here, it seems. But do we want to enforce
backward/forward compatibility for each pushed commit? We'd have to ask
everybody to compile their changes against the three different python
versions that configure currently detects before they push to the
branch.

> I needed to merge some code over to the archer-tromey-python branch
> today and wanted a clean compile before I did so. I checked in these
> fixes to the above warning, and one other.

Thanks!

> Please check the latter case,
> I'm not sure if setting the buffer to NULL will lead to correct results
> in a failure condition.

Well, it doesn't make things worse than what they already were. I
couldn't find a place which says what should happen to ptrptr in case of
an error. Perhaps we shouldn't touch it. I'll make the change.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-26  2:02     ` Thiago Jung Bauermann
@ 2009-02-26  2:46       ` Jan Kratochvil
  2009-02-26 19:00       ` Tom Tromey
  1 sibling, 0 replies; 10+ messages in thread
From: Jan Kratochvil @ 2009-02-26  2:46 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: Phil Muldoon, archer ml

On Thu, 26 Feb 2009 03:01:51 +0100, Thiago Jung Bauermann wrote:
> The problem seems to be that our compilers have their nitpicking levels
> set to different values. Perhaps someone could tell me how I can make my
> compiler behave like Fedora's? I'm using:

Assuming you still run 32bit.  When I put there `long' it is compatible to be
passed as `Py_ssize_t *'.


> > > Could you please check-in something backward/forward compatible?
> 
> This is not the issue here, it seems. But do we want to enforce
> backward/forward compatibility for each pushed commit?

I was assuming it happened as you run python2.4 so it is out of question.


Regards,
Jan

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-26  2:02     ` Thiago Jung Bauermann
  2009-02-26  2:46       ` Jan Kratochvil
@ 2009-02-26 19:00       ` Tom Tromey
  2009-03-04 17:26         ` Thiago Jung Bauermann
  2009-03-04 19:50         ` Thiago Jung Bauermann
  1 sibling, 2 replies; 10+ messages in thread
From: Tom Tromey @ 2009-02-26 19:00 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: Phil Muldoon, Jan Kratochvil, archer ml

>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:

Thiago> This is not the issue here, it seems. But do we want to enforce
Thiago> backward/forward compatibility for each pushed commit? 

No, a best effort is enough.  These sorts of bugs tend to be trivial
to fix; it isn't worth that amount of overhead.  Well, unless perhaps
someone wants to automate it for us...


I do have a couple follow-up suggestions.

A few functions in python-membuf.c are not static but probably should
be.  E.g., get_read_buffer.  (Or, if you intend to export that, give
it a less generic name.)

Also, mbpy_str still casts a CORE_ADDR to a void*, which is bad.
Daniel suggested using paddr or paddr_nz here.

Tom

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-26 19:00       ` Tom Tromey
@ 2009-03-04 17:26         ` Thiago Jung Bauermann
  2009-03-04 19:50         ` Thiago Jung Bauermann
  1 sibling, 0 replies; 10+ messages in thread
From: Thiago Jung Bauermann @ 2009-03-04 17:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Phil Muldoon, Jan Kratochvil, archer ml

El jue, 26-02-2009 a las 11:59 -0700, Tom Tromey escribió:
> A few functions in python-membuf.c are not static but probably should
> be.  E.g., get_read_buffer.  (Or, if you intend to export that, give
> it a less generic name.)

Ah, I forgot about that. Will look into it.

> Also, mbpy_str still casts a CORE_ADDR to a void*, which is bad.
> Daniel suggested using paddr or paddr_nz here.

I just committed the following patch to fix the issue. I just discovered
about paddr and friends. I used paddress instead of paddr. The
difference between paddr and paddress is that the former padds the
number on the left with 0s, while the latter doesn't. GDB seems to not
pad addresses more often than it pads when printing adresses to the
user.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


commit 7d013430def2b170f8e8ab1d24312dfecaccc13d
Author: Thiago Jung Bauermann <bauerman@br.ibm.com>
Date:   Wed Mar 4 09:14:23 2009 -0800

    Fix issue of casting CORE_ADDR to void * in mbpy_str.

	* python/python-membuf.c (mbpy_str): Use paddress and pulongest to print
	CORE_ADDR values instead of casting to void * and unsigned int.

diff --git a/gdb/python/python-membuf.c b/gdb/python/python-membuf.c
index 04bf3b4..c330652 100644
--- a/gdb/python/python-membuf.c
+++ b/gdb/python/python-membuf.c
@@ -125,9 +125,9 @@ mbpy_str (PyObject *self)
 {
   membuf_object *membuf_obj = (membuf_object *) self;
 
-  return PyString_FromFormat ("memory buffer for address %p, %u bytes long",
-			      (void *) membuf_obj->addr,
-			      (unsigned int) membuf_obj->length);
+  return PyString_FromFormat ("memory buffer for address %s, %s bytes long",
+			      paddress (membuf_obj->addr),
+			      pulongest (membuf_obj->length));
 }
 
 Py_ssize_t


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [python] Implement gdb.search_memory.
  2009-02-26 19:00       ` Tom Tromey
  2009-03-04 17:26         ` Thiago Jung Bauermann
@ 2009-03-04 19:50         ` Thiago Jung Bauermann
  1 sibling, 0 replies; 10+ messages in thread
From: Thiago Jung Bauermann @ 2009-03-04 19:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Phil Muldoon, Jan Kratochvil, archer ml

El jue, 26-02-2009 a las 11:59 -0700, Tom Tromey escribió:
> A few functions in python-membuf.c are not static but probably should
> be.  E.g., get_read_buffer.  (Or, if you intend to export that, give
> it a less generic name.)

Fixed with this patch. Committed.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

    Add static keyword to functions in python-membuf.c
    
    Plus one more minor fix.

	* python/python-membuf.c (get_read_buffer): Add static keyword.
	(get_write_buffer): Likewise.
	(get_seg_count): Likewise.
	(get_char_buffer): Likewise.
	(membuf_object_type: Set tp_new element.
	(gdbpy_initialize_membuf): Remove line setting tp_new element of
	membuf_object_type.

diff --git a/gdb/python/python-membuf.c b/gdb/python/python-membuf.c
index c330652..a4c7d74 100644
--- a/gdb/python/python-membuf.c
+++ b/gdb/python/python-membuf.c
@@ -130,7 +130,7 @@ mbpy_str (PyObject *self)
 			      pulongest (membuf_obj->length));
 }
 
-Py_ssize_t
+static Py_ssize_t
 get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
 {
   membuf_object *membuf_obj = (membuf_object *) self;
@@ -147,13 +147,13 @@ get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
   return membuf_obj->length;
 }
 
-Py_ssize_t
+static Py_ssize_t
 get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
 {
   return get_read_buffer (self, segment, ptrptr);
 }
 
-Py_ssize_t
+static Py_ssize_t
 get_seg_count (PyObject *self, Py_ssize_t *lenp)
 {
   if (lenp)
@@ -162,7 +162,7 @@ get_seg_count (PyObject *self, Py_ssize_t *lenp)
   return 1;
 }
 
-Py_ssize_t
+static Py_ssize_t
 get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
 {
   void *ptr = NULL;
@@ -212,13 +212,29 @@ static PyTypeObject membuf_object_type = {
   0,				  /*tp_setattro*/
   &buffer_procs,		  /*tp_as_buffer*/
   Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
-  "GDB memory buffer object" 	  /*tp_doc*/
+  "GDB memory buffer object", 	  /*tp_doc*/
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0,				  /* tp_alloc */
+  PyType_GenericNew		  /* tp_new */
 };
 
 void
 gdbpy_initialize_membuf (void)
 {
-  membuf_object_type.tp_new = PyType_GenericNew;
   if (PyType_Ready (&membuf_object_type) < 0)
     return;
 


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-03-04 19:50 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-20 22:03 [python] Implement gdb.search_memory Thiago Jung Bauermann
2009-02-23 19:28 ` Jan Kratochvil
2009-02-24  8:05   ` Phil Muldoon
2009-02-26  2:02     ` Thiago Jung Bauermann
2009-02-26  2:46       ` Jan Kratochvil
2009-02-26 19:00       ` Tom Tromey
2009-03-04 17:26         ` Thiago Jung Bauermann
2009-03-04 19:50         ` Thiago Jung Bauermann
2009-02-24  1:06 ` [PATCH] Fix double-free crash in gdbpy_search_memory Jan Kratochvil
2009-02-26  1:33   ` Thiago Jung Bauermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).