+2011-03-17 Phil Muldoon <pmuldoon@redhat.com>
+
+ * python/py-symtab.c: Populate symtab_object_methods,
+ sal_object_methods.
+ (stpy_is_valid): New function.
+ (salpy_is_valid): Ditto.
+ * python/py-symbol.c: Declare symbol_object_methods. Populate.
+ (sympy_is_valid): New function.
+ * python/py-objfile.c: Declare objfile_object_methods. Populate.
+ (objfpy_is_valid): New function.
+ * python/py-inferior.c: Populate inferior_object_methods.
+ (infpy_is_valid): New function.
+ * python/py-infthread.c: Populate thread_object_methods.
+ (thpy_is_valid): New function.
+ * python/py-block.c: Declare block_object_methods. Populate. Declare
+ block_iterator_object_methods. Populate.
+ (blpy_is_valid): New function.
+ (blpy_iter_is_valid): Ditto.
+
2011-03-16 Keith Seitz <keiths@redhat.com>
* linespec.c (find_methods): Canonicalize NAME before looking
This improves how Parameter set/show documentation is processed
and allows for more dynamic content.
+ ** Symbols, Symbol Table, Symbol Table and Line, Object Files,
+ Inferior, Inferior Thread, Blocks, and Block Iterator APIs now
+ have an is_valid method.
+
** Breakpoints can now be sub-classed in Python, and in particular
you may implement a 'stop' function that is executed each time
the inferior reaches that breakpoint.
+2011-03-17 Phil Muldoon <pmuldoon@redhat.com>
+
+ * gdb.texinfo (Blocks In Python): Add is_valid method description.
+ (Inferiors In Python): Likewise.
+ (Threads In Python): Likewise.
+ (Symbols In Python): Likewise.
+ (Objfiles In Python): Likewise.
+ (Symbol Tables In Python): Likewise.
+
2011-03-15 Pedro Alves <pedro@codesourcery.com>
* gdb.texinfo (Auto Display) <undisplay, enable display, disable
* gdb.texinfo (Breakpoints In Python): Add description and example
of Python stop function operation.
-
2011-03-10 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Parameters In Python): Document get_set_string and
A @code{gdb.Inferior} object has the following methods:
@table @code
+@defmethod Inferior is_valid
+Returns @code{True} if the @code{gdb.Inferior} object is valid,
+@code{False} if not. A @code{gdb.Inferior} object will become invalid
+if the inferior no longer exists within @value{GDBN}. All other
+@code{gdb.Inferior} methods will throw an exception if it is invalid
+at the time the method is called.
+@end defmethod
+
@defmethod Inferior threads
This method returns a tuple holding all the threads which are valid
when it is called. If there are no valid threads, the method will
A @code{gdb.InferiorThread} object has the following methods:
@table @code
+@defmethod InferiorThread is_valid
+Returns @code{True} if the @code{gdb.InferiorThread} object is valid,
+@code{False} if not. A @code{gdb.InferiorThread} object will become
+invalid if the thread exits, or the inferior that the thread belongs
+is deleted. All other @code{gdb.InferiorThread} methods will throw an
+exception if it is invalid at the time the method is called.
+@end defmethod
+
@defmethod InferiorThread switch
This changes @value{GDBN}'s currently selected thread to the one represented
by this object.
information.
@end defivar
+A @code{gdb.Objfile} object has the following methods:
+
+@defmethod Objfile is_valid
+Returns @code{True} if the @code{gdb.Objfile} object is valid,
+@code{False} if not. A @code{gdb.Objfile} object can become invalid
+if the object file it refers to is not loaded in @value{GDBN} any
+longer. All other @code{gdb.Objfile} methods will throw an exception
+if it is invalid at the time the method is called.
+@end defmethod
+
@node Frames In Python
@subsubsection Accessing inferior stack frames from Python.
will return @code{None}.
@end defun
+A @code{gdb.Block} object has the following methods:
+
+@table @code
+@defmethod Block is_valid
+Returns @code{True} if the @code{gdb.Block} object is valid,
+@code{False} if not. A block object can become invalid if the block it
+refers to doesn't exist anymore in the inferior. All other
+@code{gdb.Block} methods will throw an exception if it is invalid at
+the time the method is called. This method is also made available to
+the Python iterator object that @code{gdb.Block} provides in an iteration
+context and via the Python @code{iter} built-in function.
+@end defmethod
+@end table
+
A @code{gdb.Block} object has the following attributes:
@table @code
@end defivar
@end table
+A @code{gdb.Symbol} object has the following methods:
+
+@table @code
+@defmethod Symbol is_valid
+Returns @code{True} if the @code{gdb.Symbol} object is valid,
+@code{False} if not. A @code{gdb.Symbol} object can become invalid if
+the symbol it refers to does not exist in @value{GDBN} any longer.
+All other @code{gdb.Symbol} methods will throw an exception if it is
+invalid at the time the method is called.
+@end defmethod
+@end table
+
The available domain categories in @code{gdb.Symbol} are represented
as constants in the @code{gdb} module:
@end defivar
@end table
+A @code{gdb.Symtab_and_line} object has the following methods:
+
+@table @code
+@defmethod Symtab_and_line is_valid
+Returns @code{True} if the @code{gdb.Symtab_and_line} object is valid,
+@code{False} if not. A @code{gdb.Symtab_and_line} object can become
+invalid if the Symbol table and line object it refers to does not
+exist in @value{GDBN} any longer. All other
+@code{gdb.Symtab_and_line} methods will throw an exception if it is
+invalid at the time the method is called.
+@end defmethod
+@end table
+
A @code{gdb.Symtab} object has the following attributes:
@table @code
@end defivar
@end table
-The following methods are provided:
+A @code{gdb.Symtab} object has the following methods:
@table @code
+@defmethod Symtab is_valid
+Returns @code{True} if the @code{gdb.Symtab} object is valid,
+@code{False} if not. A @code{gdb.Symtab} object can become invalid if
+the symbol table it refers to does not exist in @value{GDBN} any
+longer. All other @code{gdb.Symtab} methods will throw an exception
+if it is invalid at the time the method is called.
+@end defmethod
+
@defmethod Symtab fullname
Return the symbol table's source absolute file name.
@end defmethod
Py_XDECREF (iter_obj->source);
}
+/* Implementation of gdb.Block.is_valid (self) -> Boolean.
+ Returns True if this block object still exists in GDB. */
+
+static PyObject *
+blpy_is_valid (PyObject *self, PyObject *args)
+{
+ struct block *block;
+
+ block = block_object_to_block (self);
+ if (block == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
+/* Implementation of gdb.BlockIterator.is_valid (self) -> Boolean.
+ Returns True if this block iterator object still exists in GDB */
+
+static PyObject *
+blpy_iter_is_valid (PyObject *self, PyObject *args)
+{
+ block_syms_iterator_object *iter_obj =
+ (block_syms_iterator_object *) self;
+
+ if (iter_obj->source->block == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
/* Return the innermost lexical block containing the specified pc value,
or 0 if there is none. */
PyObject *
\f
+static PyMethodDef block_object_methods[] = {
+ { "is_valid", blpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this block is valid, false if not." },
+ {NULL} /* Sentinel */
+};
+
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 },
0, /* tp_weaklistoffset */
blpy_iter, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ block_object_methods, /* tp_methods */
0, /* tp_members */
block_object_getset /* tp_getset */
};
+static PyMethodDef block_iterator_object_methods[] = {
+ { "is_valid", blpy_iter_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this block iterator is valid, false if not." },
+ {NULL} /* Sentinel */
+};
+
static PyTypeObject block_syms_iterator_object_type = {
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
0, /*tp_weaklistoffset */
blpy_block_syms_iter, /*tp_iter */
blpy_block_syms_iternext, /*tp_iternext */
- 0 /*tp_methods */
+ block_iterator_object_methods /*tp_methods */
};
Py_RETURN_NONE;
}
+/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
+ Returns True if this inferior object still exists in GDB. */
+
+static PyObject *
+infpy_is_valid (PyObject *self, PyObject *args)
+{
+ inferior_object *inf = (inferior_object *) self;
+
+ if (! inf->inferior)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
/* Clear the INFERIOR pointer in an Inferior object and clear the
thread list. */
static PyMethodDef inferior_object_methods[] =
{
+ { "is_valid", infpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this inferior is valid, false if not." },
{ "threads", infpy_threads, METH_NOARGS,
"Return all the threads of this inferior." },
{ "read_memory", (PyCFunction) infpy_read_memory,
Py_RETURN_FALSE;
}
+/* Implementation of gdb.InfThread.is_valid (self) -> Boolean.
+ Returns True if this inferior Thread object still exists
+ in GDB. */
+static PyObject *
+thpy_is_valid (PyObject *self, PyObject *args)
+{
+ thread_object *thread_obj = (thread_object *) self;
+
+ if (! thread_obj->thread)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
/* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
Returns the selected thread object. */
static PyMethodDef thread_object_methods[] =
{
+ { "is_valid", thpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this inferior thread is valid, false if not." },
{ "switch", thpy_switch, METH_NOARGS,
"switch ()\n\
Makes this the GDB selected thread." },
return 0;
}
+/* Implementation of gdb.Objfile.is_valid (self) -> Boolean.
+ Returns True if this object file still exists in GDB. */
+
+static PyObject *
+objfpy_is_valid (PyObject *self, PyObject *args)
+{
+ objfile_object *obj = (objfile_object *) self;
+
+ if (! obj->objfile)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
\f
/* Clear the OBJFILE pointer in an Objfile object and remove the
\f
+static PyMethodDef objfile_object_methods[] =
+{
+ { "is_valid", objfpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this object file is valid, false if not." },
+
+ { NULL }
+};
+
static PyGetSetDef objfile_getset[] =
{
{ "filename", objfpy_get_filename, NULL,
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ objfile_object_methods, /* tp_methods */
0, /* tp_members */
objfile_getset, /* tp_getset */
0, /* tp_base */
|| class == LOC_OPTIMIZED_OUT));
}
+/* Implementation of gdb.Symbol.is_valid (self) -> Boolean.
+ Returns True if this Symbol still exists in GDB. */
+
+static PyObject *
+sympy_is_valid (PyObject *self, PyObject *args)
+{
+ struct symbol *symbol = NULL;
+
+ symbol = symbol_object_to_symbol (self);
+ if (symbol == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
/* 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
{ NULL } /* Sentinel */
};
+static PyMethodDef symbol_object_methods[] = {
+ { "is_valid", sympy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this symbol is valid, false if not." },
+ {NULL} /* Sentinel */
+};
+
PyTypeObject symbol_object_type = {
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
- 0, /*tp_methods */
+ symbol_object_methods, /*tp_methods */
0, /*tp_members */
symbol_object_getset /*tp_getset */
};
Py_RETURN_NONE;
}
+/* Implementation of gdb.Symtab.is_valid (self) -> Boolean.
+ Returns True if this Symbol table still exists in GDB. */
+
+static PyObject *
+stpy_is_valid (PyObject *self, PyObject *args)
+{
+ struct symtab *symtab = NULL;
+
+ symtab = symtab_object_to_symtab (self);
+ if (symtab == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
static PyObject *
salpy_str (PyObject *self)
{
return (PyObject *) self_sal->symtab;
}
+/* Implementation of gdb.Symtab_and_line.is_valid (self) -> Boolean.
+ Returns True if this Symbol table and line object still exists GDB. */
+
+static PyObject *
+salpy_is_valid (PyObject *self, PyObject *args)
+{
+ struct symtab_and_line *sal;
+
+ sal = sal_object_to_symtab_and_line (self);
+ if (sal == NULL)
+ Py_RETURN_FALSE;
+
+ Py_RETURN_TRUE;
+}
+
static void
salpy_dealloc (PyObject *self)
{
};
static PyMethodDef symtab_object_methods[] = {
+ { "is_valid", stpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this symbol table is valid, false if not." },
{ "fullname", stpy_fullname, METH_NOARGS,
"fullname () -> String.\n\
Return the symtab's full source filename." },
{NULL} /* Sentinel */
};
+static PyMethodDef sal_object_methods[] = {
+ { "is_valid", salpy_is_valid, METH_NOARGS,
+ "is_valid () -> Boolean.\n\
+Return true if this symbol table and line is valid, false if not." },
+ {NULL} /* Sentinel */
+};
+
static PyTypeObject sal_object_type = {
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
- 0, /*tp_methods */
+ sal_object_methods, /*tp_methods */
0, /*tp_members */
sal_object_getset /*tp_getset */
};
+2010-03-17 Phil Muldoon <pmuldoon@redhat.com>
+
+ * gdb.python/Makefile.in: Add py-objfile.
+ * gdb.python/py-objfile.exp: New file.
+ * gdb.python/py-objfile.c: New file.
+ * gdb.python/py-block.exp: Add is_valid tests.
+ * gdb.python/py-inferior.exp: Ditto.
+ * gdb.python/py-infthread.exp: Ditto.
+ * gdb.python/py-symbol.exp: Ditto.
+ * gdb.python/py-symtab.exp: Ditto.
+
2011-03-16 Keith Seitz <keiths@redhat.com>
PR c++/12273
EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
py-symbol py-mi py-breakpoint py-inferior py-infthread \
py-shared python lib-types py-events py-evthreads py-frame \
- py-pp-maint py-progspace py-section-script
+ py-pp-maint py-progspace py-section-script py-objfile
MISCELLANEOUS = py-shared-sl.sl
gdb_test "python print block" "<gdb.Block object at $hex>" \
"Check Frame 2's block not None"
gdb_test "python print block.function" "main" "main block"
+
+
+# Test Block is_valid. This must always be the last test in this
+# testcase as it unloads the object file.
+delete_breakpoints
+gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0
+gdb_py_test_silent_cmd "python block = frame.block()" "Get Frame block" 0
+gdb_py_test_silent_cmd "python block_iter = iter (block)" "Get Frame block" 0
+gdb_test "python print block.is_valid()" "True" \
+ "Check block validity"
+gdb_test "python print block_iter.is_valid()" "True" \
+ "Check block validity"
+gdb_unload
+gdb_test "python print block.is_valid()" "False" \
+ "Check block validity"
+gdb_test "python print block_iter.is_valid()" "False" \
+ "Check block validity"
gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, end_addr - start_addr, pattern)" \
"${one_pattern_found}" "find pattern straddling chunk boundary"
}
+
+# Test Inferior is_valid. This must always be the last test in
+# this testcase as it kills the inferior.
+
+gdb_py_test_silent_cmd "python inf_list = gdb.inferiors()" "get initial list" 1
+gdb_test "python print len(inf_list)" "1" "Get inferior list length"
+gdb_test "python print inf_list\[0\].is_valid()" "True" \
+ "Check inferior validity"
+gdb_test "add-inferior" "Added inferior 2.*" "add empty inferior 2"
+gdb_py_test_silent_cmd "python inf_list = gdb.inferiors()" "get new list" 1
+gdb_test "python print len(inf_list)" "2" "Get inferior list length"
+gdb_test "python print inf_list\[0\].is_valid()" "True" \
+ "Check inferior validity"
+gdb_test "python print inf_list\[1\].is_valid()" "True" \
+ "Check inferior validity"
+gdb_test_no_output "remove-inferiors 2" "remove-inferiors 2"
+gdb_test "python print inf_list\[0\].is_valid()" "False" \
+ "Check inferior validity"
+gdb_test "python print inf_list\[1\].is_valid()" "True" \
+ "Check inferior validity"
gdb_test "python print 'result =', t0.is_stopped ()" " = True" "test InferiorThread.is_stopped"
gdb_test "python print 'result =', t0.is_running ()" " = False" "test InferiorThread.is_running"
gdb_test "python print 'result =', t0.is_exited ()" " = False" "test InferiorThread.is_exited"
+
+# Test InferiorThread is_valid. This must always be the last test in
+# this testcase as it kills the inferior.
+
+gdb_test "python print 'result =', t0.is_valid ()" " = True" "test InferiorThread.is_valid"
+gdb_test_no_output "kill inferior 1" "kill inferior 1"
+gdb_test "python print 'result =', t0.is_valid ()" " = False" "test InferiorThread.is_valid"
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2011 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
+main ()
+{
+ int some_var = 0;
+ return 0;
+}
--- /dev/null
+# Copyright (C) 2011 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 program space
+# support in Python.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+load_lib gdb-python.exp
+
+set testfile "py-objfile"
+set srcfile ${testfile}.c
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+ return -1
+}
+
+# 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
+}
+
+gdb_py_test_silent_cmd "python sym = gdb.lookup_symbol(\"some_var\")" \
+ "Find a symbol in objfile" 1
+gdb_py_test_silent_cmd "python objfile = sym\[0\].symtab.objfile" \
+ "Get backing object file" 1
+
+gdb_test "python print objfile.filename" ".*py-objfile.*" \
+ "Get objfile validity"
+gdb_test "python print objfile.is_valid()" "True" \
+ "Get objfile validity"
+gdb_unload
+gdb_test "python print objfile.is_valid()" "False" \
+ "Get objfile validity after unload"
gdb_test "python print cplusfunc.print_name" "SimpleClass::valueofi().*" "Test func.print_name"
gdb_test "python print cplusfunc.linkage_name" "SimpleClass::valueofi().*" "Test func.linkage_name"
gdb_test "python print cplusfunc.addr_class == gdb.SYMBOL_LOC_BLOCK" "True" "Test func.addr_class"
+
+# Test is_valid when the objfile is unloaded. This must be the last
+# test as it unloads the object file in GDB.
+# Start with a fresh gdb.
+clean_restart ${testfile}
+if ![runto_main] then {
+ fail "Cannot run to main."
+ return 0
+}
+gdb_breakpoint [gdb_get_line_number "Break at end."]
+gdb_continue_to_breakpoint "Break at end."
+gdb_py_test_silent_cmd "python a = gdb.lookup_symbol(\'a\')" "Get variable a" 0
+gdb_test "python print a\[0\].is_valid()" "True" "Test symbol validity"
+delete_breakpoints
+gdb_unload
+gdb_test "python print a\[0\].is_valid()" "False" "Test symbol validity"
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"
+gdb_test "python print sal.is_valid()" "True" "Test sal.is_valid"
# 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"
+gdb_test "python print symtab.is_valid()" "True" "Test symtab.is_valid()"
+
+# Test is_valid when the objfile is unloaded. This must be the last
+# test as it unloads the object file in GDB.
+gdb_unload
+gdb_test "python print sal.is_valid()" "False" "Test sal.is_valid"
+gdb_test "python print symtab.is_valid()" "False" "Test symtab.is_valid()"