From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7795 invoked by alias); 28 Jul 2010 11:35:23 -0000 Received: (qmail 7784 invoked by uid 22791); 28 Jul 2010 11:35:21 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 28 Jul 2010 11:35:14 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6SBZ0TR025079 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 28 Jul 2010 07:35:00 -0400 Received: from Phil-THINK.home (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6SBYwi0029726; Wed, 28 Jul 2010 07:34:59 -0400 Message-ID: <4C5015E2.4000205@redhat.com> Date: Wed, 28 Jul 2010 11:35:00 -0000 From: Phil Muldoon User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100720 Fedora/3.1.1-1.fc13 Thunderbird/3.1.1 MIME-Version: 1.0 To: Joel Brobecker CC: gdb-patches ml Subject: Re: [patch] Add solib_address and decode_line Python functionality References: <4C44728D.4040408@redhat.com> <20100727162545.GF13267@adacore.com> In-Reply-To: <20100727162545.GF13267@adacore.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-07/txt/msg00473.txt.bz2 On 27/07/10 17:25, Joel Brobecker wrote: > Just my 2 cents on the API and doc... > >> solib_address -- lookup an address and if it resides in an solib >> reports that libs name, or None. > > IMO, the name that was chosen for this function implies the opposite > of what it does (it implies that it returns the solib (base?) address). > I would personally prefer solib_name or solib_name_from_address. Yeah, I agree (looking at it now). Attached a patch with the new name. >> +for Python commands (@pxref{Commands In Python}). The expected >> +format of @var{expression} is: > > ISTM that we would be better off not duplicating the various forms > a linespec can take. How about using a cross reference? Thanks, I added a cross reference to the documentation (As well as a few other edits, including a missing cross reference to gdb.Symtab_and_line). What do you think? Cheers, Phil -- diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index ba5ab75..404d372 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20532,6 +20532,22 @@ 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{]} +Decode the optional argument @var{expression} the way that +@value{GDBN}'s inbuilt 'break' or 'edit' commands do (@pxref{Specify +Location}). Return a Python tuple holding all the locations that +match the expression represented as @code{gdb.Symtab_and_line} objects +(@pxref{Symbol Tables In Python}), or @code{None}. If +@var{expression} is not provided, the current location is returned. +@end defun + @node Exception Handling @subsubsection Exception Handling @cindex python exceptions diff --git a/gdb/python/python.c b/gdb/python/python.c index 6680126..79179e3 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" @@ -413,6 +416,105 @@ 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) +{ + unsigned long long pc; + char *soname; + PyObject *str_obj; + + if (!PyArg_ParseTuple (args, "K", &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; + int free_sals = 0, i; + PyObject *result = NULL; + volatile struct gdb_exception except; + + if (! PyArg_ParseTuple (args, "|s", &arg)) + return NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (arg) + { + char *copy; + + arg = strdup (arg); + copy = arg; + + sals = decode_line_1 (©, 0, 0, 0, 0, 0); + free_sals = 1; + } + else + { + set_default_source_symtab_and_line (); + sal = get_current_source_symtab_and_line (); + sals.sals = &sal; + sals.nelts = 1; + } + } + if (arg) + xfree (arg); + + if (except.reason < 0) + { + if (free_sals) + xfree (sals.sals); + /* We know this will always throw. */ + GDB_PY_HANDLE_EXCEPTION (except); + } + + if (sals.nelts) + { + result = PyTuple_New (sals.nelts); + 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); + result = NULL; + break; + } + + PyTuple_SetItem (result, i, obj); + } + } + + if (free_sals) + xfree (sals.sals); + + if (result) + return result; + Py_RETURN_NONE; +} + /* Parse a string and evaluate it as an expression. */ static PyObject * gdbpy_parse_and_eval (PyObject *self, PyObject *args) @@ -864,6 +966,14 @@ 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 holding all the\n \ +locations that match, represented as gdb.Symtab_and_line objects\n\ +(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/gdb.python/python-sl.c b/gdb/testsuite/gdb.python/python-sl.c new file mode 100644 index 0000000..579a74e --- /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 . */ + +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 0000000..750a90a --- /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 . */ + +/* 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 d0e6c63..e1187bf 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" @@ -87,3 +119,46 @@ gdb_test "python import itertools; print 'IMPOR'+'TED'" "IMPORTED" "pythonX.Y/li gdb_test_no_output \ "python x = gdb.execute('printf \"%d\", 23', to_string = True)" gdb_test "python print x" "23" + +# 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)" "1*" "Test decode_line current location" +gdb_test "python print symtab\[0\].symtab" "gdb/testsuite/gdb.python/python.c.*" "Test decode_line current locationn filename" +gdb_test "python print symtab\[0\].line" "22" "Test decode_line current location line number" + +gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"python.c:26\")" "test decode_line python.c:26" 1 +gdb_test "python print len(symtab)" "1*" "Test decode_line python.c:26 length" +gdb_test "python print symtab\[0\].symtab" "gdb/testsuite/gdb.python/python.c.*" "Test decode_line python.c:26 filename" +gdb_test "python print symtab\[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)" "1*" "Test decode_line func1 length" +gdb_test "python print symtab\[0\].symtab" "gdb/testsuite/gdb.python/python-sl.c.*" "Test decode_line func1 filename" +gdb_test "python print symtab\[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"