2013-11-11 Phil Muldoon <pmuldoon@redhat.com>

PR python/15629
	* NEWS: Add linetable feature.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add py-linetable entries.
	* python/py-linetable.c: New file.
	* python/py-symtab.c (stpy_get_linetable): New function.
	* python/python-internal.h (symtab_to_linetable_object): Declare.
	(gdbpy_initialize_linetable): Ditto.
	* python/python.c (_initialize_python): Call
	gdbpy_initialize_linetable.

2013-11-11  Phil Muldoon  <pmuldoon@redhat.com>

 	* gdb.python/py-linetable.S: New file.
	* gdb.python/py-linetable.c: New file.
 	* gdb.python/py-linetable.exp: New file.

2013-11-11  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.texinfo (Symbol Tables In Python): Add linetable method entry.
	(Line Tables In Python): New node.
This commit is contained in:
Phil Muldoon 2013-11-11 19:49:45 +00:00
parent 67dc82bc51
commit bc79de95db
13 changed files with 1241 additions and 1 deletions

View File

@ -1,3 +1,15 @@
2013-11-11 Phil Muldoon <pmuldoon@redhat.com>
PR python/15629
* NEWS: Add linetable feature.
* Makefile.in (SUBDIR_PYTHON_OBS): Add py-linetable entries.
* python/py-linetable.c: New file.
* python/py-symtab.c (stpy_get_linetable): New function.
* python/python-internal.h (symtab_to_linetable_object): Declare.
(gdbpy_initialize_linetable): Ditto.
* python/python.c (_initialize_python): Call
gdbpy_initialize_linetable.
2013-11-11 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (create_ada_exception_catchpoint): Enhance

View File

@ -299,6 +299,7 @@ SUBDIR_PYTHON_OBS = \
py-inferior.o \
py-infthread.o \
py-lazy-string.o \
py-linetable.o \
py-newobjfileevent.o \
py-objfile.o \
py-param.o \
@ -334,6 +335,7 @@ SUBDIR_PYTHON_SRCS = \
python/py-inferior.c \
python/py-infthread.c \
python/py-lazy-string.c \
python/py-linetable.c \
python/py-newobjfileevent.c \
python/py-objfile.c \
python/py-param.c \
@ -2227,6 +2229,10 @@ py-lazy-string.o: $(srcdir)/python/py-lazy-string.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-lazy-string.c
$(POSTCOMPILE)
py-linetable.o: $(srcdir)/python/py-linetable.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-linetable.c
$(POSTCOMPILE)
py-newobjfileevent.o: $(srcdir)/python/py-newobjfileevent.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-newobjfileevent.c
$(POSTCOMPILE)

View File

@ -36,6 +36,7 @@
** Frame filters and frame decorators have been added.
** Temporary breakpoints are now supported.
** Line tables representation has been added.
* New targets

View File

@ -1,3 +1,8 @@
2013-11-11 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Symbol Tables In Python): Add linetable method entry.
(Line Tables In Python): New node.
2013-11-08 Doug Evans <dje@google.com>
* gdb.texinfo (Debugging Output): Update text for

View File

