This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[python][commit] Move memory manipulation functions to theInferior class.


Hi,

This patch moves the gdb.{read,write,search}_memory functions to methods
in the Inferior class. There's no change in the code logic, just
shuffling bits around.

I'll probably commit (or post as RFC) more patches like this during the
week.

Committed to the Python branch.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


gdb/
	* Makefile.in (SUBDIR_PYTHON_OBS): Remove python-membuf.o.
	(SUBDIR_PYTHON_SRCS): Remove python-membuf.c.
	(python-membuf.o): Remove target.
	* python/python-inferior.c (membuf_object): Move from
	python-membuf.c.
	(membuf_object_type): Likewise.
	(infpy_read_memory): Likewise (was: gdbpy_read_memory).
	(infpy_write_memory): Likewise (was: gdbpy_write_memory).
	(mbpy_dealloc, mbpy_str, get_read_buffer, get_write_buffer,
	get_seg_count, get_char_buffer): Likewise.
	(add_value_pattern, add_pattern_element, get_search_pattern): Move
	from python.c.
	(infpy_search_memory): Likewise (was: gdbpy_search_memory).
	(gdbpy_initialize_inferior): Register membuf_object_type and the
	`Membuf' class with the Python interpreter.
	(inferior_object_methods): Add `read_memory', `write_memory' and
	`search_memory' elements.
	(buffer_procs, membuf_object_type): Move from python-membuf.c.
	* python/python-internal.h (gdbpy_read_memory, gdbpy_write_memory,
	gdbpy_initialize_membuf): Remove function prototypes.
	* python/python.c (GdbMethods): Remove `read_memory', `write_memory'
	and `search_memory' elements.

gdb/doc/
	* gdb.texinfo (Python API): Move documentation for read_memory,
	write_memory and search_memory to the `Inferiors In Python'
	section.

gdb/testsuite/
	* gdb.python/find.exp: Move all search tests to python-inferior.exp.
	* gdb.python/find.c: Delete file.
	* gdb.python/python-membuf.exp: Move all read and write tests to
	python-inferior.exp.
	* gdb.python/python-membuf.c: Delete file.
	* gdb.python/python-inferior.c: Expand to support memory read, write
	and search tests.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 514506c..20ea062 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -285,7 +285,6 @@ SUBDIR_PYTHON_OBS = \
 	python-hooks.o \
 	python-inferior.o \
 	python-infthread.o \
-	python-membuf.o \
 	python-objfile.o \
 	python-param.o \
 	python-symbol.o \
@@ -303,7 +302,6 @@ SUBDIR_PYTHON_SRCS = \
 	python/python-hooks.c \
 	python/python-inferior.c \
 	python/python-infthread.c \
-	python/python-membuf.c \
 	python/python-objfile.c \
 	python/python-param.c \
 	python/python-symbol.c \
@@ -1909,10 +1907,6 @@ python-infthread.o: $(srcdir)/python/python-infthread.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-infthread.c
 	$(POSTCOMPILE)
 
-python-membuf.o: $(srcdir)/python/python-membuf.c
-	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-membuf.c
-	$(POSTCOMPILE)
-
 python-objfile.o: $(srcdir)/python/python-objfile.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c
 	$(POSTCOMPILE)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4ec2cc9..da0fece 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18251,38 +18251,6 @@ Flush @value{GDBN}'s paginated standard output stream.  Flushing
 function.
 @end defun
 
-@findex gdb.read_memory
-@defun read_memory @var{address} @var{length}
-Read @var{length} bytes of memory from the inferior, starting at @var{address}.
-Returns a buffer object, which behaves much like an array or a string. It
-can be modified and given to the @code{gdb.write_memory} function.
-@end defun
-
-@findex gdb.write_memory
-@defun write_memory @var{address} @var{buffer} @r{[}@var{length}@r{]}
-Write the contents of @var{buffer} (a Python object which supports the buffer
-protocol, i.e., a string, an array or the object returned from
-@code{gdb.read_memory}) to the inferior, starting at @var{address}.  If given,
-@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
-
 @findex gdb.solib_address
 @defun solib_address @var{address}
 Return the name of the shared library holding the given address, or None.
@@ -18941,6 +18909,39 @@ This method returns a tuple holding all the threads which are valid
 when it is called.  If there are no valid threads, the method will
 return an empty list.
 @end defmethod
