diff options
author | Phil Muldoon <pmuldoon@redhat.com> | 2010-02-24 21:18:28 +0000 |
---|---|---|
committer | Phil Muldoon <pmuldoon@redhat.com> | 2010-02-24 21:18:28 +0000 |
commit | f3e9a8177c41893858fce2bdf339dbe90b3a4ef5 (patch) | |
tree | ace904e14067df9b07c95ad1b45fbb079b6ab54e /gdb/python | |
parent | 101654612f383f5427e2d727556eda80537de76b (diff) | |
download | gdb-f3e9a8177c41893858fce2bdf339dbe90b3a4ef5.zip gdb-f3e9a8177c41893858fce2bdf339dbe90b3a4ef5.tar.gz gdb-f3e9a8177c41893858fce2bdf339dbe90b3a4ef5.tar.bz2 |
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.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/py-block.c | 418 | ||||
-rw-r--r-- | gdb/python/py-frame.c | 119 | ||||
-rw-r--r-- | gdb/python/py-symbol.c | 419 | ||||
-rw-r--r-- | gdb/python/py-symtab.c | 523 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 19 | ||||
-rw-r--r-- | gdb/python/python.c | 12 |
6 files changed, 1508 insertions, 2 deletions
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c new file mode 100644 index 0000000..3523664 --- /dev/null +++ b/gdb/python/py-block.c @@ -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 */ +}; diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index 334bad9..94211db 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -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 */ }; diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c new file mode 100644 index 0000000..e4c5fef --- /dev/null +++ b/gdb/python/py-symbol.c @@ -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 */ +}; diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c new file mode 100644 index 0000000..f91f322 --- /dev/null +++ b/gdb/python/py-symtab.c @@ -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 */ +}; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 1bfa700..c48c354 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -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); diff --git a/gdb/python/python.c b/gdb/python/python.c index 29386c9..3d38de6 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -644,6 +644,9 @@ Enables or disables auto-loading of Python code when an object is opened."), gdbpy_initialize_values (); gdbpy_initialize_frames (); gdbpy_initialize_commands (); + gdbpy_initialize_symbols (); + gdbpy_initialize_symtabs (); + gdbpy_initialize_blocks (); gdbpy_initialize_functions (); gdbpy_initialize_types (); gdbpy_initialize_objfile (); @@ -724,7 +727,14 @@ Return a string explaining unwind stop reason." }, METH_VARARGS | METH_KEYWORDS, "lookup_type (name [, block]) -> type\n\ Return a Type corresponding to the given name." }, - + { "lookup_symbol", (PyCFunction) gdbpy_lookup_symbol, + METH_VARARGS | METH_KEYWORDS, + "lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)\n\ +Return a tuple with the symbol corresponding to the given name (or None) and\n\ +a boolean indicating if name is a field of the current implied argument\n\ +`this' (when the current language is object-oriented)." }, + { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS, + "Return the block containing the given pc value, or None." }, { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS, "parse_and_eval (String) -> Value.\n\ Parse String as an expression, evaluate it, and return the result as a Value." |