@ -23487,6 +23487,7 @@ optional arguments while skipping others. Example:
* Blocks In Python:: Accessing blocks from Python.
* Symbols In Python:: Python representation of symbols.
* Symbol Tables In Python:: Python representation of symbol tables.
* Line Tables In Python:: Python representation of line tables.
* Breakpoints In Python:: Manipulating breakpoints using Python.
* Finish Breakpoints in Python:: Setting Breakpoints on function return
using Python.
@ -27027,6 +27028,89 @@ Return the static block of the underlying symbol table.
@xref{Blocks In Python}.
@end defun
@defun Symtab.linetable ()
Return the line table associated with the symbol table.
@xref{Line Tables In Python}.
@end defun
@node Line Tables In Python
@subsubsection Manipulating line tables using Python
@cindex line tables in python
@tindex gdb.LineTable
Python code can request and inspect line table information from a
symbol table that is loaded in @value{GDBN}. A line table is a
mapping of source lines to their executable locations in memory. To
acquire the line table information for a particular symbol table, use
the @code{linetable} function (@pxref{Symbol Tables In Python}).
A @code{gdb.LineTable} is iterable. The iterator returns
@code{LineTableEntry} objects that correspond to the source line and
address for each line table entry. @code{LineTableEntry} objects have
the following attributes:
@defvar LineTableEntry.line
The source line number for this line table entry. This number
corresponds to the actual line of source. This attribute is not
writable.
@end defvar
@defvar LineTableEntry.pc
The address that is associated with the line table entry where the
executable code for that source line resides in memory. This
attribute is not writable.
@end defvar
As there can be multiple addresses for a single source line, you may
receive multiple @code{LineTableEntry} objects with matching
@code{line} attributes, but with different @code{pc} attributes. The
iterator is sorted in ascending @code{pc} order. Here is a small
example illustrating iterating over a line table.
@smallexample
symtab = gdb.selected_frame().find_sal().symtab
linetable = symtab.linetable()
for line in linetable:
print "Line: "+str(line.line)+" Address: "+hex(line.pc)
@end smallexample
This will have the following output:
@smallexample
Line: 33 Address: 0x4005c8L
Line: 37 Address: 0x4005caL
Line: 39 Address: 0x4005d2L
Line: 40 Address: 0x4005f8L
Line: 42 Address: 0x4005ffL
Line: 44 Address: 0x400608L
Line: 42 Address: 0x40060cL
Line: 45 Address: 0x400615L
@end smallexample
In addition to being able to iterate over a @code{LineTable}, it also
has the following direct access methods:
@defun LineTable.line (line)
Return a Python @code{Tuple} of @code{LineTableEntry} objects for any
entries in the line table for the given @var{line}. @var{line} refers
to the source code line. If there are no entries for that source code
@var{line}, the Python @code{None} is returned.
@end defun
@defun LineTable.has_line (line)
Return a Python @code{Boolean} indicating whether there is an entry in
the line table for this source line. Return @code{True} if an entry
is found, or @code{False} if not.
@end defun
@defun LineTable.source_lines ()
Return a Python @code{List} of the source line numbers in the symbol
table. Only lines with executable code locations are returned. The
contents of the @code{List} will just be the source line entries
represented as Python @code{Long} values.
@end defun
@node Breakpoints In Python
@subsubsection Manipulating breakpoints using Python

622
gdb/python/py-linetable.c Normal file
View File