+
+@findex gdb.read_memory
+@defmethod Inferior read_memory @var{address} @var{length}
+Read @var{length} bytes of memory from the inferior, starting at
+@var{address}.  Returns a buffer object, which behaves much like an array
+or a string. It can be modified and given to the @code{gdb.write_memory}
+function.
+@end defmethod
+
+@findex gdb.write_memory
+@defmethod Inferior write_memory @var{address} @var{buffer} @r{[}@var{length}@r{]}
+Write the contents of @var{buffer} (a Python object which supports the
+buffer protocol, i.e., a string, an array or the object returned from
+@code{gdb.read_memory}) to the inferior, starting at @var{address}.
+If given, @var{length} determines the number of bytes from @var{buffer} to
+be written.
+@end defmethod
+
+@findex gdb.search_memory
+@defmethod Inferior 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 defmethod
 @end table
 
 @node Threads In Python
diff --git a/gdb/python/python-inferior.c b/gdb/python/python-inferior.c
index 7842874..a08be7b 100644
--- a/gdb/python/python-inferior.c
+++ b/gdb/python/python-inferior.c
@@ -18,6 +18,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "exceptions.h"
+#include "gdbcore.h"
 #include "gdbthread.h"
 #include "inferior.h"
 #include "observer.h"
@@ -45,6 +47,17 @@ typedef struct
 
 static PyTypeObject inferior_object_type;
 
+typedef struct {
+  PyObject_HEAD
+  void *buffer;
+
+  /* These are kept just for mbpy_str.  */
+  CORE_ADDR addr;
+  CORE_ADDR length;
+} membuf_object;
+
+static PyTypeObject membuf_object_type;
+
 /* Require that INFERIOR be a valid inferior ID.  */
 #define INFPY_REQUIRE_VALID(Inferior)				\
   do {								\
@@ -349,6 +362,406 @@ gdbpy_inferiors (PyObject *unused, PyObject *unused2)
   return tuple;
 }
 
