2008-10-16 Thiago Jung Bauermann <bauerman@br.ibm.com>

Tom Tromey  <tromey@redhat.com>

gdb/
	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-value.o.
	(SUBDIR_PYTHON_SRCS): Add python-value.c.
	(python-value.o): New target.
	* configure.ac (CONFIG_OBS): Add python-value.o.
	(CONFIG_SRCS): Add python/python-value.c
	* configure: Regenerate.
	* python-internal.h (value_object_type): Add external declaration.
	(gdbpy_get_value_from_history, value_to_value_object,
	convert_value_from_python, gdbpy_initialize_values): Add function
	prototype.
	* python/python-value.c: New file.
	* python/python.c (GdbMethods): Add gdbpy_get_value_from_history.
	(_initialize_python): Call gdbpy_initialize_values.
	* python/python.h (values_in_python): Add external declaration.
	* value.c (value_prepend_to_list, value_remove_from_list): New
	functions.
	(preserve_values): Iterate over values_in_python list as well.
	* value.h (value_prepend_to_list, value_remove_from_list): Add
	function prototypes.

gdb/doc/
	* gdb.texinfo. (Values From Inferior): New subsubsection.

gdb/testsuite/
	* gdb.python/python-value.c: New file.
	* gdb.python/python-value.exp: New file.
This commit is contained in:
Thiago Jung Bauermann
2008-10-16 03:54:00 +00:00
parent eff85da5fb
commit a08702d647
13 changed files with 430 additions and 15 deletions

View File

@@ -271,10 +271,12 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
python-utils.o
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
python/python-utils.c
python/python-utils.c \
python/python-value.c
SUBDIR_PYTHON_DEPS =
SUBDIR_PYTHON_LDFLAGS=
SUBDIR_PYTHON_CFLAGS=
@@ -1836,6 +1838,10 @@ python-utils.o: $(srcdir)/python/python-utils.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
$(POSTCOMPILE)
python-value.o: $(srcdir)/python/python-value.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-value.c
$(POSTCOMPILE)
#
# Dependency tracking. Most of this is conditional on GNU Make being
# found by configure; if GNU Make is not found, we fall back to a

6
gdb/configure vendored
View File

@@ -11704,10 +11704,10 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "${ECHO_T}${PYTHON_CFLAGS}" >&6
fi
else
# Even if Python support is not compiled in, we need to have this file
# Even if Python support is not compiled in, we need to have these files
# included in order to recognize the GDB command "python".
CONFIG_OBS="$CONFIG_OBS python.o"
CONFIG_SRCS="$CONFIG_SRCS python/python.c"
CONFIG_OBS="$CONFIG_OBS python.o python-value.o"
CONFIG_SRCS="$CONFIG_SRCS python/python.c python/python-value.c"
fi

View File

@@ -624,10 +624,10 @@ if test "${have_libpython}" = yes; then
AC_MSG_RESULT(${PYTHON_CFLAGS})
fi
else
# Even if Python support is not compiled in, we need to have this file
# Even if Python support is not compiled in, we need to have these files
# included in order to recognize the GDB command "python".
CONFIG_OBS="$CONFIG_OBS python.o"
CONFIG_SRCS="$CONFIG_SRCS python/python.c"
CONFIG_OBS="$CONFIG_OBS python.o python-value.o"
CONFIG_SRCS="$CONFIG_SRCS python/python.c python/python-value.c"
fi
AC_SUBST(PYTHON_CFLAGS)

View File

@@ -1,3 +1,7 @@
2008-10-16 Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.texinfo. (Values From Inferior): New subsubsection.
2008-10-06 Doug Evans <dje@google.com>
* gdb.texinfo (set debug dwarf2-die): Document it.

View File

