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] Have read_memory and write_memory properly readaddresses from Python.


Hi,

Tromey mentioned to me that gdb.read_memory didn't accept a gdb.Value
object as the address argument, and it should. I agree, and in fact
fixing this was in my TODO list for a while. I finally fixed it.

There's a function called get_addr_from_python in python-utils.c which
tries hard to get an address out of the given Python object. I changed
read_memory and write_memory to use them. While I was at it, I fixed a
bug I just found in search_memory, and created a testcase for
read_memory and write_memory.
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center


commit fbb87559bb19198db0265d0e4402639a6bb1191d
Author: Thiago Jung Bauermann <bauerman@br.ibm.com>
Date:   Mon Mar 30 18:00:46 2009 -0300

    Have read_memory and write_memory properly read addresses from Python.
    
    Also, fix bug in search_memory.
    
    gdb/
    	* python/python-membuf.c (gdbpy_read_memory): Use
    	get_addr_from_python.
    	(gdbpy_write_memory): Likewise.
    	(gdbpy_search_memory): Use get_addr_from_python to read length
    	as well.  Fix bug where start_addr was used before being set.
    
    gdb/testsuite/
    	* gdb.python/python-membuf.c: New file.
    	* gdb.python/python-membuf.exp: New file.

diff --git a/gdb/python/python-membuf.c b/gdb/python/python-membuf.c
index a4c7d74..d422d1c 100644
--- a/gdb/python/python-membuf.c
+++ b/gdb/python/python-membuf.c
@@ -40,14 +40,15 @@ static PyTypeObject membuf_object_type;
 PyObject *
 gdbpy_read_memory (PyObject *self, PyObject *args)
 {
+  int error = 0;
   CORE_ADDR addr, length;
   void *buffer;
   membuf_object *membuf_obj;
+  PyObject *addr_obj, *length_obj;
   struct cleanup *cleanups;
   volatile struct gdb_exception except;
 
-  /* Assume CORE_ADDR corresponds to unsigned long.  */
-  if (! PyArg_ParseTuple (args, "kk", &addr, &length))
+  if (! PyArg_ParseTuple (args, "OO", &addr_obj, &length_obj))
     return NULL;
 
   buffer = xmalloc (length);
@@ -55,10 +56,23 @@ gdbpy_read_memory (PyObject *self, PyObject *args)
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
+      if (!get_addr_from_python (addr_obj, &addr)
+	  || !get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
       read_memory (addr, buffer, length);
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
+  if (error)
+    {
+      do_cleanups (cleanups);
+      return NULL;
+    }
+
   discard_cleanups (cleanups);
 
   membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
@@ -71,11 +85,11 @@ gdbpy_read_memory (PyObject *self, PyObject *args)
     }
 
   membuf_obj->buffer = buffer;
-
   membuf_obj->addr = addr;
   membuf_obj->length = length;
 
-  return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0, Py_END_OF_BUFFER);
+  return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+				       Py_END_OF_BUFFER);
 }
 
 /* Implementation of gdb.write_memory (address, buffer [, length]).
@@ -87,25 +101,39 @@ gdbpy_read_memory (PyObject *self, PyObject *args)
 PyObject *
 gdbpy_write_memory (PyObject *self, PyObject *args)
 {
-  int buf_len;
+  int buf_len, error = 0;
   const char *buffer;
-  long length = -1;
-  CORE_ADDR addr;
+  CORE_ADDR addr, length;
+  PyObject *addr_obj, *length_obj = NULL;
   volatile struct gdb_exception except;
 
-  /* Assume CORE_ADDR corresponds to unsigned long.  */
-  if (! PyArg_ParseTuple (args, "ks#|l", &addr, &buffer, &buf_len, &length))
+  if (! PyArg_ParseTuple (args, "Os#|O", &addr_obj, &buffer, &buf_len,
+			  &length_obj))
     return NULL;
 
-  if (length == -1)
-    length = buf_len;
-
   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;
 }
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c94a252..3dbd47e 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -466,49 +466,24 @@ PyObject *
 gdbpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
 {
   int size = 0;
-  long length;
   unsigned int found_count = 0;
   long max_count = 0;
-  CORE_ADDR start_addr;
+  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;
+  PyObject *pattern, *list = NULL, *start_addr_obj, *length_obj;
   volatile struct gdb_exception except;
 
-  /* Assume CORE_ADDR corresponds to unsigned long.  */
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "OlO|il", keywords,
-				     &start_addr_obj, &length, &pattern,
+  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 (!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");
@@ -517,8 +492,24 @@ gdbpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      if (get_addr_from_python (start_addr_obj, &start_addr))
+      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.  */
diff --git a/gdb/testsuite/gdb.python/python-membuf.c b/gdb/testsuite/gdb.python/python-membuf.c
new file mode 100644
index 0000000..08c0789
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-membuf.c
@@ -0,0 +1,11 @@
+#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
new file mode 100644
index 0000000..46a79a7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/python-membuf.exp
@@ -0,0 +1,70 @@
+# 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]