+
+
+/* Membuf and memory manipulation.  */
+
+/* Implementation of gdb.read_memory (address, length).
+   Returns a Python buffer object with LENGTH bytes of the inferior's memory
+   at ADDRESS. Both arguments are integers.  */
+
+static PyObject *
+infpy_read_memory (PyObject *self, PyObject *args)
+{
+  int error = 0;
+  CORE_ADDR addr, length;
+  void *buffer = NULL;
+  membuf_object *membuf_obj;
+  PyObject *addr_obj, *length_obj;
+  struct cleanup *cleanups = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "OO", &addr_obj, &length_obj))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr)
+	  || !get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      buffer = xmalloc (length);
+      cleanups = make_cleanup (xfree, buffer);
+
+      read_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    return NULL;
+
+  discard_cleanups (cleanups);
+
+  membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
+  if (membuf_obj == NULL)
+    {
+      xfree (buffer);
+      PyErr_SetString (PyExc_MemoryError,
+		       "Could not allocate memory buffer object.");
+      return NULL;
+    }
+
+  membuf_obj->buffer = buffer;
+  membuf_obj->addr = addr;
+  membuf_obj->length = length;
+
+  return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+				       Py_END_OF_BUFFER);
+}
+
+/* Implementation of gdb.write_memory (address, buffer [, length]).
+   Writes the contents of BUFFER (a Python object supporting the read buffer
+   protocol) at ADDRESS in the inferior's memory.  Write LENGTH bytes from
+   BUFFER, or its entire contents if the argument is not provided.  The
+   function returns nothing.  */
+
+static PyObject *
+infpy_write_memory (PyObject *self, PyObject *args)
+{
+  int buf_len, error = 0;
+  const char *buffer;
+  CORE_ADDR addr, length;
+  PyObject *addr_obj, *length_obj = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "Os#|O", &addr_obj, &buffer, &buf_len,
+			  &length_obj))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr))
+	{
+	  error = 1;
+	  break;
+	}
+      
+      if (!length_obj)
+	length = buf_len;
+      else if (!get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      write_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    return NULL;
+
+  Py_RETURN_NONE;
+}
+
+/* Destructor of Membuf objects.  */
+
+static void
+mbpy_dealloc (PyObject *self)
+{
+  xfree (((membuf_object *) self)->buffer);
+  self->ob_type->tp_free (self);
+}
+
+/* Return a description of the Membuf object.  */
+
+static PyObject *
+mbpy_str (PyObject *self)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  return PyString_FromFormat ("memory buffer for address %s, %s bytes long",
+			      paddress (membuf_obj->addr),
+			      pulongest (membuf_obj->length));
+}
+
+static Py_ssize_t
+get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  if (segment)
+    {
+      PyErr_SetString (PyExc_SystemError,
+		       "The memory buffer supports only one segment.");
+      return -1;
+    }
+
+  *ptrptr = membuf_obj->buffer;
+
+  return membuf_obj->length;
+}
+
+static Py_ssize_t
+get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  return get_read_buffer (self, segment, ptrptr);
+}
+
+static Py_ssize_t
+get_seg_count (PyObject *self, Py_ssize_t *lenp)
+{
+  if (lenp)
+    *lenp = ((membuf_object *) self)->length;
+
+  return 1;
+}
+
+static Py_ssize_t
+get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
+{
+  void *ptr = NULL;
+  Py_ssize_t ret;
+
+  ret = get_read_buffer (self, segment, &ptr);
+  *ptrptr = (char *) ptr;
+
+  return ret;
+}
+
+/* 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.  */
+
+      Py_ssize_t 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 (address, length, pattern [, 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.  */
+
+static PyObject *
+infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
+{
+  int size = 0;
+  unsigned int found_count = 0;
+  long max_count = 0;
+  CORE_ADDR start_addr, length;
+  char *pattern_buf;
+  static char *keywords[] = { "address", "length", "pattern", "size",
+			      "max_count", NULL };
+  ULONGEST pattern_len, search_space_len;
+  PyObject *pattern, *list = NULL, *start_addr_obj, *length_obj;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO|il", keywords,
+				     &start_addr_obj, &length_obj, &pattern,
+				     &size, &max_count))
+    return NULL;
+
+  if (!max_count)
+    max_count = LONG_MAX;
+
+  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)
+	  && get_addr_from_python (length_obj, &length))
+	{
+	  if (!length)
+	    {
+	      PyErr_SetString (PyExc_ValueError, "empty search range");
+	      break;
+	    }
+	  /* Watch for overflows.  */
+	  else if (length > CORE_ADDR_MAX
+		   || (start_addr + length - 1) < start_addr)
+	    {
+	      PyErr_SetString (PyExc_ValueError, "search range too large");
+	      break;
+	    }
+
+	  search_space_len = length;
+
+	  if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len))
+	    {
+	      /* 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)
+		{
+		  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;
+		}
+
+	      do_cleanups (cleanups);
+	    }
+	}
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return list;
+}
+
+
+
 void
 gdbpy_initialize_inferior (void)
 {
@@ -366,6 +779,12 @@ gdbpy_initialize_inferior (void)
   observer_attach_inferior_exit (delete_inferior_object);
   observer_attach_new_thread (add_thread_object);
   observer_attach_thread_exit (delete_thread_object);
+
+  if (PyType_Ready (&membuf_object_type) < 0)
+    return;
+
+  Py_INCREF (&membuf_object_type);
+  PyModule_AddObject (gdb_module, "Membuf", (PyObject *) &membuf_object_type);
 }
 
 
@@ -386,6 +805,16 @@ static PyMethodDef inferior_object_methods[] =
   { "threads", infpy_threads, METH_NOARGS,
     "Return all the threads of this inferior." },
 
+  { "read_memory", infpy_read_memory, METH_VARARGS,
+    "read_memory (address, length) -> buffer\n\
+Return a buffer object for reading from the inferior's memory." },
+  { "write_memory", infpy_write_memory, METH_VARARGS,
+    "write_memory (address, buffer [, length])\n\
+Write the given buffer object to the inferior's memory." },
+  { "search_memory", (PyCFunction) infpy_search_memory, METH_VARARGS | METH_KEYWORDS,
+    "search_memory (address, length, pattern [, size] [, max_count]) -> list\n\
+Return a list with the addresses where matches were found." },
+
   { NULL }
 };
 
@@ -430,3 +859,63 @@ static PyTypeObject inferior_object_type =
   0,				  /* tp_init */
   0				  /* tp_alloc */
 };
