This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
[python][commit] Have read_memory and write_memory properly readaddresses from Python.
- From: Thiago Jung Bauermann <bauerman at br dot ibm dot com>
- To: archer ml <archer at sourceware dot org>
- Date: Mon, 30 Mar 2009 18:30:00 -0300
- Subject: [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"