diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 374d113..2a3ae65 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19029,7 +19029,24 @@ can access its @code{foo} element with:
bar = some_val['foo']
@end smallexample
-Again, @code{bar} will also be a @code{gdb.Value} object.
+@code{bar} will be a @code{gdb.Value} object.
+
+Inferior values that represent a function or a function pointer can be
+called by supplying the arguments to the function in brackets, and
+calling the value in Python. For example, if @code{some_val} is a
+@code{gdb.Value} instance holding a function or function pointer that
+takes two integers as arguments, you may execute that function and
+store its return value, if any, like so:
+
+@smallexample
+result = some_val (10,20)
+@end smallexample
+
+Again, @code{result} will be a @code{gdb.Value} object.
+
+The arguments provided must match the function prototype of the
+function or the call will fail. Any errors generated from the
+inferior function call will be raised as an exception.
The following attributes are provided:
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 159c118..3a83e3f 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -25,6 +25,7 @@
#include "language.h"
#include "dfp.h"
#include "valprint.h"
+#include "infcall.h"
#ifdef HAVE_PYTHON
@@ -346,6 +347,48 @@ valpy_setitem (PyObject *self, PyObject *key, PyObject *value)
return -1;
}
+/* Called by the Python interpreter to perform an inferior function
+ call on the value in question. */
+static PyObject *
+valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
+{
+ struct value *return_value;
+ Py_ssize_t args_count;
+ volatile struct gdb_exception except;
+ struct value *function = ((value_object *) self)->value;
+ struct value **vargs = NULL;
+
+ args_count = PyTuple_Size (args);
+ if (args_count > 0)
+ {
+ int i;
+ vargs = alloca (sizeof (struct value *) * args_count);
+ for (i = 0; i < args_count; i++)
+ {
+ vargs[i] = convert_value_from_python (PyTuple_GetItem (args, i));
+ /* Check each argument converstion for any exceptions that
+ may have been raised during converstion. If any one
+ of the arguments raised an exception during converstion,
+ then the call should be aborted. */
+ if (PyErr_Occurred ())
+ {
+ PyErr_SetString (PyExc_RuntimeError,
+ _("An error was encountered while "
+ "converting an argument for an inferior "
+ "function call. Call aborted."));
+ return NULL;
+ }
+ }
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ return_value = call_function_by_hand (function, args_count, vargs);
+ }
+ GDB_PY_HANDLE_EXCEPTION (except);
+ return value_to_value_object (return_value);
+}
+
/* Called by the Python interpreter to obtain string representation
of the object. */
static PyObject *
@@ -1070,7 +1113,7 @@ PyTypeObject value_object_type = {
0, /*tp_as_sequence*/
&value_object_as_mapping, /*tp_as_mapping*/
0, /*tp_hash */
- 0, /*tp_call*/
+ (ternaryfunc)valpy_call, /*tp_call*/
valpy_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index adf66b5..8d69d25 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-prettyprint.c
@@ -16,6 +16,7 @@
along with this program. If not, see . */
#include
+#include
struct s
{
@@ -80,6 +81,26 @@ class Derived : public Vbase1, public Vbase2, public Vbase3
}
};
+class InferiorCall
+{
+ private:
+ int value;
+
+ public:
+ InferiorCall ()
+ {
+ value = 0;
+ }
+
+ int add (int i)
+ {
+ value += i; /* Inferior breakpoint here. */
+ if (value > 20)
+ raise (SIGABRT);
+
+ return value;
+ }
+};
#endif
typedef struct string_repr
@@ -200,7 +221,9 @@ main ()
SSS& ref (sss);
Derived derived;
-
+ InferiorCall inf;
+ inf.add (10);
+
#endif
add_item (&c, 23); /* MI breakpoint here */
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
index b2dc85d..24f06ad 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
@@ -76,6 +76,13 @@ proc run_lang_tests {lang} {
gdb_test "print derived" \
" = \{.* = pp class name: Vbase1.* = \{.* = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.* = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
+ gdb_test "print inf" "Total is: 20.*"
+ gdb_test "print inf" "RuntimeError: The program being debugged was signaled while in a function called from GDB.*"
+ runto [gdb_get_line_number "break to inspect"]
+ gdb_test "b [gdb_get_line_number {Inferior breakpoint here} ${testfile}.c ]" \
+ ".*Breakpoint.*"
+ gdb_test "print inf" "RuntimeError: The program being debugged stopped while in a function called from GDB.*"
+ runto [gdb_get_line_number "break to inspect"]
}
gdb_test "print x" " = $hex \"this is x\""
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index c3e0dc4..821317d 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-prettyprint.py
@@ -92,6 +92,13 @@ class pp_vbase1:
def to_string (self):
return "pp class name: " + self.val.type.tag
+class pp_inferiorcall:
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "Total is: %s" % (self.val['add'](self.val.address, 10))
+
class pp_nullstr:
def __init__(self, val):
self.val = val
@@ -156,6 +163,8 @@ def register_pretty_printers ():
pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual
pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1
+ pretty_printers_dict[re.compile ('^InferiorCall$')] = pp_inferiorcall
+
pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr
pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr
diff --git a/gdb/testsuite/gdb.python/python-value.c b/gdb/testsuite/gdb.python/python-value.c
index f3d6284..bc3fb24 100644
--- a/gdb/testsuite/gdb.python/python-value.c
+++ b/gdb/testsuite/gdb.python/python-value.c
@@ -15,6 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
+#include
+
struct s
{
int a;
@@ -37,6 +39,16 @@ typedef struct s *PTR;
enum e evalue = TWO;
+void func1 ()
+{
+ printf ("void function called\n");
+}
+
+int func2 (int arg1, int arg2)
+{
+ return arg1 + arg2;
+}
+
int
main (int argc, char *argv[])
{
@@ -46,10 +58,13 @@ main (int argc, char *argv[])
PTR x = &s;
char st[17] = "divide et impera";
char nullst[17] = "divide\0et\0impera";
+ void (*fp1) (void) = &func1;
+ int (*fp2) (int, int) = &func2;
s.a = 3;
s.b = 5;
u.a = 7;
-
+ (*fp1) ();
+ (*fp2) (10,20);
return 0; /* break to inspect struct and union */
}
diff --git a/gdb/testsuite/gdb.python/python-value.exp b/gdb/testsuite/gdb.python/python-value.exp
index ccf438f..30aae27 100644
--- a/gdb/testsuite/gdb.python/python-value.exp
+++ b/gdb/testsuite/gdb.python/python-value.exp
@@ -218,6 +218,18 @@ proc test_value_in_inferior {} {
gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
}
+proc test_inferior_function_call {} {
+ global gdb_prompt hex
+ gdb_test "p/x fp1" " = $hex.*"
+ gdb_py_test_silent_cmd "python fp1 = gdb.history (0)" "get value from history" 1
+ gdb_test "python result = fp1()" ""
+ gdb_test "python print result" "void"
+ gdb_test "p/x fp2" " = $hex.*"
+ gdb_py_test_silent_cmd "python fp2 = gdb.history (0)" "get value from history" 1
+ gdb_test "python result2 = fp2(10,20)" ""
+ gdb_test "python print result2" "30"
+}
+
# A few objfile tests.
proc test_objfiles {} {
gdb_test "python\nok=False\nfor file in gdb.objfiles():\n if 'python-value' in file.filename:\n ok=True\nprint ok\nend" "True"
@@ -300,5 +312,6 @@ if ![runto_main] then {
}
test_value_in_inferior
+test_inferior_function_call
test_value_after_death
test_cast_regression