+
+
+
+/* Python doesn't provide a decent way to get compatibility here.  */
+#if HAVE_LIBPYTHON2_4
+#define CHARBUFFERPROC_NAME getcharbufferproc
+#else
+#define CHARBUFFERPROC_NAME charbufferproc
+#endif
+
+static PyBufferProcs buffer_procs = {
+  get_read_buffer,
+  get_write_buffer,
+  get_seg_count,
+  /* The cast here works around a difference between Python 2.4 and
+     Python 2.5.  */
+  (CHARBUFFERPROC_NAME) get_char_buffer
+};
+
+static PyTypeObject membuf_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Membuf",			  /*tp_name*/
+  sizeof (membuf_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  mbpy_dealloc,			  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  mbpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  &buffer_procs,		  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "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 */
+};
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index afb0c51..29e55dd 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -91,8 +91,6 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
 PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
 PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args);
-PyObject *gdbpy_read_memory (PyObject *self, PyObject *args);
-PyObject *gdbpy_write_memory (PyObject *self, PyObject *args);
 PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2);
 PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
@@ -132,7 +130,6 @@ void gdbpy_initialize_objfile (void);
 void gdbpy_initialize_parameters (void);
 void gdbpy_initialize_thread (void);
 void gdbpy_initialize_inferior (void);
-void gdbpy_initialize_membuf (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index eddf7bf..e97bef8 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -312,234 +312,6 @@ gdbpy_solib_address (PyObject *self, PyObject *args)
   return str_obj;
 }
 
-/* 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.  */
-
-      Py_ssize_t 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 (address, length, pattern [, 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, PyObject *kw)
-{
-  int size = 0;
-  unsigned int found_count = 0;
-  long max_count = 0;
-  CORE_ADDR start_addr, length;
-  char *pattern_buf;
-  static char *keywords[] = { "address", "length", "pattern", "size",
-			      "max_count", NULL };
-  ULONGEST pattern_len, search_space_len;
-  PyObject *pattern, *list = NULL, *start_addr_obj, *length_obj;
-  volatile struct gdb_exception except;
-
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO|il", keywords,
-				     &start_addr_obj, &length_obj, &pattern,
-				     &size, &max_count))
-    return NULL;
-
-  if (!max_count)
-    max_count = LONG_MAX;
-
-  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)
-	  && get_addr_from_python (length_obj, &length))
-	{
-	  if (!length)
-	    {
-	      PyErr_SetString (PyExc_ValueError, "empty search range");
-	      break;
-	    }
-	  /* Watch for overflows.  */
-	  else if (length > CORE_ADDR_MAX
-		   || (start_addr + length - 1) < start_addr)
-	    {
-	      PyErr_SetString (PyExc_ValueError, "search range too large");
-	      break;
-	    }
-
-	  search_space_len = length;
-
-	  if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len))
-	    {
-	      /* 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)
-		{
-		  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;
-		}
-
-	      do_cleanups (cleanups);
-	    }
-	}
-    }
-  GDB_PY_HANDLE_EXCEPTION (except);
-
-  return list;
-}
-
 /* A Python function which is a wrapper for decode_line_1.  */
 
 static PyObject *
@@ -1687,7 +1459,6 @@ Enables or disables auto-loading of Python code when an object is opened."),
   gdbpy_initialize_thread ();
   gdbpy_initialize_inferior ();
   gdbpy_initialize_events ();
-  gdbpy_initialize_membuf ();
 
   PyRun_SimpleString ("import gdb");
   PyRun_SimpleString ("gdb.pretty_printers = []");
@@ -1810,16 +1581,6 @@ Return a tuple containing all inferiors." },
   { "post_event", gdbpy_post_event, METH_VARARGS,
     "Post an event into gdb's event loop." },
 
-  { "read_memory", gdbpy_read_memory, METH_VARARGS,
-    "read_memory (address, length) -> buffer\n\
-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", (PyCFunction) gdbpy_search_memory, METH_VARARGS | METH_KEYWORDS,
-    "search_memory (address, length, pattern [, 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." },
   { "flush", gdbpy_flush, METH_NOARGS,
diff --git a/gdb/testsuite/gdb.python/find.c b/gdb/testsuite/gdb.python/find.c
deleted file mode 100644
index 35ddd8c..0000000
--- a/gdb/testsuite/gdb.python/find.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* 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
deleted file mode 100644
index defc31c..0000000
--- a/gdb/testsuite/gdb.python/find.exp
+++ /dev/null
@@ -1,203 +0,0 @@
-# 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 search_buf = gdb.selected_frame ().read_var ('int8_search_buf')" "" ""
-gdb_test "py start_addr = search_buf.address" "" ""
-gdb_test "py length = search_buf.type.sizeof" "" ""
-
-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, with different parameter position
-
-gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], 1, 1)" \
-  "${one_pattern_found}" "size = 1, max_count = 1"
-
-gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], 1, 2)" \
-  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering"
-
-gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], size = 1, max_count = 2)" \
-  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering, with keywords"
-
-gdb_test "py print gdb.search_memory (start_addr, length, \[0x61, 0x61\], max_count = 2, size = 1)" \
-  "${two_patterns_found}" "size = 1, max_count = 2, inverted ordering"
-
-gdb_test "py print gdb.search_memory (start_addr, length, \['a', 'a'\], max_count = 2)" \
-  "${two_patterns_found}" "max_count = 2, with keyword"
-
-# Test 16-bit pattern.
-
-gdb_test "set int16_search_buf\[10\] = 0x1234" "" ""
-gdb_test "py search_buf = gdb.selected_frame ().read_var ('int16_search_buf')" "" ""
-gdb_test "py start_addr = search_buf.address" "" ""
-gdb_test "py length = search_buf.type.sizeof" "" ""
-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 search_buf = gdb.selected_frame ().read_var ('int32_search_buf')" "" ""
-gdb_test "py start_addr = search_buf.address" "" ""
-gdb_test "py length = search_buf.type.sizeof" "" ""
-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 search_buf = gdb.selected_frame ().read_var ('int64_search_buf')" "" ""
-gdb_test "py start_addr = search_buf.address" "" ""
-gdb_test "py length = search_buf.type.sizeof" "" ""
-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 search_buf = gdb.selected_frame ().read_var ('search_buf')" "" ""
-gdb_test "py start_addr = search_buf\[0\].address" "" ""
-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.selected_frame ().read_var ('search_buf')" "" ""
-gdb_test "py length = gdb.selected_frame ().read_var ('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/testsuite/gdb.python/python-inferior.c b/gdb/testsuite/gdb.python/python-inferior.c
index 22eb9f2..0b48299 100644
--- a/gdb/testsuite/gdb.python/python-inferior.c
+++ b/gdb/testsuite/gdb.python/python-inferior.c
@@ -1,5 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.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;
+
+
 int f2 (int a)
 {
+  char *str = "hello, testsuite";
+
+  puts (str);	/* Break here.  */
+
   return ++a;
 }
 