@ -0,0 +1,622 @@
/* Python interface to line tables.
Copyright (C) 2013 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 "python-internal.h"
#include "exceptions.h"
typedef struct {
PyObject_HEAD
/* The line table source line. */
int line;
/* The pc associated with the source line. */
CORE_ADDR pc;
} linetable_entry_object;
static PyTypeObject linetable_entry_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");
typedef struct {
PyObject_HEAD
/* The symtab python object. We store the Python object here as the
underlying symtab can become invalid, and we have to run validity
checks on it. */
PyObject *symtab;
} linetable_object;
static PyTypeObject linetable_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_object");
typedef struct {
PyObject_HEAD
/* The current entry in the line table for the iterator */
int current_index;
/* Pointer back to the original source line table object. Needed to
check if the line table is still valid, and has not been invalidated
when an object file has been freed. */
PyObject *source;
} ltpy_iterator_object;
static PyTypeObject ltpy_iterator_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");
/* Internal helper function to extract gdb.Symtab from a gdb.Linetable
object. */
static PyObject *
get_symtab (PyObject *linetable)
{
linetable_object *lt = (linetable_object *) linetable;
return lt->symtab;
}
#define LTPY_REQUIRE_VALID(lt_obj, symtab) \
do { \
symtab = symtab_object_to_symtab (get_symtab (lt_obj)); \
if (symtab == NULL) \
{ \
PyErr_SetString (PyExc_RuntimeError, \
_("Symbol Table in line table is invalid."));\
return NULL; \
} \
} while (0)
/* Helper function to create a line table object that wraps a
gdb.Symtab object. */
PyObject *
symtab_to_linetable_object (PyObject *symtab)
{
linetable_object *ltable;
ltable = PyObject_New (linetable_object, &linetable_object_type);
if (ltable != NULL)
{
ltable->symtab = symtab;
Py_INCREF (symtab);
}
return (PyObject *) ltable;
}
/* Internal helper function to build a line table object from a line
and an address. */
static PyObject *
build_linetable_entry (int line, CORE_ADDR address)
{
linetable_entry_object *obj;
obj = PyObject_New (linetable_entry_object,
&linetable_entry_object_type);
if (obj != NULL)
{
obj->line = line;
obj->pc = address;
}
return (PyObject *) obj;
}
/* Internal helper function to build a Python Tuple from a GDB Vector.
A line table entry can have multiple PCs for a given source line.
Construct a Tuple of all entries for the given source line, LINE
from the line table VEC. Construct one line table entry object per
address. */
static PyObject *
build_line_table_tuple_from_pcs (int line, VEC (CORE_ADDR) *vec)
{
int vec_len = 0;
PyObject *tuple;
CORE_ADDR pc;
int i;
vec_len = VEC_length (CORE_ADDR, vec);
if (vec_len < 1)
Py_RETURN_NONE;
tuple = PyTuple_New (vec_len);
if (tuple == NULL)
return NULL;
for (i = 0; VEC_iterate (CORE_ADDR, vec, i, pc); ++i)
{
PyObject *obj = build_linetable_entry (line, pc);
if (obj == NULL)
{
Py_DECREF (tuple);
tuple = NULL;
break;
}
else if (PyTuple_SetItem (tuple, i, obj) != 0)
{
Py_DECREF (obj);
Py_DECREF (tuple);
tuple = NULL;
break;
}
}
return tuple;
}
/* Implementation of gdb.LineTable.line (self) -> Tuple. Returns a
tuple of LineTableEntry objects associated with this line from the
in the line table. */
static PyObject *
ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
{
struct symtab *symtab;
int py_line;
struct linetable_entry *best_entry = NULL;
linetable_entry_object *result;
VEC (CORE_ADDR) *pcs = NULL;
PyObject *tuple;
volatile struct gdb_exception except;
LTPY_REQUIRE_VALID (self, symtab);
if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
return NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
}
GDB_PY_HANDLE_EXCEPTION (except);
tuple = build_line_table_tuple_from_pcs (py_line, pcs);
VEC_free (CORE_ADDR, pcs);
return tuple;
}
/* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
Returns a Python Boolean indicating whether a source line has any
line table entries corresponding to it. */
static PyObject *
ltpy_has_line (PyObject *self, PyObject *args)
{
struct symtab *symtab;
int py_line;
int index;
LTPY_REQUIRE_VALID (self, symtab);
if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
return NULL;
if (LINETABLE (symtab) == NULL)
{
PyErr_SetString (PyExc_RuntimeError,
_("Linetable information not found in symbol table"));
return NULL;
}
for (index = 0; index <= LINETABLE (symtab)->nitems; index++)
{
struct linetable_entry *item = &(symtab->linetable->item[index]);
if (item->line == py_line)
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
/* Implementation of gdb.LineTable.source_lines (self) -> FrozenSet.
Returns a Python FrozenSet that contains source line entries in the
line table. This function will just return the source lines
without corresponding addresses. */
static PyObject *
ltpy_get_all_source_lines (PyObject *self, PyObject *args)
{
struct symtab *symtab;
Py_ssize_t index;
PyObject *source_list, *source_dict, *line;
struct linetable_entry *item;
Py_ssize_t list_size;
LTPY_REQUIRE_VALID (self, symtab);
if (LINETABLE (symtab) == NULL)
{
PyErr_SetString (PyExc_RuntimeError,
_("Linetable information not found in symbol table"));
return NULL;
}
source_dict = PyDict_New ();
if (source_dict == NULL)
return NULL;
for (index = 0; index <= LINETABLE (symtab)->nitems; index++)
{
item = &(LINETABLE (symtab)->item[index]);
/* 0 is used to signify end of line table information. Do not
include in the source set. */
if (item->line > 0)
{
line = gdb_py_object_from_longest (item->line);
if (line == NULL)
{
Py_DECREF (source_dict);
return NULL;
}
if (PyDict_SetItem (source_dict, line, Py_None) == -1)
{
Py_DECREF (line);
Py_DECREF (source_dict);
return NULL;
}
Py_DECREF (line);
}
}
source_list = PyDict_Keys (source_dict);
Py_DECREF (source_dict);
return source_list;
}
/* Implementation of gdb.Linetable.is_valid (self) -> Boolean.
Returns True if this line table object still exists in GDB. */
static PyObject *
ltpy_is_valid (PyObject *self, PyObject *args)
{
struct symtab *symtab = NULL;
linetable_object *obj = (linetable_object *) self;
symtab = symtab_object_to_symtab (get_symtab (self));
if (symtab == NULL)
Py_RETURN_FALSE;
Py_RETURN_TRUE;
}
/* Deconstructor for the line table object. Decrement the reference
to the symbol table object before calling the default free. */
static void
ltpy_dealloc (PyObject *self)
{
linetable_object *obj = (linetable_object *) self;
Py_DECREF (obj->symtab);
Py_TYPE (self)->tp_free (self);
}
/* Initialize LineTable, LineTableEntry and LineTableIterator
objects. */
int
gdbpy_initialize_linetable (void)
{
if (PyType_Ready (&linetable_object_type) < 0)
return -1;
if (PyType_Ready (&linetable_entry_object_type) < 0)
return -1;
if (PyType_Ready (&ltpy_iterator_object_type) < 0)
return -1;
Py_INCREF (&linetable_object_type);
Py_INCREF (&linetable_entry_object_type);
Py_INCREF (&ltpy_iterator_object_type);
if (gdb_pymodule_addobject (gdb_module, "LineTable",
(PyObject *) &linetable_object_type) < 0)
return -1;
if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
(PyObject *) &linetable_entry_object_type) < 0)
return -1;
if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
(PyObject *) &ltpy_iterator_object_type) < 0)
return -1;
return 0;
}
/* Linetable entry object get functions. */
/* Implementation of gdb.LineTableEntry.line (self) -> Long. Returns
a long integer associated with the line table entry. */
static PyObject *
ltpy_entry_get_line (PyObject *self, void *closure)
{
linetable_entry_object *obj = (linetable_entry_object *) self;
return gdb_py_object_from_longest (obj->line);
}
/* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
a long integer associated with the PC of the line table entry. */
static PyObject *
ltpy_entry_get_pc (PyObject *self, void *closure)
{
linetable_entry_object *obj = (linetable_entry_object *) self;
return gdb_py_object_from_longest (obj->pc);
}
/* Linetable iterator functions. */
/* Return a new line table iterator. */
static PyObject *
ltpy_iter (PyObject *self)
{
ltpy_iterator_object *ltpy_iter_obj;
struct symtab *symtab = NULL;
LTPY_REQUIRE_VALID (self, symtab);
ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
&ltpy_iterator_object_type);
if (ltpy_iter_obj == NULL)
return NULL;
ltpy_iter_obj->current_index = 0;
ltpy_iter_obj->source = self;
Py_INCREF (self);
return (PyObject *) ltpy_iter_obj;
}
static void
ltpy_iterator_dealloc (PyObject *obj)
{
ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;
Py_DECREF (iter_obj->source);
}
/* Return a reference to the line table iterator. */
static PyObject *
ltpy_iterator (PyObject *self)
{
ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
struct symtab *symtab;
LTPY_REQUIRE_VALID (iter_obj->source, symtab);
Py_INCREF (self);
return self;
}
/* Return the next line table entry in the iteration through the line
table data structure. */
static PyObject *
ltpy_iternext (PyObject *self)
{
ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
struct symtab *symtab;
int index;
PyObject *obj;
struct linetable_entry *item;
LTPY_REQUIRE_VALID (iter_obj->source, symtab);
if (iter_obj->current_index >= LINETABLE (symtab)->nitems)
goto stop_iteration;
item = &(LINETABLE (symtab)->item[iter_obj->current_index]);
/* Skip over internal entries such as 0. 0 signifies the end of
line table data and is not useful to the API user. */
while (item->line < 1)
{
iter_obj->current_index++;
/* Exit if the internal value is the last item in the line table. */
if (iter_obj->current_index >= symtab->linetable->nitems)
goto stop_iteration;
item = &(symtab->linetable->item[iter_obj->current_index]);
}
obj = build_linetable_entry (item->line, item->pc);
iter_obj->current_index++;
return obj;
stop_iteration:
PyErr_SetNone (PyExc_StopIteration);
return NULL;
}
/* Implementation of gdb.LinetableIterator.is_valid (self) -> Boolean.
Returns True if this line table iterator object still exists in
GDB. */
static PyObject *
ltpy_iter_is_valid (PyObject *self, PyObject *args)
{
struct symtab *symtab = NULL;
ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));
if (symtab == NULL)
Py_RETURN_FALSE;
Py_RETURN_TRUE;
}
static PyMethodDef linetable_object_methods[] = {
{ "line", ltpy_get_pcs_for_line, METH_VARARGS,
"line (lineno) -> Tuple\n\
Return executable locations for a given source line." },
{ "has_line", ltpy_has_line, METH_VARARGS,
"has_line (lineno) -> Boolean\n\
Return TRUE if this line has executable information, FALSE if not." },
{ "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
"source_lines () -> FrozenSet\n\
Return a frozen set of all executable source lines." },
{ "is_valid", ltpy_is_valid, METH_NOARGS,
"is_valid () -> Boolean.\n\
Return True if this Linetable is valid, False if not." },
{NULL} /* Sentinel */
};
static PyTypeObject linetable_object_type = {
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.LineTable", /*tp_name*/
sizeof (linetable_object), /*tp_basicsize*/
0, /*tp_itemsize*/
ltpy_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, /*tp_flags*/
"GDB line table object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
ltpy_iter, /* tp_iter */
0, /* tp_iternext */
linetable_object_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
};
static PyMethodDef ltpy_iterator_methods[] = {
{ "is_valid", ltpy_iter_is_valid, METH_NOARGS,
"is_valid () -> Boolean.\n\
Return True if this Linetable iterator is valid, False if not." },
{NULL} /* Sentinel */
};
static PyTypeObject ltpy_iterator_object_type = {
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.LineTableIterator", /*tp_name*/
sizeof (ltpy_iterator_object), /*tp_basicsize*/
0, /*tp_itemsize*/
ltpy_iterator_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 line table iterator object", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
ltpy_iterator, /*tp_iter */
ltpy_iternext, /*tp_iternext */
ltpy_iterator_methods /*tp_methods */
};
static PyGetSetDef linetable_entry_object_getset[] = {
{ "line", ltpy_entry_get_line, NULL,
"The line number in the source file.", NULL },
{ "pc", ltpy_entry_get_pc, NULL,
"The memory address for this line number.", NULL },
{ NULL } /* Sentinel */
};
static PyTypeObject linetable_entry_object_type = {
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.LineTableEntry", /*tp_name*/
sizeof (linetable_entry_object), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"GDB line table entry 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 */
linetable_entry_object_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
};

