diff options
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 20 | ||||
-rw-r--r-- | gdb/python/python.c | 144 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/python-sl.c | 26 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/python.c | 28 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/python.exp | 81 |
8 files changed, 317 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index de5e7220c60..e086deca3b1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2010-08-11 Phil Muldoon <pmuldoon@redhat.com> + Thiago Jung Bauermann <bauerman@br.ibm.com> + Tom Tromey <tromey@redhat.com> + + * python/python.c (gdbpy_solib_address): New function. + (gdbpy_decode_line): Likewise. + 2010-08-10 Tom Tromey <tromey@redhat.com> Revert gdb-add-index addition: diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 43ccbbec352..9cc366496ae 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2010-08-11 Phil Muldoon <pmuldoon@redhat.com> + + * gdb.texinfo (Basic Python): Describe solib_address and + decode_line Python APIs + 2010-08-10 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Pretty Printing API): Document diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c40c9317703..9851212a005 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20554,6 +20554,26 @@ Return the name of the current target wide character set never returned. @end defun +@findex gdb.solib_name +@defun solib_name address +Return the name of the shared library holding the given @var{address} +as a string, or @code{None}. +@end defun + +@findex gdb.decode_line +@defun decode_line @r{[}expression@r{]} +Return locations of the line specified by @var{expression}, or of the +current line if no argument was given. This function returns a Python +tuple containing two elements. The first element contains a string +holding any unparsed section of @var{expression} (or @code{None} if +the expression has been fully parsed). The second element contains +either @code{None} or another tuple that contains all the locations +that match the expression represented as @code{gdb.Symtab_and_line} +objects (@pxref{Symbol Tables In Python}). If @var{expression} is +provided, it is decoded the way that @value{GDBN}'s inbuilt +@code{break} or @code{edit} commands do (@pxref{Specify Location}). +@end defun + @node Exception Handling @subsubsection Exception Handling @cindex python exceptions diff --git a/gdb/python/python.c b/gdb/python/python.c index 7346fbaaeff..16c3cbaa979 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -42,7 +42,10 @@ static int gdbpy_should_print_stack = 1; #include "cli/cli-decode.h" #include "charset.h" #include "top.h" +#include "solib.h" #include "python-internal.h" +#include "linespec.h" +#include "source.h" #include "version.h" #include "target.h" #include "gdbthread.h" @@ -374,6 +377,137 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } +/* Implementation of gdb.solib_name (Long) -> String. + Returns the name of the shared library holding a given address, or None. */ + +static PyObject * +gdbpy_solib_name (PyObject *self, PyObject *args) +{ + char *soname; + PyObject *str_obj; +#ifdef PY_LONG_LONG + unsigned PY_LONG_LONG pc; + const char *format = "K"; +#else + unsigned long pc; + const char *format = "k"; +#endif + + if (!PyArg_ParseTuple (args, format, &pc)) + return NULL; + + soname = solib_name_from_address (current_program_space, pc); + if (soname) + str_obj = PyString_Decode (soname, strlen (soname), host_charset (), NULL); + else + { + str_obj = Py_None; + Py_INCREF (Py_None); + } + + return str_obj; +} + +/* A Python function which is a wrapper for decode_line_1. */ + +static PyObject * +gdbpy_decode_line (PyObject *self, PyObject *args) +{ + struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc. */ + struct symtab_and_line sal; + char *arg = NULL; + char *copy = NULL; + struct cleanup *cleanups; + PyObject *result = NULL; + PyObject *return_result = NULL; + PyObject *unparsed = NULL; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "|s", &arg)) + return NULL; + + cleanups = ensure_python_env (get_current_arch (), current_language); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (arg) + { + arg = xstrdup (arg); + make_cleanup (xfree, arg); + copy = arg; + sals = decode_line_1 (©, 0, 0, 0, 0, 0); + make_cleanup (xfree, sals.sals); + } + else + { + set_default_source_symtab_and_line (); + sal = get_current_source_symtab_and_line (); + sals.sals = &sal; + sals.nelts = 1; + } + } + if (except.reason < 0) + { + do_cleanups (cleanups); + /* We know this will always throw. */ + GDB_PY_HANDLE_EXCEPTION (except); + } + + if (sals.nelts) + { + int i; + + result = PyTuple_New (sals.nelts); + if (! result) + goto error; + for (i = 0; i < sals.nelts; ++i) + { + PyObject *obj; + char *str; + + obj = symtab_and_line_to_sal_object (sals.sals[i]); + if (! obj) + { + Py_DECREF (result); + goto error; + } + + PyTuple_SetItem (result, i, obj); + } + } + else + { + result = Py_None; + Py_INCREF (Py_None); + } + + return_result = PyTuple_New (2); + if (! return_result) + { + Py_DECREF (result); + goto error; + } + + if (copy && strlen (copy) > 0) + unparsed = PyString_FromString (copy); + else + { + unparsed = Py_None; + Py_INCREF (Py_None); + } + + PyTuple_SetItem (return_result, 0, unparsed); + PyTuple_SetItem (return_result, 1, result); + + do_cleanups (cleanups); + + return return_result; + + error: + do_cleanups (cleanups); + return NULL; +} + /* Parse a string and evaluate it as an expression. */ static PyObject * gdbpy_parse_and_eval (PyObject *self, PyObject *args) @@ -825,6 +959,16 @@ a boolean indicating if name is a field of the current implied argument\n\ `this' (when the current language is object-oriented)." }, { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, "Return the block containing the given pc value, or None." }, + { "solib_name", gdbpy_solib_name, METH_VARARGS, + "solib_name (Long) -> String.\n\ +Return the name of the shared library holding a given address, or None." }, + { "decode_line", gdbpy_decode_line, METH_VARARGS, + "decode_line (String) -> Tuple. Decode a string argument the way\n\ +that 'break' or 'edit' does. Return a tuple containing two elements.\n\ +The first element contains any unparsed portion of the String parameter\n\ +(or None if the string was fully parsed). The second element contains\n\ +a tuple that contains all the locations that match, represented as\n\ +gdb.Symtab_and_line objects (or None)."}, { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, "parse_and_eval (String) -> Value.\n\ Parse String as an expression, evaluate it, and return the result as a Value." diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 71680bce7a3..778d13e7c4b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-08-11 Phil Muldoon <pmuldoon@redhat.com> + + * gdb.python/python.c: New File. + * gdb.python/python-sl.c: New File. + * gdb.python/python.exp: Test solib_address and decode_line + * functions. + 2010-08-07 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.python/python.exp (show height, set height 10) diff --git a/gdb/testsuite/gdb.python/python-sl.c b/gdb/testsuite/gdb.python/python-sl.c new file mode 100644 index 00000000000..579a74e6e80 --- /dev/null +++ b/gdb/testsuite/gdb.python/python-sl.c @@ -0,0 +1,26 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 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/>. */ + +void func1 () +{ + return; +} + +int func2 () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.python/python.c b/gdb/testsuite/gdb.python/python.c new file mode 100644 index 00000000000..750a90a477c --- /dev/null +++ b/gdb/testsuite/gdb.python/python.c @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 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/>. */ + +/* Shared library function */ +extern void func1 (void); +extern int func2 (void); + +int +main (int argc, char *argv[]) +{ + func1 (); + func2 (); + return 0; /* Break to end. */ +} diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp index 7aef888b5b5..e153ab81f4a 100644 --- a/gdb/testsuite/gdb.python/python.exp +++ b/gdb/testsuite/gdb.python/python.exp @@ -20,12 +20,44 @@ if $tracelevel then { strace $tracelevel } -# Start with a fresh gdb. +set testfile "python" +set srcfile ${testfile}.c +set libfile "python-sl" +set libsrc ${libfile}.c +set library ${objdir}/${subdir}/${libfile}.sl +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile_shlib ${srcdir}/${subdir}/${libsrc} ${library} "debug"] != "" } { + untested "Could not compile shared library." + return -1 +} + +set exec_opts [list debug shlib=${library}] + +if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable $exec_opts] != "" } { + untested "Could not compile $binfile." + return -1 +} +# Start with a fresh gdb. gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +# 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 } } + } +} + gdb_test_multiple "python print 23" "verify python support" { -re "not supported.*$gdb_prompt $" { unsupported "python support is disabled" @@ -110,3 +142,50 @@ gdb_test_multiple "python print \"\\n\" * $lines" $test { } } gdb_test "q" "Quit" "verify pagination afterwards: q" + +# Start with a fresh gdb. +clean_restart ${testfile} + +# The following tests require execution. + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +runto [gdb_get_line_number "Break to end."] + +# Test gdb.decode_line. +gdb_test "python gdb.decode_line(\"main.c:43\")" \ + "RuntimeError: No source file named main.c.*" "test decode_line no source named main" + +gdb_py_test_silent_cmd "python symtab = gdb.decode_line()" "test decode_line current location" 1 +gdb_test "python print len(symtab)" "2" "Test decode_line current location" +gdb_test "python print symtab\[0\]" "None" "Test decode_line expression parse" +gdb_test "python print len(symtab\[1\])" "1" "Test decode_line current location" +gdb_test "python print symtab\[1\]\[0\].symtab" "gdb/testsuite/gdb.python/python.c.*" "Test decode_line current locationn filename" +gdb_test "python print symtab\[1\]\[0\].line" "22" "Test decode_line current location line number" + +gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"python.c:26 if foo\")" "test decode_line python.c:26" 1 +gdb_test "python print len(symtab)" "2" "Test decode_line python.c:26 length" +gdb_test "python print symtab\[0\]" "if foo" "Test decode_line expression parse" +gdb_test "python print len(symtab\[1\])" "1" "Test decode_line python.c:26 length" +gdb_test "python print symtab\[1\]\[0\].symtab" "gdb/testsuite/gdb.python/python.c.*" "Test decode_line python.c:26 filename" +gdb_test "python print symtab\[1\]\[0\].line" "26" "Test decode_line python.c:26 line number" + +gdb_test "python gdb.decode_line(\"randomfunc\")" \ + "RuntimeError: Function \"randomfunc\" not defined.*" "test decode_line randomfunc" +gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"func1\")" "test decode_line func1()" 1 +gdb_test "python print len(symtab)" "2" "Test decode_line func1 length" +gdb_test "python print len(symtab\[1\])" "1" "Test decode_line func1 length" +gdb_test "python print symtab\[1\]\[0\].symtab" "gdb/testsuite/gdb.python/python-sl.c.*" "Test decode_line func1 filename" +gdb_test "python print symtab\[1\]\[0\].line" "19" "Test decode_line func1 line number" + +# Test gdb.solib_name +gdb_test "p &func1" "" "func1 address" +gdb_py_test_silent_cmd "python func1 = gdb.history(0)" "Aquire func1 address" 1 +gdb_test "python print gdb.solib_name(long(func1))" "gdb/testsuite/gdb.python/python-sl.sl" "test func1 solib location" + +gdb_test "p &main" "" "main address" +gdb_py_test_silent_cmd "python main = gdb.history(0)" "Aquire main address" 1 +gdb_test "python print gdb.solib_name(long(main))" "None" "test main solib location" |