@@ -8,7 +31,19 @@ int f1 (int a, int b)
   return f2(a) + b;
 }
 
+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 (int argc, char *argv[])
 {
+  init_bufs ();
+
   return f1 (1, 2);
 }
diff --git a/gdb/testsuite/gdb.python/python-inferior.exp b/gdb/testsuite/gdb.python/python-inferior.exp
index e99aba4..2527dd9 100644
--- a/gdb/testsuite/gdb.python/python-inferior.exp
+++ b/gdb/testsuite/gdb.python/python-inferior.exp
@@ -39,6 +39,24 @@ proc gdb_py_test_silent_cmd {cmd name report_pass} {
   }
 }
 
+# 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
+}
+
 # Start with a fresh gdb.
 
 gdb_exit
@@ -61,9 +79,9 @@ if ![runto_main] then {
     return 0
 }
 
-gdb_breakpoint "f2"
-gdb_continue_to_breakpoint "breakpoint at f2"
-gdb_test "up" "" ""
+runto [gdb_get_line_number "Break here."]
+
+# Test basic gdb.Inferior attributes and methods.
 
 gdb_py_test_silent_cmd "python inferiors = gdb.inferiors ()" "get inferiors list" 1
 gdb_test "python print inferiors" "\\(<gdb.Inferior object at 0x\[\[:xdigit:\]\]+>,\\)" "verify inferiors list"
@@ -74,3 +92,140 @@ gdb_test "python print 'result =', i0.num" " = \[0-9\]+" "test Inferior.num"
 gdb_test "python print 'result =', i0.pid" " = \[0-9\]+" "test Inferior.pid"
 gdb_test "python print 'result =', i0.was_attached" " = False" "test Inferior.was_attached"
 gdb_test "python print i0.threads ()" "\\(<gdb.InferiorThread object at 0x\[\[:xdigit:\]\]+>,\\)" "test Inferior.threads"