@@ -17690,6 +17690,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
@menu
* Basic Python:: Basic Python Functions.
* Exception Handling::
* Values From Inferior::
@end menu
@node Basic Python
@@ -17768,6 +17769,64 @@ message as its value, and the Python call stack backtrace at the
Python statement closest to where the @value{GDBN} error occured as the
traceback.
@node Values From Inferior
@subsubsection Values From Inferior
@cindex values from inferior, with Python
@cindex python, working with values from inferior
@cindex @code{gdb.Value}
@value{GDBN} provides values it obtains from the inferior program in
an object of type @code{gdb.Value}. @value{GDBN} uses this object
for its internal bookkeeping of the inferior's values, and for
fetching values when necessary.
Inferior values that are simple scalars can be used directly in
Python expressions that are valid for the value's data type. Here's
an example for an integer or floating-point value @code{some_val}:
@smallexample
bar = some_val + 2
@end smallexample
@noindent
As result of this, @code{bar} will also be a @code{gdb.Value} object
whose values are of the same type as those of @code{some_val}.
Inferior values that are structures or instances of some class can
be accessed using the Python @dfn{dictionary syntax}. For example, if
@code{some_val} is a @code{gdb.Value} instance holding a structure, you
can access its @code{foo} element with:
@smallexample
bar = some_val['foo']
@end smallexample
Again, @code{bar} will also be a @code{gdb.Value} object.
For pointer data types, @code{gdb.Value} provides a method for
dereferencing the pointer to obtain the object it points to.
@defmethod Value dereference
This method returns a new @code{gdb.Value} object whose contents is
the object pointed to by the pointer. For example, if @code{foo} is
a C pointer to an @code{int}, declared in your C program as
@smallexample
int *foo;
@end smallexample
@noindent
then you can use the corresponding @code{gdb.Value} to access what
@code{foo} points to like this:
@smallexample
bar = foo.dereference ()
@end smallexample
The result @code{bar} will be a @code{gdb.Value} object holding the
value pointed to by @code{foo}.
@end defmethod
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters

View File

@@ -43,11 +43,18 @@ typedef Py_intptr_t Py_ssize_t;
#error "Unable to find usable Python.h"
#endif
struct block;
struct symbol;
struct symtab_and_line;
struct value;
extern PyObject *gdb_module;
extern PyTypeObject value_object_type;
PyObject *gdbpy_get_value_from_history (PyObject *self, PyObject *args);
PyObject *value_to_value_object (struct value *v);
struct value *convert_value_from_python (PyObject *obj);
void gdbpy_initialize_values (void);
struct cleanup *make_cleanup_py_decref (PyObject *py);

View File

