From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29124 invoked by alias); 19 Jul 2010 15:43:25 -0000 Received: (qmail 29110 invoked by uid 22791); 19 Jul 2010 15:43:24 -0000 X-SWARE-Spam-Status: No, hits=-5.3 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; Mon, 19 Jul 2010 15:43:14 +0000 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6JFhCBA010784 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 19 Jul 2010 11:43:13 -0400 Received: from Phil-THINK.home (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6JFh9ba017234 for ; Mon, 19 Jul 2010 11:43:10 -0400 Message-ID: <4C44728D.4040408@redhat.com> Date: Mon, 19 Jul 2010 15:43:00 -0000 From: Phil Muldoon User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100621 Fedora/3.0.5-1.fc13 Thunderbird/3.0.5 MIME-Version: 1.0 To: gdb-patches ml Subject: [patch] Add solib_address and decode_line Python functionality 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/msg00287.txt.bz2 This patch imports the (last) two utility functions from archer (the other missing section from archer is the event posting code, but that is another email ...) These are general purpose utilities to make script hackers life a little easier. solib_address -- lookup an address and if it resides in an solib reports that libs name, or None. decode_line -- provide decode_line_1 like functionality. Useful for Python commands Tested on x8664 with no regressions. Comments? Cheers, Phil ChangeLog: 2010-07-19 Phil Muldoon Thiago Jung Bauermann Tom Tromey * python/python.c (gdbpy_solib_address): New function. (gdbpy_decode_line): Likewise. Documentation ChangeLog: 2010-07-19 Phil Muldoon * gdb.texinfo (Basic Python): Describe solib_address and decode_line Python APIs Testsuite ChangeLog: 2010-07-19 Phil Muldoon * gdb.python/python.c: New File. * gdb.python/python-sl.c: New File. * gdb.python/python.exp: Test solib_address and decode_line * functions. -- diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index ba5ab75..b75dc23 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20532,6 +20532,35 @@ Return the name of the current target wide character set never returned. @end defun +@findex gdb.solib_address +@defun solib_address 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. Return a Python +tuple holding all the locations that match the expression represented +as @code{gdb.Symtab_and_line} objects, or @code{None}. If +@var{expression} is not provided, the current location is returned. +This function is useful for decoding line, file and function arguments +for Python commands (@pxref{Commands In Python}). The expected +format of @var{expression} is: + +@table @code +@item FILE:LINENUM +A location indicated at that line in that file. +@item FUNCTION +A location at the beginning of that function. +@item FILE:FUNCTION +A location to distinguish among like-named static functions. +@item ADDRESS +A location containing that address. +@item VARIABLE +A location containing that variable. +@end table +@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..8a9a374 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_address (Long) -> String. + Returns the name of the shared library holding a given address, or None. */ + +static PyObject * +gdbpy_solib_address (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_address", gdbpy_solib_address, METH_VARARGS, + "solib_address (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..0d7b4bf 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_address +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_address(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_address(long(main))" "None" "test main solib location"