2010-02-24 Phil Muldoon <pmuldoon@redhat.com>

Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* 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.


2010-02-24  Phil Muldoon  <pmuldoon@redhat.com>

	* 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.


2010-02-24  Phil Muldoon  <pmuldoon@redhat.com>

	* 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.
This commit is contained in:
Phil Muldoon
2010-02-24 21:18:28 +00:00
parent 101654612f
commit f3e9a8177c
18 changed files with 2279 additions and 5 deletions

View File

@@ -1,3 +1,31 @@
2010-02-24 Phil Muldoon <pmuldoon@redhat.com>
Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
* 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.
2010-02-24 Pedro Alves <pedro@codesourcery.com>
PR gdb/11321

View File

@@ -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
@@ -1971,6 +1977,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)
@@ -1995,6 +2005,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)

View File

@@ -3,6 +3,11 @@
*** Changes since GDB 7.1
* Python scripting
The GDB Python API now has access to symbols, symbol tables, and
frame's code blocks.
*** Changes in GDB 7.1
* C++ Improvements

View File

@@ -1,3 +1,13 @@
2010-02-24 Phil Muldoon <pmuldoon@redhat.com>
* 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.
2010-02-24 Vladimir Prus <vladimir@codesourcery.com>
Multiexec MI

View File

@@ -19547,7 +19547,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:: Python representation of symbol tables.
* Lazy Strings In Python:: Python representation of lazy strings.
@end menu
@@ -20707,7 +20710,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
@@ -20770,6 +20773,15 @@ function to a string.
Returns the frame's resume address.
@end defmethod
@defmethod Frame block
Return the frame's code block. @xref{Blocks In Python}.
@end defmethod
@defmethod Frame function
Return the symbol for the function corresponding to this frame.
@xref{Symbols In Python}.
@end defmethod
@defmethod Frame older
Return the frame that called this frame.
@end defmethod
@@ -20778,10 +20790,308 @@ 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.
@xref{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 selected frame. @xref{Stack, ,Examining the
Stack}.
@end defmethod
@end table
@node Blocks In Python
@subsubsection Accessing frame blocks from Python.
@cindex blocks in python
@tindex gdb.Block
Within each frame, @value{GDBN} maintains information on each block
stored in that frame. These blocks are organized hierarchically, and
are represented individually in Python as a @code{gdb.Block}.
Please see @ref{Frames In Python}, for a more in-depth discussion on
frames. Furthermore, see @ref{Stack, ,Examining the Stack}, for more
detailed technical information on @value{GDBN}'s book-keeping of the
stack.
The following block-related functions are available in the @code{gdb}
module:
@findex gdb.block_for_pc
@defun block_for_pc pc
Return the @code{gdb.Block} containing the given @var{pc} value. If the
block cannot be found for the @var{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
The start address of the block. This attribute is not writable.
@end defivar
@defivar Block end
The end address of the block. This attribute is not writable.
@end defivar
@defivar Block function
The name of the block represented as a @code{gdb.Symbol}. If the
block is not named, then this attribute holds @code{None}. This
attribute is not writable.
@end defivar
@defivar Block superblock
The block containing this block. If this parent block 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 every variable, function and type as an
entry in a symbol table. @xref{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
@defun lookup_symbol name [block] [domain]
This function searches for 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. It must be a string. The
optional @var{block} argument restricts the search 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 search 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
@code{name} or @code{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
@code{True} if the symbol is an argument of a function.
@end defivar
@defivar Symbol is_constant
@code{True} if the symbol is a constant.
@end defivar
@defivar Symbol is_function
@code{True} if the symbol is a function or a method.
@end defivar
@defivar Symbol is_variable
@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. This value is at the offset stored within the
symbol inside the frame's argument list.
@findex SYMBOL_LOC_REF_ARG
@findex gdb.SYMBOL_LOC_REF_ARG
@item SYMBOL_LOC_REF_ARG
Value address is stored in the frame's argument list. Just like
@code{LOC_ARG} except that the value's address is stored at the
offset, not the value itself.
@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}. Symbol table and line data for a frame is returned
from the @code{find_sal} method in @code{gdb.Frame} object.
@xref{Frames In Python}.
For more information on @value{GDBN}'s symbol table management, see
@ref{Symbols, ,Examining the Symbol Table}, for more information.
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 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 source absolute file name.
@end defmethod
@end table
@node Lazy Strings In Python

418
gdb/python/py-block.c Normal file
View File

@@ -0,0 +1,418 @@
/* 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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "block.h"
#include "dictionary.h"
#include "symtab.h"
#include "python-internal.h"
#include "objfiles.h"
#include "symtab.h"
typedef struct blpy_block_object {
PyObject_HEAD
/* The GDB block structure that represents a frame's code block. */
struct block *block;
/* The backing object file. There is no direct relationship in GDB
between a block and an object file. When a block is created also
store a pointer to the object file for later use. */
struct objfile *objfile;
/* Keep track of all blocks with a doubly-linked list. Needed for
block invalidation if the source object file has been freed. */
struct blpy_block_object *prev;
struct blpy_block_object *next;
} block_object;
typedef struct {
PyObject_HEAD
/* The block dictionary of symbols. */
struct dictionary *dict;
/* The iterator for that dictionary. */
struct dict_iterator iter;
/* Has the iterator been initialized flag. */
int initialized_p;
/* Pointer back to the original source block object. Needed to
check if the block is still valid, and has not been invalidated
when an object file has been freed. */
struct blpy_block_object *source;
} block_syms_iterator_object;
/* Require a valid block. All access to block_object->block should be
gated by this call. */
#define BLPY_REQUIRE_VALID(block_obj, block) \
do { \
block = block_object_to_block (block_obj); \
if (block == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Block is invalid.")); \
return NULL; \
} \
} while (0)
/* Require a valid block. This macro is called during block iterator
creation, and at each next call. */
#define BLPY_ITER_REQUIRE_VALID(block_obj) \
do { \
if (block_obj->block == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Source block for iterator is invalid.")); \
return NULL; \
} \
} while (0)
static PyTypeObject block_syms_iterator_object_type;
static const struct objfile_data *blpy_objfile_data_key;
static PyObject *
blpy_iter (PyObject *self)
{
block_syms_iterator_object *block_iter_obj;
struct block *block = NULL;
BLPY_REQUIRE_VALID (self, block);
block_iter_obj = PyObject_New (block_syms_iterator_object,
&block_syms_iterator_object_type);
if (block_iter_obj == NULL)
return NULL;
block_iter_obj->dict = BLOCK_DICT (block);
block_iter_obj->initialized_p = 0;
Py_INCREF (self);
block_iter_obj->source = (block_object *) self;
return (PyObject *) block_iter_obj;
}
static PyObject *
blpy_get_start (PyObject *self, void *closure)
{
struct block *block = NULL;
BLPY_REQUIRE_VALID (self, block);
return PyLong_FromUnsignedLongLong (BLOCK_START (block));
}
static PyObject *
blpy_get_end (PyObject *self, void *closure)
{
struct block *block = NULL;
BLPY_REQUIRE_VALID (self, block);
return PyLong_FromUnsignedLongLong (BLOCK_END (block));
}
static PyObject *
blpy_get_function (PyObject *self, void *closure)
{
struct symbol *sym;
struct block *block = NULL;
BLPY_REQUIRE_VALID (self, block);
sym = BLOCK_FUNCTION (block);
if (sym)
return symbol_to_symbol_object (sym);
Py_RETURN_NONE;
}
static PyObject *
blpy_get_superblock (PyObject *self, void *closure)
{
struct block *block = NULL;
struct block *super_block = NULL;
block_object *self_obj = (block_object *) self;
BLPY_REQUIRE_VALID (self, block);
super_block = BLOCK_SUPERBLOCK (block);
if (super_block)
return block_to_block_object (super_block, self_obj->objfile);
Py_RETURN_NONE;
}
static void
blpy_dealloc (PyObject *obj)
{
block_object *block = (block_object *) obj;
if (block->prev)
block->prev->next = block->next;
else if (block->objfile)
{
set_objfile_data (block->objfile, blpy_objfile_data_key,
block->next);
}
if (block->next)
block->next->prev = block->prev;
block->block = NULL;
}
/* Given a block, and a block_object that has previously been
allocated and initialized, populate the block_object with the
struct block data. Also, register the block_object life-cycle
with the life-cycle of the the object file associated with this
block, if needed. */
static void
set_block (block_object *obj, struct block *block,
struct objfile *objfile)
{
obj->block = block;
obj->prev = NULL;
if (objfile)
{
obj->objfile = objfile;
obj->next = objfile_data (objfile, blpy_objfile_data_key);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (objfile, blpy_objfile_data_key, obj);
}
else
obj->next = NULL;
}
/* Create a new block object (gdb.Block) that encapsulates the struct
block object from GDB. */
PyObject *
block_to_block_object (struct block *block, struct objfile *objfile)
{
block_object *block_obj;
block_obj = PyObject_New (block_object, &block_object_type);
if (block_obj)
set_block (block_obj, block, objfile);
return (PyObject *) block_obj;
}
/* Return struct block reference that is wrapped by this object. */
struct block *
block_object_to_block (PyObject *obj)
{
if (! PyObject_TypeCheck (obj, &block_object_type))
return NULL;
return ((block_object *) obj)->block;
}
/* Return a reference to the block iterator. */
static PyObject *
blpy_block_syms_iter (PyObject *self)
{
block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
BLPY_ITER_REQUIRE_VALID (iter_obj->source);
Py_INCREF (self);
return self;
}
/* Return the next symbol in the iteration through the block's
dictionary. */
static PyObject *
blpy_block_syms_iternext (PyObject *self)
{
block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
struct symbol *sym;
BLPY_ITER_REQUIRE_VALID (iter_obj->source);
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));
if (sym == NULL)
{
PyErr_SetString (PyExc_StopIteration, "Symbol is null.");
return NULL;
}
return symbol_to_symbol_object (sym);
}
static void
blpy_block_syms_dealloc (PyObject *obj)
{
block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) obj;
Py_XDECREF (iter_obj->source);
}
/* 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;
struct obj_section *section;
struct symtab *symtab;
PyObject *sym_obj;
if (!PyArg_ParseTuple (args, "K", &pc))
return NULL;
section = find_pc_mapped_section (pc);
symtab = find_pc_sect_symtab (pc, section);
if (!symtab || symtab->objfile == NULL)
{
PyErr_SetString (PyExc_RuntimeError,
"Cannot locate object file for block.");
return NULL;
}
block = block_for_pc (pc);
if (block)
return block_to_block_object (block, symtab->objfile);
Py_RETURN_NONE;
}
/* This function is called when an objfile is about to be freed.
Invalidate the block as further actions on the block would result
in bad data. All access to obj->symbol should be gated by
BLPY_REQUIRE_VALID which will raise an exception on invalid
blocks. */
static void
del_objfile_blocks (struct objfile *objfile, void *datum)
{
block_object *obj = datum;
while (obj)
{
block_object *next = obj->next;
obj->block = NULL;
obj->objfile = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
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;
/* Register an objfile "free" callback so we can properly
invalidate blocks when an object file is about to be
deleted. */
blpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_blocks);
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*/
blpy_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*/
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*/
blpy_block_syms_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*/
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 */
};

View File

@@ -26,6 +26,8 @@
#include "stack.h"
#include "value.h"
#include "python-internal.h"
#include "symfile.h"
#include "objfiles.h"
typedef struct {
PyObject_HEAD
@@ -202,6 +204,64 @@ 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;
struct symtab_and_line sal;
TRY_CATCH (except, RETURN_MASK_ALL)
{
FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
find_frame_sal (frame, &sal);
block = block_for_pc (get_frame_address_in_block (frame));
}
GDB_PY_HANDLE_EXCEPTION (except);
if (!sal.symtab || !sal.symtab->objfile)
{
PyErr_SetString (PyExc_RuntimeError,
"Cannot locate object file for block.");
return NULL;
}
if (block)
return block_to_block_object (block, sal.symtab->objfile);
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 +356,30 @@ 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;
struct objfile *objfile = NULL;
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 +396,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 +451,26 @@ 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 +590,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 */
};

419
gdb/python/py-symbol.c Normal file
View File

@@ -0,0 +1,419 @@
/* 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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "block.h"
#include "exceptions.h"
#include "frame.h"
#include "symtab.h"
#include "python-internal.h"
#include "objfiles.h"
typedef struct sympy_symbol_object {
PyObject_HEAD
/* The GDB symbol structure this object is wrapping. */
struct symbol *symbol;
/* A symbol object is associated with an objfile, so keep track with
doubly-linked list, rooted in the objfile. This lets us
invalidate the underlying struct symbol when the objfile is
deleted. */
struct sympy_symbol_object *prev;
struct sympy_symbol_object *next;
} symbol_object;
/* Require a valid symbol. All access to symbol_object->symbol should be
gated by this call. */
#define SYMPY_REQUIRE_VALID(symbol_obj, symbol) \
do { \
symbol = symbol_object_to_symbol (symbol_obj); \
if (symbol == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Symbol is invalid.")); \
return NULL; \
} \
} while (0)
static const struct objfile_data *sympy_objfile_data_key;
static PyObject *
sympy_str (PyObject *self)
{
PyObject *result;
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
result = PyString_FromString (SYMBOL_PRINT_NAME (symbol));
return result;
}
static PyObject *
sympy_get_symtab (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return symtab_to_symtab_object (SYMBOL_SYMTAB (symbol));
}
static PyObject *
sympy_get_name (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return PyString_FromString (SYMBOL_NATURAL_NAME (symbol));
}
static PyObject *
sympy_get_linkage_name (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return PyString_FromString (SYMBOL_LINKAGE_NAME (symbol));
}
static PyObject *
sympy_get_print_name (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return sympy_str (self);
}
static PyObject *
sympy_get_addr_class (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return PyInt_FromLong (SYMBOL_CLASS (symbol));
}
static PyObject *
sympy_is_argument (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
SYMPY_REQUIRE_VALID (self, symbol);
return PyBool_FromLong (SYMBOL_IS_ARGUMENT (symbol));
}
static PyObject *
sympy_is_constant (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
enum address_class class;
SYMPY_REQUIRE_VALID (self, symbol);
class = SYMBOL_CLASS (symbol);
return PyBool_FromLong (class == LOC_CONST || class == LOC_CONST_BYTES);
}
static PyObject *
sympy_is_function (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
enum address_class class;
SYMPY_REQUIRE_VALID (self, symbol);
class = SYMBOL_CLASS (symbol);
return PyBool_FromLong (class == LOC_BLOCK);
}
static PyObject *
sympy_is_variable (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
enum address_class class;
SYMPY_REQUIRE_VALID (self, symbol);
class = SYMBOL_CLASS (symbol);
return PyBool_FromLong (!SYMBOL_IS_ARGUMENT (symbol)
&& (class == LOC_LOCAL || class == LOC_REGISTER
|| class == LOC_STATIC || class == LOC_COMPUTED
|| class == LOC_OPTIMIZED_OUT));
}
/* Given a symbol, and a symbol_object that has previously been
allocated and initialized, populate the symbol_object with the
struct symbol data. Also, register the symbol_object life-cycle
with the life-cycle of the the object file associated with this
symbol, if needed. */
static void
set_symbol (symbol_object *obj, struct symbol *symbol)
{
obj->symbol = symbol;
obj->prev = NULL;
if (SYMBOL_SYMTAB (symbol))
{
obj->next = objfile_data (SYMBOL_SYMTAB (symbol)->objfile,
sympy_objfile_data_key);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (SYMBOL_SYMTAB (symbol)->objfile,
sympy_objfile_data_key, obj);
}
else
obj->next = NULL;
}
/* Create a new symbol object (gdb.Symbol) that encapsulates the struct
symbol object from GDB. */
PyObject *
symbol_to_symbol_object (struct symbol *sym)
{
symbol_object *sym_obj;
sym_obj = PyObject_New (symbol_object, &symbol_object_type);
if (sym_obj)
set_symbol (sym_obj, sym);
return (PyObject *) sym_obj;
}
/* Return the symbol that is wrapped by this symbol object. */
struct symbol *
symbol_object_to_symbol (PyObject *obj)
{
if (! PyObject_TypeCheck (obj, &symbol_object_type))
return NULL;
return ((symbol_object *) obj)->symbol;
}
static void
sympy_dealloc (PyObject *obj)
{
symbol_object *sym_obj = (symbol_object *) obj;
if (sym_obj->prev)
sym_obj->prev->next = sym_obj->next;
else if (SYMBOL_SYMTAB (sym_obj->symbol))
{
set_objfile_data (SYMBOL_SYMTAB (sym_obj->symbol)->objfile,
sympy_objfile_data_key, sym_obj->next);
}
if (sym_obj->next)
sym_obj->next->prev = sym_obj->prev;
sym_obj->symbol = NULL;
}
/* 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)
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;
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol as further actions on the symbol would result
in bad data. All access to obj->symbol should be gated by
SYMPY_REQUIRE_VALID which will raise an exception on invalid
symbols. */
static void
del_objfile_symbols (struct objfile *objfile, void *datum)
{
symbol_object *obj = datum;
while (obj)
{
symbol_object *next = obj->next;
obj->symbol = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
void
gdbpy_initialize_symbols (void)
{
if (PyType_Ready (&symbol_object_type) < 0)
return;
/* Register an objfile "free" callback so we can properly
invalidate symbol when an object file that is about to be
deleted. */
sympy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_symbols);
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*/
sympy_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*/
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 */
};

523
gdb/python/py-symtab.c Normal file
View File

@@ -0,0 +1,523 @@
/* 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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "charset.h"
#include "symtab.h"
#include "source.h"
#include "python-internal.h"
#include "objfiles.h"
typedef struct stpy_symtab_object {
PyObject_HEAD
/* The GDB Symbol table structure. */
struct symtab *symtab;
/* A symtab object is associated with an objfile, so keep track with
a doubly-linked list, rooted in the objfile. This allows
invalidation of the underlying struct symtab when the objfile is
deleted. */
struct stpy_symtab_object *prev;
struct stpy_symtab_object *next;
} symtab_object;
static PyTypeObject symtab_object_type;
static const struct objfile_data *stpy_objfile_data_key;
/* Require a valid symbol table. All access to symtab_object->symtab
should be gated by this call. */
#define STPY_REQUIRE_VALID(symtab_obj, symtab) \
do { \
symtab = symtab_object_to_symtab (symtab_obj); \
if (symtab == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Symbol Table is invalid.")); \
return NULL; \
} \
} while (0)
typedef struct salpy_sal_object {
PyObject_HEAD
/* The GDB Symbol table structure. */
symtab_object *symtab;
/* The GDB Symbol table and line structure. */
struct symtab_and_line *sal;
/* A Symtab and line object is associated with an objfile, so keep
track with a doubly-linked list, rooted in the objfile. This
allows invalidation of the underlying struct symtab_and_line
when the objfile is deleted. */
struct salpy_sal_object *prev;
struct salpy_sal_object *next;
} sal_object;
static PyTypeObject sal_object_type;
static const struct objfile_data *salpy_objfile_data_key;
/* Require a valid symbol table and line object. All access to
sal_object->sal should be gated by this call. */
#define SALPY_REQUIRE_VALID(sal_obj, sal) \
do { \
sal = sal_object_to_symtab_and_line (sal_obj); \
if (sal == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Symbol Table and Line is invalid.")); \
return NULL; \
} \
} while (0)
static PyObject *
stpy_str (PyObject *self)
{
PyObject *result;
struct symtab *symtab = NULL;
STPY_REQUIRE_VALID (self, symtab);
result = PyString_FromString (symtab->filename);
return result;
}
static PyObject *
stpy_get_filename (PyObject *self, void *closure)
{
PyObject *str_obj;
struct symtab *symtab = NULL;
STPY_REQUIRE_VALID (self, symtab);
str_obj = PyString_Decode (symtab->filename,
strlen (symtab->filename),
host_charset (), NULL);
return str_obj;
}
static PyObject *
stpy_get_objfile (PyObject *self, void *closure)
{
struct symtab *symtab = NULL;
PyObject *result;
STPY_REQUIRE_VALID (self, symtab);
result = objfile_to_objfile_object (symtab->objfile);
Py_XINCREF (result);
return result;
}
static PyObject *
stpy_fullname (PyObject *self, PyObject *args)
{
char *fullname;
struct symtab *symtab = NULL;
STPY_REQUIRE_VALID (self, symtab);
fullname = symtab_to_fullname (symtab);
if (fullname)
return PyString_Decode (fullname, strlen (fullname),
host_charset (), NULL);
Py_RETURN_NONE;
}
static PyObject *
salpy_str (PyObject *self)
{
char *s, *filename;
sal_object *sal_obj;
PyObject *result;
struct symtab_and_line *sal = NULL;
SALPY_REQUIRE_VALID (self, sal);
sal_obj = (sal_object *) self;
filename = (sal_obj->symtab == (symtab_object *) Py_None)
? "<unknown>" : sal_obj->symtab->symtab->filename;
s = xstrprintf ("symbol and line for %s, line %d", filename,
sal->line);
result = PyString_FromString (s);
xfree (s);
return result;
}
static void
stpy_dealloc (PyObject *obj)
{
symtab_object *symtab = (symtab_object *) obj;
if (symtab->prev)
symtab->prev->next = symtab->next;
else if (symtab->symtab)
{
set_objfile_data (symtab->symtab->objfile,
stpy_objfile_data_key, symtab->next);
}
if (symtab->next)
symtab->next->prev = symtab->prev;
symtab->symtab = NULL;
}
static PyObject *
salpy_get_pc (PyObject *self, void *closure)
{
struct symtab_and_line *sal = NULL;
SALPY_REQUIRE_VALID (self, sal);
return PyLong_FromUnsignedLongLong (sal->pc);
}
static PyObject *
salpy_get_line (PyObject *self, void *closure)
{
struct symtab_and_line *sal = NULL;
SALPY_REQUIRE_VALID (self, sal);
return PyLong_FromUnsignedLongLong (sal->line);
}
static PyObject *
salpy_get_symtab (PyObject *self, void *closure)
{
struct symtab_and_line *sal;
sal_object *self_sal = (sal_object *) self;
SALPY_REQUIRE_VALID (self, sal);
Py_INCREF (self_sal->symtab);
return (PyObject *) self_sal->symtab;
}
static void
salpy_dealloc (PyObject *self)
{
sal_object *self_sal = (sal_object *) self;
if (self_sal->prev)
self_sal->prev->next = self_sal->next;
else if (self_sal->symtab != (symtab_object * ) Py_None)
set_objfile_data (self_sal->symtab->symtab->objfile,
salpy_objfile_data_key, self_sal->next);
if (self_sal->next)
self_sal->next->prev = self_sal->prev;
Py_DECREF (self_sal->symtab);
xfree (self_sal->sal);
self_sal->ob_type->tp_free (self);
}
/* Given a sal, and a sal_object that has previously been
allocated and initialized, populate the sal_object with the
struct sal data. Also, register the sal_object life-cycle with the
life-cycle of the the object file associated with this sal, if
needed. If a failure occurs during the sal population, this
function will return NULL. */
static int
set_sal (sal_object *sal_obj, struct symtab_and_line sal)
{
symtab_object *symtab_obj;
if (sal.symtab)
{
symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab);
/* If a symtab existed in the sal, but it cannot be duplicated,
we exit. */
if (symtab_obj == NULL)
return 0;
}
else
{
symtab_obj = (symtab_object *) Py_None;
Py_INCREF (Py_None);
}
sal_obj->sal = xmemdup (&sal, sizeof (struct symtab_and_line),
sizeof (struct symtab_and_line));
sal_obj->symtab = symtab_obj;
sal_obj->prev = NULL;
/* If the SAL does not have a symtab, we do not add it to the
objfile cleanup observer linked list. */
if (sal_obj->symtab != (symtab_object *)Py_None)
{
sal_obj->next = objfile_data (sal_obj->symtab->symtab->objfile,
salpy_objfile_data_key);
if (sal_obj->next)
sal_obj->next->prev = sal_obj;
set_objfile_data (sal_obj->symtab->symtab->objfile,
salpy_objfile_data_key, sal_obj);
}
else
sal_obj->next = NULL;
return 1;
}
/* Given a symtab, and a symtab_object that has previously been
allocated and initialized, populate the symtab_object with the
struct symtab data. Also, register the symtab_object life-cycle
with the life-cycle of the the object file associated with this
symtab, if needed. */
static void
set_symtab (symtab_object *obj, struct symtab *symtab)
{
obj->symtab = symtab;
obj->prev = NULL;
if (symtab)
{
obj->next = objfile_data (symtab->objfile, stpy_objfile_data_key);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (symtab->objfile, stpy_objfile_data_key, obj);
}
else
obj->next = NULL;
}
/* Create a new symbol table (gdb.Symtab) object that encapsulates the
symtab structure from GDB. */
PyObject *
symtab_to_symtab_object (struct symtab *symtab)
{
symtab_object *symtab_obj;
symtab_obj = PyObject_New (symtab_object, &symtab_object_type);
if (symtab_obj)
set_symtab (symtab_obj, symtab);
return (PyObject *) symtab_obj;
}
/* Create a new symtab and line (gdb.Symtab_and_line) object
that encapsulates the symtab_and_line structure from GDB. */
PyObject *
symtab_and_line_to_sal_object (struct symtab_and_line sal)
{
sal_object *sal_obj;
symtab_object *symtab_obj;
int success = 0;
sal_obj = PyObject_New (sal_object, &sal_object_type);
if (sal_obj)
{
success = set_sal (sal_obj, sal);
if (!success)
{
Py_DECREF (sal_obj);
return NULL;
}
}
return (PyObject *) sal_obj;
}
/* Return struct symtab_and_line reference that is wrapped by this
object. */
struct symtab_and_line *
sal_object_to_symtab_and_line (PyObject *obj)
{
if (! PyObject_TypeCheck (obj, &sal_object_type))
return NULL;
return ((sal_object *) obj)->sal;
}
/* Return struct symtab reference that is wrapped by this object. */
struct symtab *
symtab_object_to_symtab (PyObject *obj)
{
if (! PyObject_TypeCheck (obj, &symtab_object_type))
return NULL;
return ((symtab_object *) obj)->symtab;
}
/* This function is called when an objfile is about to be freed.
Invalidate the symbol table as further actions on the symbol table
would result in bad data. All access to obj->symtab should be
gated by STPY_REQUIRE_VALID which will raise an exception on
invalid symbol tables. */
static void
del_objfile_symtab (struct objfile *objfile, void *datum)
{
symtab_object *obj = datum;
while (obj)
{
symtab_object *next = obj->next;
obj->symtab = NULL;
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
}
/* This function is called when an objfile is about to be freed.
Invalidate the sal object as further actions on the sal
would result in bad data. All access to obj->sal should be
gated by SALPY_REQUIRE_VALID which will raise an exception on
invalid symbol table and line objects. */
static void
del_objfile_sal (struct objfile *objfile, void *datum)
{
sal_object *obj = datum;
while (obj)
{
sal_object *next = obj->next;
obj->symtab = NULL;
obj->next = NULL;
obj->prev = NULL;
xfree (obj->sal);
obj->sal = NULL;
obj = next;
}
}
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;
/* Register an objfile "free" callback so we can properly
invalidate symbol tables, and symbol table and line data
structures when an object file that is about to be
deleted. */
stpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_symtab);
salpy_objfile_data_key
= register_objfile_data_with_cleanup (NULL, del_objfile_sal);
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,
"fullname () -> String.\n\
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*/
stpy_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*/
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 */
};

View File

@@ -61,32 +61,51 @@ 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, struct objfile *objfile);
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);
struct symtab *symtab_object_to_symtab (PyObject *obj);
struct symtab_and_line *sal_object_to_symtab_and_line (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);

View File

@@ -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."

View File

@@ -1,3 +1,12 @@
2010-02-24 Phil Muldoon <pmuldoon@redhat.com>
* 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.
2010-02-24 Phil Muldoon <pmuldoon@redhat.com>
PR python/11314

View File

@@ -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 $@..."

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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. */
}

View File

@@ -0,0 +1,79 @@
# 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 <http://www.gnu.org/licenses/>.
# 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}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
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" "<gdb.Block object at $hex>" "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" "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" "<gdb.Block object at $hex>" "Check block not None"
gdb_test "python print block.function" "main" "main block"

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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. */
}

View File

@@ -0,0 +1,132 @@
# 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 <http://www.gnu.org/licenses/>.
# 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}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
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" "gdb.python/py-symbol.c.*" "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"

View File

@@ -0,0 +1,73 @@
# 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 <http://www.gnu.org/licenses/>.
# 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}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
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" "<gdb.Objfile object at ${hex}>" "Test symtab.objfile"
gdb_test "python print symtab.fullname()" "testsuite/gdb.python/py-symbol.c.*" "Test symtab.fullname"