@@ -52,6 +52,8 @@ static PyObject *gdbpy_flush (PyObject *, PyObject *);
static PyMethodDef GdbMethods[] =
{
{ "get_value_from_history", gdbpy_get_value_from_history, METH_VARARGS,
"Get a value from history" },
{ "execute", execute_gdb_command, METH_VARARGS,
"Execute a gdb command" },
{ "get_parameter", get_parameter, METH_VARARGS,
@@ -398,6 +400,8 @@ Enables or disables printing of Python stack traces."),
PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
gdbpy_initialize_values ();
PyRun_SimpleString ("import gdb");
/* Create a couple objects which are used for Python's stdout and

View File

@@ -22,6 +22,8 @@
#include "value.h"
extern struct value *values_in_python;
void eval_python_from_control_command (struct command_line *);
#endif /* GDB_PYTHON_H */

View File

@@ -1,3 +1,8 @@
2008-10-16 Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-value.c: New file.
* gdb.python/python-value.exp: New file.
2008-10-15 Pedro Alves <pedro@codesourcery.com>
* gdb.mi/mi-nsmoribund.exp, gdb.mi/nsmoribund.c: New test.

View File

@@ -0,0 +1,41 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2008 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/>. */
struct s
{
int a;
int b;
};
union u
{
int a;
float b;
};
int
main (int argc, char *argv[])
{
struct s s;
union u u;
s.a = 3;
s.b = 5;
u.a = 7;
return 0; /* break to inspect struct and union */
}

View File

@@ -0,0 +1,250 @@
# Copyright (C) 2008 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
# exposing values to Python.
if $tracelevel then {
strace $tracelevel
}
set testfile "python-value"
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
}
# 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
}
# 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 } }
}
}
proc test_value_creation {} {
global gdb_prompt
gdb_py_test_silent_cmd "python i = gdb.Value (True)" "create boolean value" 1
gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create integer value" 1
gdb_py_test_silent_cmd "python i = gdb.Value (5L)" "create long value" 1
gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create double value" 1
gdb_py_test_silent_cmd "python a = gdb.Value ('string test')" "create 8-bit string value" 1
gdb_test "python print a" "\"string test\"" "print 8-bit string"
gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of 8-bit string"
gdb_py_test_silent_cmd "python a = gdb.Value (u'unicode test')" "create unicode value" 1
gdb_test "python print a" "\"unicode test\"" "print Unicode string"
gdb_test "python print a.__class__" "<type 'gdb.Value'>" "verify type of unicode string"
}
proc test_value_numeric_ops {} {
global gdb_prompt
gdb_py_test_silent_cmd "python i = gdb.Value (5)" "create first integer value" 0
gdb_py_test_silent_cmd "python j = gdb.Value (2)" "create second integer value" 0
gdb_py_test_silent_cmd "python f = gdb.Value (1.25)" "create first double value" 0
gdb_py_test_silent_cmd "python g = gdb.Value (2.5)" "create second double value" 0
gdb_test "python print 'result = ' + str(i+j)" " = 7" "add two integer values"
gdb_test "python print (i+j).__class__" "<type 'gdb.Value'>" "verify type of integer add result"
gdb_test "python print 'result = ' + str(f+g)" " = 3.75" "add two double values"
gdb_test "python print 'result = ' + str(i-j)" " = 3" "subtract two integer values"
gdb_test "python print 'result = ' + str(f-g)" " = -1.25" "subtract two double values"
gdb_test "python print 'result = ' + str(i*j)" " = 10" "multiply two integer values"
gdb_test "python print 'result = ' + str(f*g)" " = 3.125" "multiply two double values"
gdb_test "python print 'result = ' + str(i/j)" " = 2" "divide two integer values"
gdb_test "python print 'result = ' + str(f/g)" " = 0.5" "divide two double values"
gdb_test "python print 'result = ' + str(i%j)" " = 1" "take remainder of two integer values"
# Remainder of float is implemented in Python but not in GDB's value system.
gdb_test "python print 'result = ' + str(i**j)" " = 25" "integer value raised to the power of another integer value"
gdb_test "python print 'result = ' + str(g**j)" " = 6.25" "double value raised to the power of integer value"
gdb_test "python print 'result = ' + str(-i)" " = -5" "negated integer value"
gdb_test "python print 'result = ' + str(+i)" " = 5" "positive integer value"
gdb_test "python print 'result = ' + str(-f)" " = -1.25" "negated double value"
gdb_test "python print 'result = ' + str(+f)" " = 1.25" "positive double value"
gdb_test "python print 'result = ' + str(abs(j-i))" " = 3" "absolute of integer value"
gdb_test "python print 'result = ' + str(abs(f-g))" " = 1.25" "absolute of double value"
# Test gdb.Value mixed with Python types.
gdb_test "python print 'result = ' + str(i-1)" " = 4" "subtract integer value from python integer"
gdb_test "python print (i-1).__class__" "<type 'gdb.Value'>" "verify type of mixed integer subtraction result"
gdb_test "python print 'result = ' + str(f+1.5)" " = 2.75" "add double value with python float"
gdb_test "python print 'result = ' + str(1-i)" " = -4" "subtract python integer from integer value"
gdb_test "python print 'result = ' + str(1.5+f)" " = 2.75" "add python float with double value"
# Test pointer arithmethic
# First, obtain the pointers
gdb_test "print (void *) 2" "" ""
gdb_test "python a = gdb.get_value_from_history (0)" "" ""
gdb_test "print (void *) 5" "" ""
gdb_test "python b = gdb.get_value_from_history (0)" "" ""
gdb_test "python print 'result = ' + str(a+5)" " = 0x7" "add pointer value with python integer"
gdb_test "python print 'result = ' + str(b-2)" " = 0x3" "subtract python integer from pointer value"
gdb_test "python print 'result = ' + str(b-a)" " = 3" "subtract two pointer values"
# Test some invalid operations.
gdb_test_multiple "python print 'result = ' + str(i+'foo')" "catch error in python type conversion" {
-re "Argument to arithmetic operation not a number or boolean.*$gdb_prompt $" {pass "catch error in python type conversion"}
-re "result = .*$gdb_prompt $" {fail "catch error in python type conversion"}
-re "$gdb_prompt $" {fail "catch error in python type conversion"}
}
gdb_test_multiple "python print 'result = ' + str(i+gdb.Value('foo'))" "catch throw of GDB error" {
-re "Traceback.*$gdb_prompt $" {pass "catch throw of GDB error"}
-re "result = .*$gdb_prompt $" {fail "catch throw of GDB error"}
-re "$gdb_prompt $" {fail "catch throw of GDB error"}
}
}
proc test_value_boolean {} {
# First, define a useful function to test booleans.
gdb_py_test_multiple "define function to test booleans" \
"python" "" \
"def test_bool (val):" "" \
" if val:" "" \
" print 'yay'" "" \
" else:" "" \
" print 'nay'" "" \
"end" ""
gdb_test "py test_bool (gdb.Value (True))" "yay" "check evaluation of true boolean value in expression"
gdb_test "py test_bool (gdb.Value (False))" "nay" "check evaluation of false boolean value in expression"
gdb_test "py test_bool (gdb.Value (5))" "yay" "check evaluation of true integer value in expression"
gdb_test "py test_bool (gdb.Value (0))" "nay" "check evaluation of false integer value in expression"
gdb_test "py test_bool (gdb.Value (5.2))" "yay" "check evaluation of true integer value in expression"
gdb_test "py test_bool (gdb.Value (0.0))" "nay" "check evaluation of false integer value in expression"
}
proc test_value_compare {} {
gdb_test "py print gdb.Value (1) < gdb.Value (1)" "False" "less than, equal"
gdb_test "py print gdb.Value (1) < gdb.Value (2)" "True" "less than, less"
gdb_test "py print gdb.Value (2) < gdb.Value (1)" "False" "less than, greater"
gdb_test "py print gdb.Value (2) < None" "False" "less than, None"
gdb_test "py print gdb.Value (1) <= gdb.Value (1)" "True" "less or equal, equal"
gdb_test "py print gdb.Value (1) <= gdb.Value (2)" "True" "less or equal, less"
gdb_test "py print gdb.Value (2) <= gdb.Value (1)" "False" "less or equal, greater"
gdb_test "py print gdb.Value (2) <= None" "False" "less or equal, None"
gdb_test "py print gdb.Value (1) == gdb.Value (1)" "True" "equality of gdb.Values"
gdb_test "py print gdb.Value (1) == gdb.Value (2)" "False" "inequality of gdb.Values"
gdb_test "py print gdb.Value (1) == 1.0" "True" "equality of gdb.Value with Python value"
gdb_test "py print gdb.Value (1) == 2" "False" "inequality of gdb.Value with Python value"
gdb_test "py print gdb.Value (1) == None" "False" "inequality of gdb.Value with None"
gdb_test "py print gdb.Value (1) != gdb.Value (1)" "False" "inequality, false"
gdb_test "py print gdb.Value (1) != gdb.Value (2)" "True" "inequality, true"
gdb_test "py print gdb.Value (1) != None" "True" "inequality, None"
gdb_test "py print gdb.Value (1) > gdb.Value (1)" "False" "greater than, equal"
gdb_test "py print gdb.Value (1) > gdb.Value (2)" "False" "greater than, less"
gdb_test "py print gdb.Value (2) > gdb.Value (1)" "True" "greater than, greater"
gdb_test "py print gdb.Value (2) > None" "True" "greater than, None"
gdb_test "py print gdb.Value (1) >= gdb.Value (1)" "True" "greater or equal, equal"
gdb_test "py print gdb.Value (1) >= gdb.Value (2)" "False" "greater or equal, less"
gdb_test "py print gdb.Value (2) >= gdb.Value (1)" "True" "greater or equal, greater"
gdb_test "py print gdb.Value (2) >= None" "True" "greater or equal, None"
}
proc test_value_in_inferior {} {
global gdb_prompt
global testfile
gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"]
gdb_start_cmd
# Avoid race condition where a continue command in gdb_continue_to_breakpoint
# is issued too early.
gdb_test "" "$gdb_prompt"
gdb_continue_to_breakpoint "break to inspect struct and union"
# Just get inferior variable s in the value history, available to python.
gdb_test "print s" " = {a = 3, b = 5}" ""
gdb_py_test_silent_cmd "python s = gdb.get_value_from_history (0)" "get value from history" 1
gdb_test "python print 'result = ' + str(s\['a'\])" " = 3" "access element inside struct using 8-bit string name"
gdb_test "python print 'result = ' + str(s\[u'a'\])" " = 3" "access element inside struct using unicode name"
# Test dereferencing the argv pointer
# Just get inferior variable argv the value history, available to python.
gdb_test "print argv" " = \\(char \\*\\*\\) 0x.*" ""
gdb_py_test_silent_cmd "python argv = gdb.get_value_from_history (0)" "" 0
gdb_py_test_silent_cmd "python arg0 = argv.dereference ()" "dereference value" 1
# Check that the dereferenced value is sane
gdb_test "python print arg0" "0x.*$testfile\"" "verify dereferenced value"
}
# 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 $" {}
}
test_value_creation
test_value_numeric_ops
test_value_boolean
test_value_compare
test_value_in_inferior

