From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14884 invoked by alias); 1 Feb 2010 13:42:48 -0000 Received: (qmail 14840 invoked by uid 22791); 1 Feb 2010 13:42:33 -0000 X-SWARE-Spam-Status: No, hits=-0.5 required=5.0 tests=AWL,BAYES_50,KAM_STOCKGEN,SPF_HELO_PASS,SPF_PASS 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, 01 Feb 2010 13:42:17 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o11DgFnU029632 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 1 Feb 2010 08:42:15 -0500 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o11DgDlA018018 for ; Mon, 1 Feb 2010 08:42:14 -0500 Message-ID: <4B66DA35.7080701@redhat.com> Date: Mon, 01 Feb 2010 13:42:00 -0000 From: Phil Muldoon User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7) Gecko/20100120 Fedora/3.0.1-1.fc12 Lightning/1.0b2pre Thunderbird/3.0.1 MIME-Version: 1.0 To: gdb-patches ml Subject: [patch][python] Add symbol, symbol table and frame block support to GDB API 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-02/txt/msg00012.txt.bz2 This patch adds symbol, symbol table and block support to the Python GDB API. It also reconstitutes several functions missing from py-frame, and adds the glue back into python.c to make these code segments work together. This is for the most part a merge of the code that has existed in the archer repository for sometime. OK? Regards -- ChangeLog 2010-02-01 Phil Muldoon Tom Tromey Thiago Jung Bauermann * python/python.c (_initialize_python): Call gdbpy_initialize_symtabs, gdbpy_initialize_symbols and gdbpy_initialize_blocks. * python/python-internal.h: Declare struct symbol, block and symtab_and_line. Declare block_object_type and symbol_object_type (gdbpy_lookup_symbol gdbpy_block_for_pc) (symtab_and_line_to_sal_object, symtab_to_symtab_object) (symbol_to_symbol_object, block_to_block_object) (gdbpy_initialize_symtabs,gdbpy_initialize_symbols) (gdbpy_initialize_blocks ): Declare. * python/py-frame.c (frapy_block, frapy_function, frapy_find_sal) (frapy_select): Add methods. (frapy_read_var): Add symbol branch. * Makefile.in (SUBDIR_PYTHON_OBS): Add py-symbol, py-symtab, py-block. (SUBDIR_PYTHON_SRCS): Likewise. (py-symbol.o): New rule. (py-symtab.o): Likewise. (py-block.o): Likewise. * python/py-symbol.c: New file. * python/py-symtab.c: Likewise. * python/py-block.c: Likewise. doc/Changelog 2010-02-01 Phil Muldoon * gdb.texinfo (Frames In Python): Add block, find_sal, function and select method descriptions. (Python API): Add Blocks In Python, Symbols in Python and Symbol Tables in Python to menu. (Blocks In Python): New node. (Symbols In Python): New node. (Symbol Tables in Python): New node. testsuite/ChangeLog 2010-02-01 Phil Muldoon * Makefile.in: Add py-block and py-symbol. * gdb.python/py-symbol.exp: New File. * gdb.python/py-symtab.exp: New File. * gdb.python/py-block.exp: New File. * gdb.python/py-symbol.c: New File. * gdb.python/py-block.c: New File. -- diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ff8b86e..453f88c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -267,23 +267,29 @@ SUBDIR_TUI_CFLAGS= \ # SUBDIR_PYTHON_OBS = \ python.o \ + py-block.o \ py-cmd.o \ py-frame.o \ py-function.o \ py-lazy-string.o \ py-objfile.o \ py-prettyprint.o \ + py-symbol.o \ + py-symtab.o \ py-type.o \ py-utils.o \ py-value.o SUBDIR_PYTHON_SRCS = \ python/python.c \ + python/py-block.c \ python/py-cmd.c \ python/py-frame.c \ python/py-function.c \ python/py-lazy-string.c \ python/py-objfile.c \ python/py-prettyprint.c \ + python/py-symbol.c \ + python/py-symtab.c \ python/py-type.c \ python/py-utils.c \ python/py-value.c @@ -1970,6 +1976,10 @@ python.o: $(srcdir)/python/python.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python.c $(POSTCOMPILE) +py-block.o: $(srcdir)/python/py-block.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c + $(POSTCOMPILE) + py-cmd.o: $(srcdir)/python/py-cmd.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c $(POSTCOMPILE) @@ -1994,6 +2004,14 @@ py-prettyprint.o: $(srcdir)/python/py-prettyprint.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-prettyprint.c $(POSTCOMPILE) +py-symbol.o: $(srcdir)/python/py-symbol.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symbol.c + $(POSTCOMPILE) + +py-symtab.o: $(srcdir)/python/py-symtab.c + $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symtab.c + $(POSTCOMPILE) + py-type.o: $(srcdir)/python/py-type.c $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-type.c $(POSTCOMPILE) diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fc11609..268a011 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -19538,7 +19538,10 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. * Commands In Python:: Implementing new commands in Python. * Functions In Python:: Writing new convenience functions. * Objfiles In Python:: Object files. -* Frames In Python:: Acessing inferior stack frames from Python. +* Frames In Python:: Accessing inferior stack frames from Python. +* Blocks In Python:: Accessing frame blocks from Python. +* Symbols In Python:: Python representation of Symbols. +* Symbol Tables In Python:: Symbol table representation in Python. * Lazy Strings In Python:: Python representation of lazy strings. @end menu @@ -20698,7 +20701,7 @@ information. @end defivar @node Frames In Python -@subsubsection Acessing inferior stack frames from Python. +@subsubsection Accessing inferior stack frames from Python. @cindex frames in python When the debugged program stops, @value{GDBN} is able to analyze its call @@ -20761,6 +20764,15 @@ function to a string. Returns the frame's resume address. @end defmethod +@defmethod Frame block +Returns the frame's code block. (@pxref{Blocks In Python}). +@end defmethod + +@defmethod Frame function +Returns the symbol for the function corresponding to this frame. +(@pxref{Symbols In Python}). +@end defmethod + @defmethod Frame older Return the frame that called this frame. @end defmethod @@ -20769,10 +20781,310 @@ Return the frame that called this frame. Return the frame called by this frame. @end defmethod +@defmethod Frame find_sal +Return the frame's symtab and line object. +(@pxref{Symbol Tables In Python}). +@end defmethod + @defmethod Frame read_var variable Return the value of the given variable in this frame. @var{variable} must be a string. @end defmethod + +@defmethod Frame select +Set this frame to be the user's selected frame. +@end defmethod +@end table + +@node Blocks In Python +@subsubsection Accessing frame blocks from Python. + +@cindex blocks in python +@tindex gdb.Block + +All of the name-scope contours of a program are represented as 'block' +objects in @value{GDBN}. Similarly, in Python these objects are +represented as @code{gdb.Block} objects. Each @code{gdb.Block} object +has to be sourced, and parented from a @code{gdb.Frame} object. The +validity of a @code{gdb.Block} follows the same rules as that of a +@code{gdb.Frame} (@pxref{Frames In Python} for more information). + +The structure of a @code{gdb.Block} follows the same rules as the +underlying @value{GDBN} block. This can be summarized as: each block +represents one name scope; each lexical context has its own block. + +The following block-related functions are available in the @code{gdb} +module: + +@findex gdb.block_for_pc pc +@defun block_for_pc pc +Return the @code{gdb.Block} containing the given @code{pc} value. If the +block cannot be found for the @code{pc} value specified, the function +will return @code{None}. +@end defun + +A @code{gdb.Block} object has the following attributes: + +@table @code +@defivar Block start +This attribute holds the start address of the block. This attribute is not +writable. +@end defivar + +@defivar Block end +This attribute holds the end address of the block. This attribute +is not writable. +@end defivar + +@defivar Block function +This attribute holds the name of the block represented as a +@code{gdb.Symbol}. If the block is not named, then this attribute +returns @code{None}. This attribute is not writable. +@end defivar + +@defivar Block superblock +This attribute holds the superblock containing this block represented as a +@code{gdb.Block}. If a superblock does not exist, this attribute holds +@code{None}. This attribute is not writable. +@end defivar +@end table + +@node Symbols In Python +@subsubsection Python representation of Symbols. + +@cindex symbols in python +@tindex gdb.Symbol + +@value{GDBN} represents the name of every variable, function and type +as a symbol (@pxref{Symbols, ,Examining the Symbol Table}). Similarly, +Python represents these symbols in @value{GDBN} with the +@code{gdb.Symbol} object. + +The following symbol-related functions are available in the @code{gdb} +module: + +@findex gdb.lookup_symbol name [block] [domain] +@defun lookup_symbol name [block] [domain] +This function looks up a symbol by name. The search scope can be +restricted to the parameters defined in the optional domain and block +arguments. + +@var{name} is the name of the symbol to look-up. It must be a +string. The optional @var{block} argument restricts the look-up to +symbols visible in that @var{block}. The @var{block} argument must be a +@code{gdb.Block} object. The optional @var{domain} argument restricts +the look-up to the domain type. The @var{domain} argument must be a +domain constant defined in the @code{gdb} module and described later +in this chapter. +@end defun + +A @code{gdb.Symbol} object has the following attributes: + +@table @code +@defivar Symbol symtab +The symbol table in which the symbol appears. This attribute is +represented as a @code{gdb.Symtab} object. @xref{Symbol Tables In +Python}. This attribute is not writable. +@end defivar + +@defivar Symbol name +The name of the symbol as a string. This attribute is not writable. +@end defivar + +@defivar Symbol linkage_name +The name of the symbol, as used by the linker (i.e., may be mangled). +This attribute is not writable. +@end defivar + +@defivar Symbol print_name +The name of the symbol in a form suitable for output. This is either +name or linkage_name, depending on whether the user asked @value{GDBN} +to display demangled or mangled names. +@end defivar + +@defivar Symbol addr_class +The address class of the symbol. This classifies how to find the value +of a symbol. Each address class is a constant defined in the +@code{gdb} module and described later in this chapter. +@end defivar + +@defivar Symbol is_argument +Returns @code{True} if the symbol is an argument of a function. +@end defivar + +@defivar Symbol is_constant +Returns @code{True} if the symbol is a constant. +@end defivar + +@defivar Symbol is_function +Returns @code{True} if the symbol is a function or a method. +@end defivar + +@defivar Symbol is_variable +Returns @code{True} if the symbol is a variable. +@end defivar +@end table + +The available domain categories in @code{gdb.Symbol} are represented +as constants in the @code{gdb} module: + +@table @code +@findex SYMBOL_UNDEF_DOMAIN +@findex gdb.SYMBOL_UNDEF_DOMAIN +@item SYMBOL_UNDEF_DOMAIN +This is used when a domain has not been discovered or none of the +following domains apply. This usually indicates an error either +in the symbol information or in @value{GDBN}'s handling of symbols. +@findex SYMBOL_VAR_DOMAIN +@findex gdb.SYMBOL_VAR_DOMAIN +@item SYMBOL_VAR_DOMAIN +This domain contains variables, function names, typedef names and enum +type values. +@findex SYMBOL_STRUCT_DOMAIN +@findex gdb.SYMBOL_STRUCT_DOMAIN +@item SYMBOL_STRUCT_DOMAIN +This domain holds struct, union and enum type names. +@findex SYMBOL_LABEL_DOMAIN +@findex gdb.SYMBOL_LABEL_DOMAIN +@item SYMBOL_LABEL_DOMAIN +This domain contains names of labels (for gotos). +@findex SYMBOL_VARIABLES_DOMAIN +@findex gdb.SYMBOL_VARIABLES_DOMAIN +@item SYMBOL_VARIABLES_DOMAIN +This domain holds a subset of the @code{SYMBOLS_VAR_DOMAIN}; it +contains everything minus functions and types. +@findex SYMBOL_FUNCTIONS_DOMAIN +@findex gdb.SYMBOL_FUNCTIONS_DOMAIN +@item SYMBOL_FUNCTION_DOMAIN +This domain contains all functions. +@findex SYMBOL_TYPES_DOMAIN +@findex gdb.SYMBOL_TYPES_DOMAIN +@item SYMBOL_TYPES_DOMAIN +This domain contains all types. +@end table + +The available address class categories in @code{gdb.Symbol} are represented +as constants in the @code{gdb} module: + +@table @code +@findex SYMBOL_LOC_UNDEF +@findex gdb.SYMBOL_LOC_UNDEF +@item SYMBOL_LOC_UNDEF +If this is returned by address class, it indicates an error either in +the symbol information or in @value{GDBN}'s handling of symbols. +@findex SYMBOL_LOC_CONST +@findex gdb.SYMBOL_LOC_CONST +@item SYMBOL_LOC_CONST +Value is constant int. +@findex SYMBOL_LOC_STATIC +@findex gdb.SYMBOL_LOC_STATIC +@item SYMBOL_LOC_STATIC +Value is at a fixed address. +@findex SYMBOL_LOC_REGISTER +@findex gdb.SYMBOL_LOC_REGISTER +@item SYMBOL_LOC_REGISTER +Value is in a register. +@findex SYMBOL_LOC_ARG +@findex gdb.SYMBOL_LOC_ARG +@item SYMBOL_LOC_ARG +Value is an argument. +@findex SYMBOL_LOC_REF_ARG +@findex gdb.SYMBOL_LOC_REF_ARG +@item SYMBOL_LOC_REF_ARG +Value address is an offset in arglist. +@findex SYMBOL_LOC_REGPARM_ADDR +@findex gdb.SYMBOL_LOC_REGPARM_ADDR +@item SYMBOL_LOC_REGPARM_ADDR +Value is a specified register. Just like @code{LOC_REGISTER} except +the register holds the address of the argument instead of the argument +itself. +@findex SYMBOL_LOC_LOCAL +@findex gdb.SYMBOL_LOC_LOCAL +@item SYMBOL_LOC_LOCAL +Value is a local variable. +@findex SYMBOL_LOC_TYPEDEF +@findex gdb.SYMBOL_LOC_TYPEDEF +@item SYMBOL_LOC_TYPEDEF +Value not used. Symbols in the domain @code{SYMBOL_STRUCT_DOMAIN} all +have this class. +@findex SYMBOL_LOC_BLOCK +@findex gdb.SYMBOL_LOC_BLOCK +@item SYMBOL_LOC_BLOCK +Value is a block. +@findex SYMBOL_LOC_CONST_BYTES +@findex gdb.SYMBOL_LOC_CONST_BYTES +@item SYMBOL_LOC_CONST_BYTES +Value is a byte-sequence. +@findex SYMBOL_LOC_UNRESOLVED +@findex gdb.SYMBOL_LOC_UNRESOLVED +@item SYMBOL_LOC_UNRESOLVED +Value is at a fixed address, but the address of the variable has to be +determined from the minimal symbol table whenever the variable is +referenced. +@findex SYMBOL_LOC_OPTIMIZED_OUT +@findex gdb.SYMBOL_LOC_OPTIMIZED_OUT +@item SYMBOL_LOC_OPTIMIZED_OUT +The value does not actually exist in the program. +@findex SYMBOL_LOC_COMPUTED +@findex gdb.SYMBOL_LOC_COMPUTED +@item SYMBOL_LOC_COMPUTED +The value's address is a computed location. +@end table + +@node Symbol Tables In Python +@subsubsection Symbol table representation in Python. + +@cindex symbol tables in python +@tindex gdb.Symtab +@tindex gdb.Symtab_and_line + +Access to symbol table data maintained by @value{GDBN} on the inferior +is exposed to Python via two objects: @code{gdb.Symtab_and_line} and +@code{gdb.Symtab}. Access to the @code{gdb.Symtab_and_line} object for +each frame is returned from the @code{find_sal} method in +@code{gdb.Frame} object (@pxref{Frames In Python}). + +For more information on @value{GDBN}'s symbol table management +@xref{Symbols, ,Examining the Symbol Table}. + +A @code{gdb.Symtab_and_line} object has the following attributes: + +@table @code +@defivar Symtab_and_line symtab +The symbol table object (@code{gdb.Symtab}) for this frame. +This attribute is not writable. +@end defivar + +@defivar Symtab_and_line pc +Indicates the current program counter address. This attribute is not +writable. +@end defivar + +@defivar Symtab_and_line line +Indicates the current line number information for this object. This +attribute is not writable. +@end defivar +@end table + +A @code{gdb.Symtab} object has the following attributes: + +@table @code +@defivar Symtab filename +The symbol table's source filename. This attribute is not writable. +@end defivar + +@defivar Symtab objfile +The symbol table's backing object file. @xref{Objfiles In Python}. +This attribute is not writable. +@end defivar +@end table + +The following methods are provided: + +@table @code +@defmethod Symtab fullname +Return the symbol table's full source filename. +@end defmethod @end table @node Lazy Strings In Python diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c new file mode 100644 index 0000000..5fc4760 --- /dev/null +++ b/gdb/python/py-block.c @@ -0,0 +1,265 @@ +/* Python interface to blocks. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "block.h" +#include "dictionary.h" +#include "symtab.h" +#include "python-internal.h" + +typedef struct { + PyObject_HEAD + struct block *block; +} block_object; + +typedef struct { + PyObject_HEAD + struct dictionary *dict; + struct dict_iterator iter; + int initialized_p; +} block_syms_iterator_object; + +static PyTypeObject block_syms_iterator_object_type; + +static PyObject * +blpy_iter (PyObject *self) +{ + block_syms_iterator_object *block_iter_obj; + + block_iter_obj = PyObject_New (block_syms_iterator_object, + &block_syms_iterator_object_type); + if (block_iter_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, + "Could not allocate iterator object."); + return NULL; + } + + block_iter_obj->dict = BLOCK_DICT (((block_object *) self)->block); + block_iter_obj->initialized_p = 0; + + return (PyObject *) block_iter_obj; +} + +static PyObject * +blpy_get_start (PyObject *self, void *closure) +{ + block_object *self_block = (block_object *) self; + + return PyLong_FromUnsignedLongLong (BLOCK_START (self_block->block)); +} + +static PyObject * +blpy_get_end (PyObject *self, void *closure) +{ + block_object *self_block = (block_object *) self; + + return PyLong_FromUnsignedLongLong (BLOCK_END (self_block->block)); +} + +static PyObject * +blpy_get_function (PyObject *self, void *closure) +{ + block_object *self_block = (block_object *) self; + struct symbol *sym; + + sym = BLOCK_FUNCTION (self_block->block); + if (sym) + return symbol_to_symbol_object (sym); + + Py_RETURN_NONE; +} + +static PyObject * +blpy_get_superblock (PyObject *self, void *closure) +{ + block_object *self_block = (block_object *) self; + struct block *block; + + block = BLOCK_SUPERBLOCK (self_block->block); + if (block) + return block_to_block_object (block); + + Py_RETURN_NONE; +} + +PyObject * +block_to_block_object (struct block *block) +{ + block_object *block_obj; + + block_obj = PyObject_New (block_object, &block_object_type); + if (block_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, "Could not allocate block object."); + return NULL; + } + + block_obj->block = block; + + return (PyObject *) block_obj; +} + +struct block * +block_object_to_block (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &block_object_type)) + return NULL; + return ((block_object *) obj)->block; +} + +static PyObject * +blpy_block_syms_iter (PyObject *self) +{ + return self; +} + +static PyObject * +blpy_block_syms_iternext (PyObject *self) +{ + block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self; + struct symbol *sym; + + if (!iter_obj->initialized_p) + { + sym = dict_iterator_first (iter_obj->dict, &(iter_obj->iter)); + iter_obj->initialized_p = 1; + } + else + sym = dict_iterator_next (&(iter_obj->iter)); + + return (sym == NULL)? NULL : symbol_to_symbol_object (sym); +} + +/* Return the innermost lexical block containing the specified pc value, + or 0 if there is none. */ + +PyObject * +gdbpy_block_for_pc (PyObject *self, PyObject *args) +{ + unsigned PY_LONG_LONG pc; + struct block *block; + PyObject *sym_obj; + + if (!PyArg_ParseTuple (args, "K", &pc)) + return NULL; + + block = block_for_pc (pc); + if (block) + return block_to_block_object (block); + + Py_RETURN_NONE; +} + +void +gdbpy_initialize_blocks (void) +{ + block_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&block_object_type) < 0) + return; + + block_syms_iterator_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&block_syms_iterator_object_type) < 0) + return; + + Py_INCREF (&block_object_type); + PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type); + + Py_INCREF (&block_syms_iterator_object_type); + PyModule_AddObject (gdb_module, "BlockIterator", + (PyObject *) &block_syms_iterator_object_type); +} + + + +static PyGetSetDef block_object_getset[] = { + { "start", blpy_get_start, NULL, "Start address of the block.", NULL }, + { "end", blpy_get_end, NULL, "End address of the block.", NULL }, + { "function", blpy_get_function, NULL, + "Symbol that names the block, or None.", NULL }, + { "superblock", blpy_get_superblock, NULL, + "Block containing the block, or None.", NULL }, + { NULL } /* Sentinel */ +}; + +PyTypeObject block_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Block", /*tp_name*/ + sizeof (block_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB block object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + blpy_iter, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + block_object_getset /* tp_getset */ +}; + +static PyTypeObject block_syms_iterator_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.BlockIterator", /*tp_name*/ + sizeof (block_syms_iterator_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB block syms iterator object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + blpy_block_syms_iter, /* tp_iter */ + blpy_block_syms_iternext, /* tp_iternext */ + 0 /* tp_methods */ +}; diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 334bad9..f48a3ad 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -202,6 +202,55 @@ frapy_pc (PyObject *self, PyObject *args) return PyLong_FromUnsignedLongLong (pc); } +/* Implementation of gdb.Frame.block (self) -> gdb.Block. + Returns the frame's code block. */ + +static PyObject * +frapy_block (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + struct block *block = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + block = block_for_pc (get_frame_address_in_block (frame)); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (block) + return block_to_block_object (block); + + Py_RETURN_NONE; +} + + +/* Implementation of gdb.Frame.function (self) -> gdb.Symbol. + Returns the symbol for the function corresponding to this frame. */ + +static PyObject * +frapy_function (PyObject *self, PyObject *args) +{ + struct symbol *sym = NULL; + struct frame_info *frame; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + sym = find_pc_function (get_frame_address_in_block (frame)); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (sym) + return symbol_to_symbol_object (sym); + + Py_RETURN_NONE; +} + /* Convert a frame_info struct to a Python Frame object. Sets a Python exception and returns NULL on error. */ @@ -296,6 +345,29 @@ frapy_newer (PyObject *self, PyObject *args) return next_obj; } +/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line. + Returns the frame's symtab and line. */ + +static PyObject * +frapy_find_sal (PyObject *self, PyObject *args) +{ + struct frame_info *frame; + struct symtab_and_line sal; + volatile struct gdb_exception except; + PyObject *sal_obj = NULL; /* Initialize to appease gcc warning. */ + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + + find_frame_sal (frame, &sal); + sal_obj = symtab_and_line_to_sal_object (sal); + } + GDB_PY_HANDLE_EXCEPTION (except); + + return sal_obj; +} + /* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value. Returns the value of the given variable in this frame. The argument must be a string. Returns None if GDB can't find the specified variable. */ @@ -312,7 +384,9 @@ frapy_read_var (PyObject *self, PyObject *args) if (!PyArg_ParseTuple (args, "O", &sym_obj)) return NULL; - if (gdbpy_is_string (sym_obj)) + if (PyObject_TypeCheck (sym_obj, &symbol_object_type)) + var = symbol_object_to_symbol (sym_obj); + else if (gdbpy_is_string (sym_obj)) { char *var_name; struct block *block = NULL; @@ -365,6 +439,25 @@ frapy_read_var (PyObject *self, PyObject *args) Py_RETURN_NONE; } +/* Select this frame. */ + +static PyObject * +frapy_select (PyObject *self, PyObject *args) +{ + struct frame_info *fi; + frame_object *frame = (frame_object *) self; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + FRAPY_REQUIRE_VALID (frame, fi); + select_frame (fi); + } + GDB_PY_HANDLE_EXCEPTION (except); + + Py_RETURN_NONE; +} + /* Implementation of gdb.selected_frame () -> gdb.Frame. Returns the selected frame object. */ @@ -484,15 +577,26 @@ Return the reason why it's not possible to find frames older than this." }, { "pc", frapy_pc, METH_NOARGS, "pc () -> Long.\n\ Return the frame's resume address." }, + { "block", frapy_block, METH_NOARGS, + "block () -> gdb.Block.\n\ +Return the frame's code block." }, + { "function", frapy_function, METH_NOARGS, + "function () -> gdb.Symbol.\n\ +Returns the symbol for the function corresponding to this frame." }, { "older", frapy_older, METH_NOARGS, "older () -> gdb.Frame.\n\ Return the frame that called this frame." }, { "newer", frapy_newer, METH_NOARGS, "newer () -> gdb.Frame.\n\ Return the frame called by this frame." }, + { "find_sal", frapy_find_sal, METH_NOARGS, + "find_sal () -> gdb.Symtab_and_line.\n\ +Return the frame's symtab and line." }, { "read_var", frapy_read_var, METH_VARARGS, "read_var (variable) -> gdb.Value.\n\ Return the value of the variable in this frame." }, + { "select", frapy_select, METH_NOARGS, + "Select this frame as the user's current frame." }, {NULL} /* Sentinel */ }; diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c new file mode 100644 index 0000000..2a33b63 --- /dev/null +++ b/gdb/python/py-symbol.c @@ -0,0 +1,314 @@ +/* Python interface to symbols. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "block.h" +#include "exceptions.h" +#include "frame.h" +#include "symtab.h" +#include "python-internal.h" + +typedef struct { + PyObject_HEAD + struct symbol *symbol; +} symbol_object; + + +static PyObject * +sympy_str (PyObject *self) +{ + int ret; + char *s; + PyObject *result; + + ret = asprintf (&s, "symbol for %s", + SYMBOL_PRINT_NAME (((symbol_object *) self)->symbol)); + if (ret < 0) + Py_RETURN_NONE; + + result = PyString_FromString (s); + xfree (s); + + return result; +} + +static PyObject * +sympy_get_symtab (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return symtab_to_symtab_object (SYMBOL_SYMTAB (self_sym->symbol)); +} + +static PyObject * +sympy_get_name (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return PyString_FromString (SYMBOL_NATURAL_NAME (self_sym->symbol)); +} + +static PyObject * +sympy_get_linkage_name (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return PyString_FromString (SYMBOL_LINKAGE_NAME (self_sym->symbol)); +} + +static PyObject * +sympy_get_print_name (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return PyString_FromString (SYMBOL_PRINT_NAME (self_sym->symbol)); +} + +static PyObject * +sympy_get_addr_class (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return PyInt_FromLong (SYMBOL_CLASS (self_sym->symbol)); +} + +static PyObject * +sympy_is_argument (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + + return PyBool_FromLong (SYMBOL_IS_ARGUMENT (self_sym->symbol)); +} + +static PyObject * +sympy_is_constant (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + enum address_class class = SYMBOL_CLASS (self_sym->symbol); + + return PyBool_FromLong (class == LOC_CONST || class == LOC_CONST_BYTES); +} + +static PyObject * +sympy_is_function (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + enum address_class class = SYMBOL_CLASS (self_sym->symbol); + + return PyBool_FromLong (class == LOC_BLOCK); +} + +static PyObject * +sympy_is_variable (PyObject *self, void *closure) +{ + symbol_object *self_sym = (symbol_object *) self; + enum address_class class = SYMBOL_CLASS (self_sym->symbol); + + return PyBool_FromLong (!SYMBOL_IS_ARGUMENT (self_sym->symbol) + && (class == LOC_LOCAL || class == LOC_REGISTER || class == LOC_STATIC + || class == LOC_COMPUTED || class == LOC_OPTIMIZED_OUT)); +} + +PyObject * +symbol_to_symbol_object (struct symbol *sym) +{ + symbol_object *sym_obj; + + sym_obj = PyObject_New (symbol_object, &symbol_object_type); + if (sym_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, "Could not allocate symbol object."); + return NULL; + } + + sym_obj->symbol = sym; + + return (PyObject *) sym_obj; +} + +struct symbol * +symbol_object_to_symbol (PyObject *obj) +{ + if (! PyObject_TypeCheck (obj, &symbol_object_type)) + return NULL; + return ((symbol_object *) obj)->symbol; +} + +/* Implementation of + gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this) + A tuple with 2 elements is always returned. The first is the symbol + object or None, the second is a boolean with the value of + is_a_field_of_this (see comment in lookup_symbol_in_language). */ + +PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw) +{ + int domain = VAR_DOMAIN, is_a_field_of_this = 0; + const char *name; + static char *keywords[] = { "name", "block", "domain", NULL }; + struct symbol *symbol; + PyObject *block_obj = NULL, *ret_tuple, *sym_obj, *bool_obj; + struct block *block = NULL; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!i", keywords, &name, + &block_object_type, &block_obj, &domain)) + return NULL; + + if (block_obj) + block = block_object_to_block (block_obj); + else + { + struct frame_info *selected_frame; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + selected_frame = get_selected_frame (_("No frame selected.")); + block = block_for_pc (get_frame_address_in_block (selected_frame)); + } + GDB_PY_HANDLE_EXCEPTION (except); + } + + symbol = lookup_symbol (name, block, domain, &is_a_field_of_this); + + ret_tuple = PyTuple_New (2); + if (!ret_tuple) + { + PyErr_SetString (PyExc_MemoryError, "Could not allocate tuple object."); + return NULL; + } + + if (symbol) + { + sym_obj = symbol_to_symbol_object (symbol); + if (!sym_obj) + { + Py_DECREF (ret_tuple); + return NULL; + } + } + else + { + sym_obj = Py_None; + Py_INCREF (Py_None); + } + PyTuple_SET_ITEM (ret_tuple, 0, sym_obj); + + bool_obj = is_a_field_of_this? Py_True : Py_False; + Py_INCREF (bool_obj); + PyTuple_SET_ITEM (ret_tuple, 1, bool_obj); + + return ret_tuple; +} + +void +gdbpy_initialize_symbols (void) +{ + if (PyType_Ready (&symbol_object_type) < 0) + return; + + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST", LOC_CONST); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_STATIC", LOC_STATIC); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGISTER", LOC_REGISTER); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_ARG", LOC_ARG); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REF_ARG", LOC_REF_ARG); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL", LOC_LOCAL); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_TYPEDEF", LOC_TYPEDEF); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LABEL", LOC_LABEL); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BLOCK", LOC_BLOCK); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST_BYTES", + LOC_CONST_BYTES); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNRESOLVED", LOC_UNRESOLVED); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_OPTIMIZED_OUT", + LOC_OPTIMIZED_OUT); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED", LOC_COMPUTED); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM_ADDR", + LOC_REGPARM_ADDR); + PyModule_AddIntConstant (gdb_module, "SYMBOL_UNDEF_DOMAIN", UNDEF_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_VAR_DOMAIN", VAR_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_STRUCT_DOMAIN", STRUCT_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_LABEL_DOMAIN", LABEL_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_VARIABLES_DOMAIN", + VARIABLES_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_FUNCTIONS_DOMAIN", + FUNCTIONS_DOMAIN); + PyModule_AddIntConstant (gdb_module, "SYMBOL_TYPES_DOMAIN", TYPES_DOMAIN); + + Py_INCREF (&symbol_object_type); + PyModule_AddObject (gdb_module, "Symbol", (PyObject *) &symbol_object_type); +} + + + +static PyGetSetDef symbol_object_getset[] = { + { "symtab", sympy_get_symtab, NULL, + "Symbol table in which the symbol appears.", NULL }, + { "name", sympy_get_name, NULL, + "Name of the symbol, as it appears in the source code.", NULL }, + { "linkage_name", sympy_get_linkage_name, NULL, + "Name of the symbol, as used by the linker (i.e., may be mangled).", NULL }, + { "print_name", sympy_get_print_name, NULL, + "Name of the symbol in a form suitable for output.\n\ +This is either name or linkage_name, depending on whether the user asked GDB\n\ +to display demangled or mangled names.", NULL }, + { "addr_class", sympy_get_addr_class, NULL, "Address class of the symbol." }, + { "is_argument", sympy_is_argument, NULL, + "True if the symbol is an argument of a function." }, + { "is_constant", sympy_is_constant, NULL, + "True if the symbol is a constant." }, + { "is_function", sympy_is_function, NULL, + "True if the symbol is a function or method." }, + { "is_variable", sympy_is_variable, NULL, + "True if the symbol is a variable." }, + { NULL } /* Sentinel */ +}; + +PyTypeObject symbol_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symbol", /*tp_name*/ + sizeof (symbol_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + sympy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symbol object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + symbol_object_getset /* tp_getset */ +}; diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c new file mode 100644 index 0000000..866c71a --- /dev/null +++ b/gdb/python/py-symtab.c @@ -0,0 +1,322 @@ +/* Python interface to symbol tables. + + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "defs.h" +#include "charset.h" +#include "symtab.h" +#include "source.h" +#include "python-internal.h" + +typedef struct { + PyObject_HEAD + struct symtab *symtab; +} symtab_object; + +static PyTypeObject symtab_object_type; + +typedef struct { + PyObject_HEAD + symtab_object *symtab; + struct symtab_and_line *sal; +} sal_object; + +static PyTypeObject sal_object_type; + + +static PyObject * +stpy_str (PyObject *self) +{ + int ret; + char *s; + PyObject *result; + + ret = asprintf (&s, "symbol table for %s", + ((symtab_object *) self)->symtab->filename); + if (ret < 0) + Py_RETURN_NONE; + + result = PyString_FromString (s); + xfree (s); + + return result; +} + +static PyObject * +stpy_get_filename (PyObject *self, void *closure) +{ + symtab_object *self_symtab = (symtab_object *) self; + PyObject *str_obj; + + /* FIXME: Can symtab->filename really be NULL? */ + if (self_symtab->symtab->filename) + str_obj = PyString_Decode (self_symtab->symtab->filename, + strlen (self_symtab->symtab->filename), + host_charset (), NULL); + else + { + str_obj = Py_None; + Py_INCREF (Py_None); + } + + return str_obj; +} + +static PyObject * +stpy_get_objfile (PyObject *self, void *closure) +{ + symtab_object *self_symtab = (symtab_object *) self; + PyObject *result = objfile_to_objfile_object (self_symtab->symtab->objfile); + Py_INCREF (result); + return result; +} + +static PyObject * +stpy_fullname (PyObject *self, PyObject *args) +{ + char *fullname; + + fullname = symtab_to_fullname (((symtab_object *) self)->symtab); + if (fullname) + return PyString_Decode (fullname, strlen (fullname), host_charset (), NULL); + + Py_RETURN_NONE; +} + +static PyObject * +salpy_str (PyObject *self) +{ + int ret; + char *s, *filename; + sal_object *sal_obj; + PyObject *result; + + sal_obj = (sal_object *) self; + filename = (sal_obj->symtab == (symtab_object *) Py_None)? "" : + sal_obj->symtab->symtab->filename; + ret = asprintf (&s, "symbol and line for %s, line %d", filename, + sal_obj->sal->line); + if (ret < 0) + Py_RETURN_NONE; + + result = PyString_FromString (s); + xfree (s); + + return result; +} + +static PyObject * +salpy_get_pc (PyObject *self, void *closure) +{ + return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->pc); +} + +static PyObject * +salpy_get_line (PyObject *self, void *closure) +{ + return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->line); +} + +static PyObject * +salpy_get_symtab (PyObject *self, void *closure) +{ + sal_object *self_sal = (sal_object *) self; + + Py_INCREF (self_sal->symtab); + + return (PyObject *) self_sal->symtab; +} + +static void +salpy_dealloc (PyObject *self) +{ + sal_object *self_sal = (sal_object *) self; + + Py_DECREF (self_sal->symtab); + xfree (self_sal->sal); + self_sal->ob_type->tp_free (self); +} + +PyObject * +symtab_and_line_to_sal_object (struct symtab_and_line sal) +{ + sal_object *sal_obj; + symtab_object *symtab_obj; + + sal_obj = PyObject_New (sal_object, &sal_object_type); + if (sal_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, + "Could not allocate Symtab_and_line object."); + return NULL; + } + + if (sal.symtab) + { + symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab); + if (symtab_obj == NULL) + { + Py_DECREF (sal_obj); + return NULL; + } + + symtab_obj->symtab = sal.symtab; + } + else + { + symtab_obj = (symtab_object *) Py_None; + Py_INCREF (Py_None); + } + + sal_obj->sal = (struct symtab_and_line *) + xmalloc (sizeof (struct symtab_and_line)); + *(sal_obj->sal) = sal; + sal_obj->symtab = symtab_obj; + + return (PyObject *) sal_obj; +} + +PyObject * +symtab_to_symtab_object (struct symtab *symtab) +{ + symtab_object *symtab_obj; + + symtab_obj = PyObject_New (symtab_object, &symtab_object_type); + if (symtab_obj == NULL) + { + PyErr_SetString (PyExc_MemoryError, + "Could not allocate Symtab object."); + + return NULL; + } + + symtab_obj->symtab = symtab; + + return (PyObject *) symtab_obj; +} + +void +gdbpy_initialize_symtabs (void) +{ + symtab_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&symtab_object_type) < 0) + return; + + sal_object_type.tp_new = PyType_GenericNew; + if (PyType_Ready (&sal_object_type) < 0) + return; + + Py_INCREF (&symtab_object_type); + PyModule_AddObject (gdb_module, "Symtab", (PyObject *) &symtab_object_type); + + Py_INCREF (&sal_object_type); + PyModule_AddObject (gdb_module, "Symtab_and_line", + (PyObject *) &sal_object_type); +} + + + +static PyGetSetDef symtab_object_getset[] = { + { "filename", stpy_get_filename, NULL, + "The symbol table's source filename.", NULL }, + { "objfile", stpy_get_objfile, NULL, "The symtab's objfile.", + NULL }, + {NULL} /* Sentinel */ +}; + +static PyMethodDef symtab_object_methods[] = { + { "fullname", stpy_fullname, METH_NOARGS, + "Return the symtab's full source filename." }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject symtab_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symtab", /*tp_name*/ + sizeof (symtab_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + stpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symtab object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + symtab_object_methods, /* tp_methods */ + 0, /* tp_members */ + symtab_object_getset /* tp_getset */ +}; + +static PyGetSetDef sal_object_getset[] = { + { "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL }, + { "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL }, + { "line", salpy_get_line, NULL, + "Return the symtab_and_line's line.", NULL }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject sal_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.Symtab_and_line", /*tp_name*/ + sizeof (sal_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + salpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + salpy_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "GDB symtab_and_line object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + sal_object_getset /* tp_getset */ +}; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 9196f08..8edba30 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -61,32 +61,49 @@ typedef int Py_ssize_t; #define PyEval_ReleaseLock() 0 #endif +struct block; +struct symbol; +struct symtab_and_line; struct value; struct language_defn; extern PyObject *gdb_module; extern PyTypeObject value_object_type; +extern PyTypeObject block_object_type; +extern PyTypeObject symbol_object_type; PyObject *gdbpy_history (PyObject *self, PyObject *args); PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *); +PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args); +PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args); PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw); PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length, const char *encoding, struct type *type); +PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); +PyObject *symtab_to_symtab_object (struct symtab *symtab); +PyObject *symbol_to_symbol_object (struct symbol *sym); +PyObject *block_to_block_object (struct block *block); PyObject *value_to_value_object (struct value *v); PyObject *type_to_type_object (struct type *); PyObject *objfile_to_objfile_object (struct objfile *); PyObject *objfpy_get_printers (PyObject *, void *); +struct block *block_object_to_block (PyObject *obj); +struct symbol *symbol_object_to_symbol (PyObject *obj); struct value *value_object_to_value (PyObject *self); struct value *convert_value_from_python (PyObject *obj); struct type *type_object_to_type (PyObject *obj); void gdbpy_initialize_values (void); void gdbpy_initialize_frames (void); +void gdbpy_initialize_symtabs (void); void gdbpy_initialize_commands (void); +void gdbpy_initialize_symbols (void); +void gdbpy_initialize_symtabs (void); +void gdbpy_initialize_blocks (void); void gdbpy_initialize_types (void); void gdbpy_initialize_functions (void); void gdbpy_initialize_objfile (void); diff --git a/gdb/python/python.c b/gdb/python/python.c index 29386c9..3d38de6 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -644,6 +644,9 @@ Enables or disables auto-loading of Python code when an object is opened."), gdbpy_initialize_values (); gdbpy_initialize_frames (); gdbpy_initialize_commands (); + gdbpy_initialize_symbols (); + gdbpy_initialize_symtabs (); + gdbpy_initialize_blocks (); gdbpy_initialize_functions (); gdbpy_initialize_types (); gdbpy_initialize_objfile (); @@ -724,7 +727,14 @@ Return a string explaining unwind stop reason." }, METH_VARARGS | METH_KEYWORDS, "lookup_type (name [, block]) -> type\n\ Return a Type corresponding to the given name." }, - + { "lookup_symbol", (PyCFunction) gdbpy_lookup_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)\n\ +Return a tuple with the symbol corresponding to the given name (or None) and\n\ +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." }, { "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/Makefile.in b/gdb/testsuite/gdb.python/Makefile.in index 3e81bd3..06f8c9c 100644 --- a/gdb/testsuite/gdb.python/Makefile.in +++ b/gdb/testsuite/gdb.python/Makefile.in @@ -1,7 +1,8 @@ VPATH = @srcdir@ srcdir = @srcdir@ -EXECUTABLES = py-type py-value py-prettyprint py-template +EXECUTABLES = py-type py-value py-prettyprint py-template py-block \ + py-symbol all info install-info dvi install uninstall installcheck check: @echo "Nothing to be done for $@..." diff --git a/gdb/testsuite/gdb.python/py-block.c b/gdb/testsuite/gdb.python/py-block.c new file mode 100644 index 0000000..a748044 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-block.c @@ -0,0 +1,41 @@ +/* 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 . +*/ + + + +int block_func (void) +{ + int i = 0; + { + double i = 1.0; + double f = 2.0; + { + const char *i = "stuff"; + const char *f = "foo"; + const char *b = "bar"; + return 0; /* Block break here. */ + } + } +} + + +int main (int argc, char *argv[]) +{ + block_func (); + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.python/py-block.exp b/gdb/testsuite/gdb.python/py-block.exp new file mode 100644 index 0000000..31345e3 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-block.exp @@ -0,0 +1,84 @@ +# Copyright (C) 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 . + +# This file is part of the GDB testsuite. It tests the mechanism +# exposing values to Python. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "py-block" +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 +} + +# 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 } } + } +} + +# 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 $" {} +} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +global hex decimal +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." + +# Test initial innermost block. +gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 +gdb_py_test_silent_cmd "python block = frame.block()" "Get block" 0 +gdb_test "python print block" "" "Check block not None" +gdb_test "python print block.function" "None" "First anonymous block" +gdb_test "python print block.start" "${decimal}" "Check start not None" +gdb_test "python print block.end" "${decimal}" "Check end not None" + +# Move up superblock(s) until we reach function block_func. +gdb_test "python block = block.superblock" "" "Get superblock" +gdb_test "python print block.function" "None" "Second anonymous block" +gdb_test "python block = block.superblock" "" "Get superblock" +gdb_test "python print block.function" "symbol for block_func" + +# Switch frames, then test for main block. +gdb_test "up" "" +gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 +gdb_py_test_silent_cmd "python block = frame.block()" "Get block" 0 +gdb_test "python print block" "" "Check block not None" +gdb_test "python print block.function" "symbol for main" "main block" diff --git a/gdb/testsuite/gdb.python/py-symbol.c b/gdb/testsuite/gdb.python/py-symbol.c new file mode 100644 index 0000000..0c8bb60 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-symbol.c @@ -0,0 +1,62 @@ +/* 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 . +*/ + +#ifdef __cplusplus +class SimpleClass +{ + private: + int i; + + public: + void seti (int arg) + { + i = arg; + } + + int valueofi (void) + { + return i; /* Break in class. */ + } +}; +#endif + +int func (int arg) +{ + int i = 2; + i = i * arg; + return arg; /* Block break here. */ +} + +int main (int argc, char *argv[]) +{ +#ifdef __cplusplus + SimpleClass sclass; +#endif + int a = 0; + int result; + enum tag {one, two, three}; + enum tag t = one; + + result = func (42); + +#ifdef __cplusplus + sclass.seti (42); + sclass.valueofi (); +#endif + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.python/py-symbol.exp b/gdb/testsuite/gdb.python/py-symbol.exp new file mode 100644 index 0000000..23b7844 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-symbol.exp @@ -0,0 +1,137 @@ +# Copyright (C) 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 . + +# This file is part of the GDB testsuite. It tests the mechanism +# exposing values to Python. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "py-symbol" +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 +} + +# 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 } } + } +} + +# 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 $" {} +} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +global hex decimal + +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." +gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 +gdb_py_test_silent_cmd "python block = frame.block()" "Get block" 0 + +# Test is_argument attribute. +gdb_py_test_silent_cmd "python arg = gdb.lookup_symbol(\"arg\")" "Get variable a" 0 +gdb_test "python print arg\[0\].is_variable" "False" "Test arg.is_variable" +gdb_test "python print arg\[0\].is_constant" "False" "Test arg.is_constant" +gdb_test "python print arg\[0\].is_argument" "True" "Test arg.is_argument" +gdb_test "python print arg\[0\].is_function" "False" "Test arg.is_function" + +# Test is_function attribute. +gdb_py_test_silent_cmd "python func = frame.block().function" "Get block" 0 +gdb_test "python print func.is_variable" "False" "Test func.is_variable" +gdb_test "python print func.is_constant" "False" "Test func.is_constant" +gdb_test "python print func.is_argument" "False" "Test func.is_argument" +gdb_test "python print func.is_function" "True" "Test func.is_function" +gdb_test "python print func.name" "func" "Test func.name" +gdb_test "python print func.print_name" "func" "Test func.print_name" +gdb_test "python print func.linkage_name" "func" "Test func.linkage_name" +gdb_test "python print func.addr_class == gdb.SYMBOL_LOC_BLOCK" "True" "Test func.addr_class" + +gdb_breakpoint [gdb_get_line_number "Break at end."] +gdb_continue_to_breakpoint "Break at end." +gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 + +# Test is_variable attribute. +gdb_py_test_silent_cmd "python a = gdb.lookup_symbol(\'a\')" "Get variable a" 0 +gdb_test "python print a\[0\].is_variable" "True" "Test a.is_variable" +gdb_test "python print a\[0\].is_constant" "False" "Test a.is_constant" +gdb_test "python print a\[0\].is_argument" "False" "Test a.is_argument" +gdb_test "python print a\[0\].is_function" "False" "Test a.is_function" +gdb_test "python print a\[0\].addr_class == gdb.SYMBOL_LOC_COMPUTED" "True" "Test a.addr_class" + +# Test is_constant attribute +gdb_py_test_silent_cmd "python t = gdb.lookup_symbol(\"one\")" "Get variable a" 0 +gdb_test "python print t\[0\].is_variable" "False" "Test t.is_variable" +gdb_test "python print t\[0\].is_constant" "True" "Test t.is_constant" +gdb_test "python print t\[0\].is_argument" "False" "Test t.is_argument" +gdb_test "python print t\[0\].is_function" "False" "Test t.is_function" +gdb_test "python print t\[0\].addr_class == gdb.SYMBOL_LOC_CONST" "True" "Test t.addr_class" +gdb_test "python print t\[0\].symtab" "symbol table for.*" "Get symtab" + +# C++ tests +# Recompile binary. + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug c++"] != "" } { + untested "Couldn't compile ${srcfile} in c++ mode" + return -1 + } + +# Start with a fresh gdb. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_breakpoint [gdb_get_line_number "Break in class."] +gdb_continue_to_breakpoint "Break in class." + +gdb_py_test_silent_cmd "python cplusframe = gdb.selected_frame()" "Get Frame" 0 +gdb_py_test_silent_cmd "python cplusfunc = cplusframe.block().function" "Get block" 0 +gdb_test "python print cplusfunc.is_variable" "False" "Test func.is_variable" +gdb_test "python print cplusfunc.is_constant" "False" "Test func.is_constant" +gdb_test "python print cplusfunc.is_argument" "False" "Test func.is_argument" +gdb_test "python print cplusfunc.is_function" "True" "Test func.is_function" +gdb_test "python print cplusfunc.name" "SimpleClass::valueofi().*" "Test func.name" +gdb_test "python print cplusfunc.print_name" "SimpleClass::valueofi().*" "Test func.print_name" +gdb_test "python print cplusfunc.linkage_name" "_ZN11SimpleClass8valueofiEv" "Test func.linkage_name" +gdb_test "python print cplusfunc.addr_class == gdb.SYMBOL_LOC_BLOCK" "True" "Test func.addr_class" diff --git a/gdb/testsuite/gdb.python/py-symtab.exp b/gdb/testsuite/gdb.python/py-symtab.exp new file mode 100644 index 0000000..a43207b --- /dev/null +++ b/gdb/testsuite/gdb.python/py-symtab.exp @@ -0,0 +1,78 @@ +# Copyright (C) 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 . + +# This file is part of the GDB testsuite. It tests the mechanism +# exposing values to Python. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "py-symbol" +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 +} + +# 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 } } + } +} + +# 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 $" {} +} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +global hex decimal + +# Setup and get the symbol table. +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." +gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 +gdb_py_test_silent_cmd "python sal = frame.find_sal()" "Get block" 0 +gdb_py_test_silent_cmd "python symtab = sal.symtab" "Get block" 0 + +# Test sal. +gdb_test "python print sal.symtab" "gdb/testsuite/gdb.python/py-symbol.c.*" "Test symtab" +gdb_test "python print sal.pc" "${decimal}" "Test sal.pc" +gdb_test "python print sal.line" "42" "Test sal.line" + +# Test symbol table. +gdb_test "python print symtab.filename" "testsuite/gdb.python/py-symbol.c.*" "Test symtab.filename" +gdb_test "python print symtab.objfile" "" "Test symtab.objfile" +gdb_test "python print symtab.fullname()" "testsuite/gdb.python/py-symbol.c.*" "Test symtab.fullname"