View File

@ -186,6 +186,20 @@ stpy_static_block (PyObject *self, PyObject *args)
return block_to_block_object (block, symtab->objfile);
}
/* Implementation of gdb.Symtab.linetable (self) -> gdb.Linetable.
Returns a gdb.Linetable object corresponding to this symbol
table. */
static PyObject *
stpy_get_linetable (PyObject *self, PyObject *args)
{
struct symtab *symtab = NULL;
STPY_REQUIRE_VALID (self, symtab);
return symtab_to_linetable_object (self);
}
static PyObject *
salpy_str (PyObject *self)
{
@ -532,6 +546,9 @@ Return the global block of the symbol table." },
{ "static_block", stpy_static_block, METH_NOARGS,
"static_block () -> gdb.Block.\n\
Return the static block of the symbol table." },
{ "linetable", stpy_get_linetable, METH_NOARGS,
"linetable () -> gdb.Linetable.\n\
Return the Linetable associated with this symbol table" },
{NULL} /* Sentinel */
};

View File

@ -311,7 +311,7 @@ PyObject *block_to_block_object (const struct block *block,
PyObject *value_to_value_object (struct value *v);
PyObject *type_to_type_object (struct type *);
PyObject *frame_info_to_frame_object (struct frame_info *frame);
PyObject *symtab_to_linetable_object (PyObject *symtab);
PyObject *pspace_to_pspace_object (struct program_space *)
CPYCHECKER_RETURNS_BORROWED_REF;
PyObject *pspy_get_printers (PyObject *, void *);
@ -371,6 +371,8 @@ int gdbpy_initialize_finishbreakpoints (void)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
int gdbpy_initialize_lazy_string (void)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
int gdbpy_initialize_linetable (void)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
int gdbpy_initialize_parameters (void)
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
int gdbpy_initialize_thread (void)

View File

@ -1673,6 +1673,7 @@ message == an error message without a stack will be printed."),
|| gdbpy_initialize_breakpoints () < 0
|| gdbpy_initialize_finishbreakpoints () < 0
|| gdbpy_initialize_lazy_string () < 0
|| gdbpy_initialize_linetable () < 0
|| gdbpy_initialize_thread () < 0
|| gdbpy_initialize_inferior () < 0
|| gdbpy_initialize_events () < 0

View File

@ -1,3 +1,9 @@
2013-11-11 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-linetable.S: New file.
* gdb.python/py-linetable.c: New file.
* gdb.python/py-linetable.exp: New file.
2013-11-11 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/mi_ex_cond: New testcase.

View File

@ -0,0 +1,362 @@
/* Copyright (C) 2013 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/>. */
.file "py-linetable.c"
.text
.Ltext0:
.globl foo
.type foo, @function
foo:
.LFB0:
.file 1 "./py-linetable.c"
.loc 1 20 0
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
.loc 1 21 0
movl -4(%rbp), %eax
cmpl -8(%rbp), %eax
jne .L2
.loc 1 22 0
movl $1, %eax
jmp .L3
.L2:
.loc 1 24 0
movl $0, %eax
.L3:
.loc 1 25 0
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.globl bar
.type bar, @function
bar:
.LFB1:
.loc 1 28 0
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
.loc 1 29 0
cmpl $0, -8(%rbp)
jne .L5
.loc 1 30 0
movl $1, %eax
jmp .L6
.L5:
.loc 1 32 0
movl $0, %eax
.L6:
.loc 1 33 0
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size bar, .-bar
.globl main
.type main, @function
main:
.LFB2:
.loc 1 37 0
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
.loc 1 39 0
movl $5, %esi
movl $5, %edi
call foo
testl %eax, %eax
je .L8
.loc 1 39 0 is_stmt 0 discriminator 1
movl $0, %esi
movl $5, %edi
call bar
testl %eax, %eax
je .L8
.loc 1 40 0 is_stmt 1
movl $0, %eax
jmp .L9
.L8:
.loc 1 42 0
movl $0, -4(%rbp)
jmp .L10
.L11:
.loc 1 44 0
addl $1, -4(%rbp)
.L10:
.loc 1 42 0 discriminator 1
cmpl $499, -4(%rbp)
jle .L11
.loc 1 45 0
movl $0, %eax
.L9:
.loc 1 46 0
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE2:
.size main, .-main
.Letext0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.long 0xcf
.value 0x4
.long .Ldebug_abbrev0
.byte 0x8
.uleb128 0x1
.long .LASF0
.byte 0x1
.long .LASF1
.long .LASF2
.quad .Ltext0
.quad .Letext0
.long .Ldebug_line0
.uleb128 0x2
.string "foo"
.byte 0x1
.byte 0x13
.long 0x67
.quad .LFB0
.quad .LFE0
.uleb128 0x1
.byte 0x9c
.long 0x67
.uleb128 0x3
.string "a"
.byte 0x1
.byte 0x13
.long 0x67
.uleb128 0x2
.byte 0x91
.sleb128 -20
.uleb128 0x3
.string "b"
.byte 0x1
.byte 0x13
.long 0x67
.uleb128 0x2
.byte 0x91
.sleb128 -24
.byte 0
.uleb128 0x4
.byte 0x4
.byte 0x5
.string "int"
.uleb128 0x2
.string "bar"
.byte 0x1
.byte 0x1b
.long 0x67
.quad .LFB1
.quad .LFE1
.uleb128 0x1
.byte 0x9c
.long 0xa8
.uleb128 0x3
.string "a"
.byte 0x1
.byte 0x1b
.long 0x67
.uleb128 0x2
.byte 0x91
.sleb128 -20
.uleb128 0x3
.string "b"
.byte 0x1
.byte 0x1b
.long 0x67
.uleb128 0x2
.byte 0x91
.sleb128 -24
.byte 0
.uleb128 0x5
.long .LASF3
.byte 0x1
.byte 0x24
.long 0x67
.quad .LFB2
.quad .LFE2
.uleb128 0x1
.byte 0x9c
.uleb128 0x6
.string "i"
.byte 0x1
.byte 0x26
.long 0x67
.uleb128 0x2
.byte 0x91
.sleb128 -20
.byte 0
.byte 0
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.uleb128 0x1
.uleb128 0x11
.byte 0x1
.uleb128 0x25
.uleb128 0xe
.uleb128 0x13
.uleb128 0xb
.uleb128 0x3
.uleb128 0xe
.uleb128 0x1b
.uleb128 0xe
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x10
.uleb128 0x17
.byte 0
.byte 0
.uleb128 0x2
.uleb128 0x2e
.byte 0x1
.uleb128 0x3f
.uleb128 0x19
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x27
.uleb128 0x19
.uleb128 0x49
.uleb128 0x13
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0x18
.uleb128 0x2117
.uleb128 0x19
.uleb128 0x1
.uleb128 0x13
.byte 0
.byte 0
.uleb128 0x3
.uleb128 0x5
.byte 0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0x18
.byte 0
.byte 0
.uleb128 0x4
.uleb128 0x24
.byte 0
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.uleb128 0x3
.uleb128 0x8
.byte 0
.byte 0
.uleb128 0x5
.uleb128 0x2e
.byte 0x1
.uleb128 0x3f
.uleb128 0x19
.uleb128 0x3
.uleb128 0xe
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x27
.uleb128 0x19
.uleb128 0x49
.uleb128 0x13
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0x18
.uleb128 0x2116
.uleb128 0x19
.byte 0
.byte 0
.uleb128 0x6
.uleb128 0x34
.byte 0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0x18
.byte 0
.byte 0
.byte 0
.section .debug_aranges,"",@progbits
.long 0x2c
.value 0x2
.long .Ldebug_info0
.byte 0x8
.byte 0
.value 0
.value 0
.quad .Ltext0
.quad .Letext0-.Ltext0
.quad 0
.quad 0
.section .debug_line,"",@progbits
.Ldebug_line0:
.section .debug_str,"MS",@progbits,1
.LASF0:
.string "GNU C 4.7.2 20121109 (Red Hat 4.7.2-8) -mtune=generic -march=x86-64 -g -O0"
.LASF1:
.string "./py-linetable.c"
.LASF3:
.string "main"
.LASF2:
.string "gdb/testsuite/gdb.python"
.ident "GCC: (GNU) 4.7.2 20121109 (Red Hat 4.7.2-8)"
.section .note.GNU-stack,"",@progbits

View File

@ -0,0 +1,46 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2013 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
foo (int a, int b)
{
if (a == b)
return 1;
return 0;
}
bar (int a, int b)
{
if (a + b == a)
return 1;
return 0;
}
int
main (void)
{
int i;
if (foo (5,5) && bar (5,0))
return 0;
for (i = 0;
i<500;
i++);
return 0;
}

View File

@ -0,0 +1,76 @@
# Copyright 2013 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/>.
load_lib gdb-python.exp
set opts {}
standard_testfile .S
if [info exists COMPILE] {
# make check RUNTESTFLAGS="gdb.python/py-linetable.exp COMPILE=1"
standard_testfile
lappend opts debug optimize=-O2
} elseif { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
verbose "Skipping ${testfile}."
return
}
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} $opts] } {
return -1
}
if ![runto_main] {
return -1
}
# Skip all tests if Python scripting is not enabled.
if { [skip_python_tests] } { continue }
gdb_py_test_silent_cmd "python lt = gdb.selected_frame().find_sal().symtab.linetable()" \
"get instruction" 0
gdb_py_test_multiple "input simple command" \
"python" "" \
"def list_lines():" "" \
" for l in lt:" "" \
" print 'L' +str(l.line)+' A '+hex(l.pc)" "" \
"end" ""
gdb_test "python list_lines()" \
"L20 A $hex.*L21 A $hex.*L22 A $hex.*L24 A $hex.*L25 A $hex.*L40 A $hex.*L42 A $hex.*L44 A $hex.*L42 A $hex.*L46 A $hex.*" \
"test linetable iterator addr"
gdb_test "python print len(lt.line(42))" "2" \
"Test length of a multiple pc line"
gdb_test "python print len(lt.line(20))" "1" \
"Test length of a single pc line"
gdb_test "python print lt.line(1)" "None" \
"Test None returned for line with no pc"
# Test gdb.Linetable.sourcelines ()
gdb_py_test_silent_cmd "python fset = lt.source_lines()" \
"Get all source lines into a frozen set" 0
gdb_test "python print sorted(fset)" \
"\[20L, 21L, 22L, 24L, 25L, 28L, 29L, 30L, 32L, 33L, 37L, 39L, 40L, 42L, 44L, 45L, 46L\].*" \
"Test frozen set contains line numbers"
# Test gdb.Linetable.has_line ()
gdb_test "python print lt.has_line(20)" \
"True.*" \
"Test has_pcs at line 20"
gdb_test "python print lt.has_line(44)" \
"True.*" \
"Test has_pcs at line 40"
gdb_test "python print lt.has_line(10)" \
"False.*" \
"Test has_pcs at line 10"