+
+# Test memory read and write operations.
+
+gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \
+  "read str address" 0
+gdb_py_test_silent_cmd "python str = gdb.inferiors()\[0\].read_memory (addr, 5)" \
+  "read str contents" 1
+gdb_py_test_silent_cmd "python str\[1\] = 'a'" "change str" 0
+gdb_py_test_silent_cmd "python gdb.inferiors()\[0\].write_memory (addr, str)" \
+  "write str" 1
+gdb_test "print str" " = 0x\[\[:xdigit:\]\]+ \"hallo, testsuite\"" \
+  "ensure str was changed in the inferior"
+
+# Test memory search.
+
+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 search_buf = gdb.selected_frame ().read_var ('int8_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].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.inferiors()\[0\].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.inferiors()\[0\].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, with different parameter position
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], 1, 1)" \
+  "${one_pattern_found}" "size = 1, max_count = 1"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], 1, 2)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], size = 1, max_count = 2)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering, with keywords"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], max_count = 2, size = 1)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, inverted ordering"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \['a', 'a'\], max_count = 2)" \
+  "${two_patterns_found}" "max_count = 2, with keyword"
+
+# Test 16-bit pattern.
+
+gdb_test "set int16_search_buf\[10\] = 0x1234" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('int16_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int16_t) 0x1234')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0x1234, 2)" \
+  "${one_pattern_found}" "find 16-bit pattern, with python pattern"
+
+gdb_test "py print gdb.inferiors()\[0\].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 search_buf = gdb.selected_frame ().read_var ('int32_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int32_t) 0x12345678')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0x12345678, 4)" \
+  "${one_pattern_found}" "find 32-bit pattern, with python pattern"
+gdb_test "py print gdb.inferiors()\[0\].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 search_buf = gdb.selected_frame ().read_var ('int64_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int64_t) 0xfedcba9876543210LL')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0xfedcba9876543210, 8)" \
+  "${one_pattern_found}" "find 64-bit pattern, with python pattern"
+gdb_test "py print gdb.inferiors()\[0\].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 search_buf = gdb.selected_frame ().read_var ('search_buf')" "" ""
+gdb_test "py start_addr = search_buf\[0\].address" "" ""
+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.inferiors()\[0\].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.selected_frame ().read_var ('search_buf')" "" ""
+gdb_test "py length = gdb.selected_frame ().read_var ('search_buf_size')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].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.inferiors()\[0\].search_memory (start_addr, length, 0xfdb97531, 4)" \
+      "${one_pattern_found}" "find pattern straddling chunk boundary"
+}
diff --git a/gdb/testsuite/gdb.python/python-membuf.c b/gdb/testsuite/gdb.python/python-membuf.c
deleted file mode 100644
index 08c0789..0000000
--- a/gdb/testsuite/gdb.python/python-membuf.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-
-int
-main (int argc, char *argv[])
-{
-  char *str = "hello, testsuite";
-
-  puts (str);  /* Break here.  */
-
-  return 0;
-}
diff --git a/gdb/testsuite/gdb.python/python-membuf.exp b/gdb/testsuite/gdb.python/python-membuf.exp
deleted file mode 100644
index 46a79a7..0000000
--- a/gdb/testsuite/gdb.python/python-membuf.exp
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (C) 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 file is part of the GDB testsuite.  It tests the mechanism
-# for reading and writing inferior memory.
-
-if $tracelevel then {
-    strace $tracelevel
-}
-
-set testfile "python-membuf"
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
-    untested "Couldn't compile ${srcfile}"
-    return -1
-}
-
-# Run a command in GDB, and report a failure if a Python exception is thrown.
-# If report_pass is true, report a pass if no exception is thrown.
-proc gdb_py_test_silent_cmd {cmd name report_pass} {
-  global gdb_prompt
-
-  gdb_test_multiple $cmd $name {
-      -re "Traceback.*$gdb_prompt $"  { fail $name }
-      -re "$gdb_prompt $"	      { if $report_pass { pass $name } }
-  }
-}
-
-# Start with a fresh gdb.
-
-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 $"	{}
-}
-
-# The following tests require execution.
-
-if ![runto_main] then {
-    fail "Can't run to main"
-    return 0
-}
-
-runto [gdb_get_line_number "Break here."]
-
-gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" "read str address" 0
-gdb_py_test_silent_cmd "python str = gdb.read_memory (addr, 5)" "read str contents" 1
-gdb_py_test_silent_cmd "python str\[1\] = 'a'" "change str" 0
-gdb_py_test_silent_cmd "python gdb.write_memory (addr, str)" "write str" 1
-gdb_test "print str" " = 0x\[\[:xdigit:\]\]+ \"hallo, testsuite\"" "ensure str was changed in the inferior"



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]