mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-16 04:18:50 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
5
gdb/NEWS
5
gdb/NEWS
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
418
gdb/python/py-block.c
Normal 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 */
|
||||
};
|
||||
@@ -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
419
gdb/python/py-symbol.c
Normal 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
523
gdb/python/py-symtab.c
Normal 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 */
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 $@..."
|
||||
|
||||
41
gdb/testsuite/gdb.python/py-block.c
Normal file
41
gdb/testsuite/gdb.python/py-block.c
Normal 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. */
|
||||
}
|
||||
79
gdb/testsuite/gdb.python/py-block.exp
Normal file
79
gdb/testsuite/gdb.python/py-block.exp
Normal 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"
|
||||
62
gdb/testsuite/gdb.python/py-symbol.c
Normal file
62
gdb/testsuite/gdb.python/py-symbol.c
Normal 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. */
|
||||
}
|
||||
132
gdb/testsuite/gdb.python/py-symbol.exp
Normal file
132
gdb/testsuite/gdb.python/py-symbol.exp
Normal 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"
|
||||
73
gdb/testsuite/gdb.python/py-symtab.exp
Normal file
73
gdb/testsuite/gdb.python/py-symtab.exp
Normal 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"
|
||||
Reference in New Issue
Block a user