View File

@@ -37,6 +37,8 @@
#include "dfp.h"
#include "objfiles.h"
#include "python/python.h"
/* Prototypes for exported functions. */
void _initialize_values (void);
@@ -130,8 +132,8 @@ struct value
/* Values are stored in a chain, so that they can be deleted easily
over calls to the inferior. Values assigned to internal
variables or put into the value history are taken off this
list. */
variables, put into the value history or exposed to Python are
taken off this list. */
struct value *next;
/* Register number if the value is from a register. */
@@ -257,6 +259,31 @@ allocate_repeat_value (struct type *type, int count)
type, range_type));
}
/* Needed if another module needs to maintain its on list of values. */
void
value_prepend_to_list (struct value **head, struct value *val)
{
val->next = *head;
*head = val;
}
/* Needed if another module needs to maintain its on list of values. */
void
value_remove_from_list (struct value **head, struct value *val)
{
struct value *prev;
if (*head == val)
*head = (*head)->next;
else
for (prev = *head; prev->next; prev = prev->next)
if (prev->next == val)
{
prev->next = val->next;
break;
}
}
/* Accessor methods. */
struct value *
@@ -916,6 +943,7 @@ preserve_values (struct objfile *objfile)
htab_t copied_types;
struct value_history_chunk *cur;
struct internalvar *var;
struct value *val;
int i;
/* Create the hash table. We allocate on the objfile's obstack, since
@@ -930,6 +958,9 @@ preserve_values (struct objfile *objfile)
for (var = internalvars; var; var = var->next)
preserve_one_value (var->value, objfile, copied_types);
for (val = values_in_python; val; val = val->next)
preserve_one_value (val, objfile, copied_types);
htab_delete (copied_types);
}

View File

@@ -40,9 +40,15 @@ struct language_defn;
struct value;
/* Needed if another module needs to maintain its own list of values. */
void value_prepend_to_list (struct value **head, struct value *val);
void value_remove_from_list (struct value **head, struct value *val);
/* Values are stored in a chain, so that they can be deleted easily
over calls to the inferior. Values assigned to internal variables
or put into the value history are taken off this list. */
over calls to the inferior. Values assigned to internal variables,
put into the value history or exposed to Python are taken off this
list. */
struct value *value_next (struct value *);