2009-04-01  Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Phil Muldoon  <pmuldoon@redhat.com>

	* python/python.c: Include objfiles.h, observer.h.
	(gdbpy_auto_load): New global.
	(gdbpy_current_objfile): Likewise.
	(GDBPY_AUTO_FILENAME): New define.
	(gdbpy_new_objfile): New function.
	(gdbpy_get_current_objfile): Likewise.
	(gdbpy_objfiles): Likewise.
	(_initialize_python): Add "maint set auto-load".  Call
	gdbpy_initialize_objfile.  Attach objfile observer.
	(GdbMethods): New methods current_objfile, objfiles.
	* python/python-objfile.c: New file.
	* python/python-internal.h (objfile_to_objfile_object): Declare.
	(objfpy_get_printers): Likewise.
	(gdbpy_initialize_objfile): Likewise.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-objfile.o.
	(SUBDIR_PYTHON_SRCS): Add python-objfile.c.
	(python-objfile.o): New target.

gdb/doc

2009-04-01  Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* gdb.texinfo (Python API): Update.
	(Auto-loading): New node.
	(Objfiles In Python): New node.

gdb/testsuite

2009-04-06  Tom Tromey  <tromey@redhat.com>

	* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
	tests.
	* gdb.python/python-value.exp (py_objfile_tests): New proc.
	Call it.
This commit is contained in:
Tom Tromey 2009-05-28 00:40:24 +00:00
parent 58683880f5
commit 89c73adef9
10 changed files with 530 additions and 0 deletions

View File

@ -1,3 +1,25 @@
2009-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
* python/python.c: Include objfiles.h, observer.h.
(gdbpy_auto_load): New global.
(gdbpy_current_objfile): Likewise.
(GDBPY_AUTO_FILENAME): New define.
(gdbpy_new_objfile): New function.
(gdbpy_get_current_objfile): Likewise.
(gdbpy_objfiles): Likewise.
(_initialize_python): Add "maint set auto-load". Call
gdbpy_initialize_objfile. Attach objfile observer.
(GdbMethods): New methods current_objfile, objfiles.
* python/python-objfile.c: New file.
* python/python-internal.h (objfile_to_objfile_object): Declare.
(objfpy_get_printers): Likewise.
(gdbpy_initialize_objfile): Likewise.
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-objfile.o.
(SUBDIR_PYTHON_SRCS): Add python-objfile.c.
(python-objfile.o): New target.
2009-05-27 Pedro Alves <pedro@codesourcery.com>
* infrun.c (follow_exec): Clear the stop_requested flag.

View File

@ -267,6 +267,7 @@ SUBDIR_PYTHON_OBS = \
python-cmd.o \
python-frame.o \
python-function.o \
python-objfile.o \
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
@ -274,6 +275,7 @@ SUBDIR_PYTHON_SRCS = \
python/python-cmd.c \
python/python-frame.c \
python/python-function.c \
python/python-objfile.c \
python/python-utils.c \
python/python-value.c
SUBDIR_PYTHON_DEPS =
@ -1864,6 +1866,10 @@ python-function.o: $(srcdir)/python/python-function.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-function.c
$(POSTCOMPILE)
python-objfile.o: $(srcdir)/python/python-objfile.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c
$(POSTCOMPILE)
python-utils.o: $(srcdir)/python/python-utils.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
$(POSTCOMPILE)

View File

@ -1,3 +1,12 @@
2009-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo: Add @syncodeindex for `tp'.
(Python API): Update.
(Auto-loading): New node.
(Objfiles In Python): New node.
2009-05-15 Paul Pluzhnikov <ppluzhnikov@google.com>
* gdb.texinfo (Threads): Document libthread-db-search-path.

View File

@ -21,6 +21,7 @@
@finalout
@syncodeindex ky cp
@syncodeindex tp cp
@c readline appendices use @vindex, @findex and @ftable,
@c annotate.texi and gdbmi use @findex.
@ -18513,9 +18514,11 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
@menu
* Basic Python:: Basic Python Functions.
* Exception Handling::
* Auto-loading:: Automatically loading Python code.
* Values From Inferior::
* Commands In Python:: Implementing new commands in Python.
* Functions In Python:: Writing new convenience functions.
* Objfiles In Python:: Object files.
* Frames In Python:: Acessing inferior stack frames from Python.
@end menu
@ -18614,6 +18617,53 @@ message as its value, and the Python call stack backtrace at the
Python statement closest to where the @value{GDBN} error occured as the
traceback.
@node Auto-loading
@subsubsection Auto-loading
@cindex auto-loading, Python
When a new object file is read (for example, due to the @code{file}
command, or because the inferior has loaded a shared library),
@value{GDBN} will look for a file named @file{@var{objfile}-gdb.py},
where @var{objfile} is the object file's real name, formed by ensuring
that the file name is absolute, following all symlinks, and resolving
@code{.} and @code{..} components. If this file exists and is
readable, @value{GDBN} will evaluate it as a Python script.
If this file does not exist, and if the parameter
@code{debug-file-directory} is set (@pxref{Separate Debug Files}),
then @value{GDBN} will use the file named
@file{@var{debug-file-directory}/@var{real-name}}, where
@var{real-name} is the object file's real name, as described above.
Finally, if this file does not exist, then @value{GDBN} will look for
a file named @file{@var{data-directory}/python/auto-load/@var{real-name}}, where
@var{data-directory} is @value{GDBN}'s data directory (available via
@code{show data-directory}, @pxref{Data Files}), and @var{real-name}
is the object file's real name, as described above.
When reading an auto-loaded file, @value{GDBN} sets the ``current
objfile''. This is available via the @code{gdb.current_objfile}
function (@pxref{Objfiles In Python}). This can be useful for
registering objfile-specific pretty-printers.
The auto-loading feature is useful for supplying application-specific
debugging commands and scripts. You can enable or disable this
feature, and view its current state.
@table @code
@kindex maint set python auto-load
@item maint set python auto-load [yes|no]
Enable or disable the Python auto-loading feature.
@kindex show python auto-load
@item show python auto-load
Show whether Python auto-loading is enabled or disabled.
@end table
@value{GDBN} does not track which files it has already auto-loaded.
So, your @samp{-gdb.py} file should take care to ensure that it may be
evaluated multiple times without error.
@node Values From Inferior
@subsubsection Values From Inferior
@cindex values from inferior, with Python
@ -19027,6 +19077,50 @@ registration of the function with @value{GDBN}. Depending on how the
Python code is read into @value{GDBN}, you may need to import the
@code{gdb} module explicitly.
@node Objfiles In Python
@subsubsection Objfiles In Python
@cindex objfiles in python
@tindex gdb.Objfile
@tindex Objfile
@value{GDBN} loads symbols for an inferior from various
symbol-containing files (@pxref{Files}). These include the primary
executable file, any shared libraries used by the inferior, and any
separate debug info files (@pxref{Separate Debug Files}).
@value{GDBN} calls these symbol-containing files @dfn{objfiles}.
The following objfile-related functions are available in the
@code{gdb} module:
@findex gdb.current_objfile
@defun current_objfile
When auto-loading a Python script (@pxref{Auto-loading}), @value{GDBN}
sets the ``current objfile'' to the corresponding objfile. This
function returns the current objfile. If there is no current objfile,
this function returns @code{None}.
@end defun
@findex gdb.objfiles
@defun objfiles
Return a sequence of all the objfiles current known to @value{GDBN}.
@xref{Objfiles In Python}.
@end defun
Each objfile is represented by an instance of the @code{gdb.Objfile}
class.
@defivar Objfile filename
The file name of the objfile as a string.
@end defivar
@defivar Objfile pretty_printers
The @code{pretty_printers} attribute is a list of functions. It is
used to look up pretty-printers. A @code{Value} is passed to each
function in order; if the function returns @code{None}, then the
search continues. Otherwise, the return value should be an object
which is used to format the value.
@end defivar
@node Frames In Python
@subsubsection Acessing inferior stack frames from Python.

View File

@ -68,6 +68,9 @@ PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
PyObject *value_to_value_object (struct value *v);
PyObject *objfile_to_objfile_object (struct objfile *);
PyObject *objfpy_get_printers (PyObject *, void *);
struct value *convert_value_from_python (PyObject *obj);
@ -75,6 +78,7 @@ void gdbpy_initialize_values (void);
void gdbpy_initialize_frames (void);
void gdbpy_initialize_commands (void);
void gdbpy_initialize_functions (void);
void gdbpy_initialize_objfile (void);
struct cleanup *make_cleanup_py_decref (PyObject *py);
struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);

229
gdb/python/python-objfile.c Normal file
View File

@ -0,0 +1,229 @@
/* Python interface to objfiles.
Copyright (C) 2008, 2009 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 "charset.h"
#include "objfiles.h"
typedef struct
{
PyObject_HEAD
/* The corresponding objfile. */
struct objfile *objfile;
/* The pretty-printer list of functions. */
PyObject *printers;
} objfile_object;
static PyTypeObject objfile_object_type;
static const struct objfile_data *objfpy_objfile_data_key;
/* An Objfile method which returns the objfile's file name, or None. */
static PyObject *
objfpy_get_filename (PyObject *self, void *closure)
{
objfile_object *obj = (objfile_object *) self;
if (obj->objfile && obj->objfile->name)
return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name),
host_charset (), NULL);
Py_RETURN_NONE;
}
static void
objfpy_dealloc (PyObject *o)
{
objfile_object *self = (objfile_object *) o;
Py_XDECREF (self->printers);
self->ob_type->tp_free ((PyObject *) self);
}
static PyObject *
objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
{
objfile_object *self = (objfile_object *) type->tp_alloc (type, 0);
if (self)
{
self->objfile = NULL;
self->printers = PyList_New (0);
if (!self->printers)
{
Py_DECREF (self);
return NULL;
}
}
return (PyObject *) self;
}
PyObject *
objfpy_get_printers (PyObject *o, void *ignore)
{
objfile_object *self = (objfile_object *) o;
Py_INCREF (self->printers);
return self->printers;
}
static int
objfpy_set_printers (PyObject *o, PyObject *value, void *ignore)
{
PyObject *tmp;
objfile_object *self = (objfile_object *) o;
if (! value)
{
PyErr_SetString (PyExc_TypeError,
"cannot delete the pretty_printers attribute");
return -1;
}
if (! PyList_Check (value))
{
PyErr_SetString (PyExc_TypeError,
"the pretty_printers attribute must be a list");
return -1;
}
/* Take care in case the LHS and RHS are related somehow. */
tmp = self->printers;
Py_INCREF (value);
self->printers = value;
Py_XDECREF (tmp);
return 0;
}
/* Clear the OBJFILE pointer in an Objfile object and remove the
reference. */
static void
clean_up_objfile (struct objfile *objfile, void *datum)
{
PyGILState_STATE state;
objfile_object *object = datum;
state = PyGILState_Ensure ();
object->objfile = NULL;
Py_DECREF ((PyObject *) object);
PyGILState_Release (state);
}
/* Return a borrowed reference to the Python object of type Objfile
representing OBJFILE. If the object has already been created,
return it. Otherwise, create it. Return NULL and set the Python
error on failure. */
PyObject *
objfile_to_objfile_object (struct objfile *objfile)
{
objfile_object *object;
object = objfile_data (objfile, objfpy_objfile_data_key);
if (!object)
{
object = PyObject_New (objfile_object, &objfile_object_type);
if (object)
{
PyObject *dict;
object->objfile = objfile;
object->printers = PyList_New (0);
if (!object->printers)
{
Py_DECREF (object);
return NULL;
}
set_objfile_data (objfile, objfpy_objfile_data_key, object);
}
}
return (PyObject *) object;
}
void
gdbpy_initialize_objfile (void)
{
objfpy_objfile_data_key
= register_objfile_data_with_cleanup (clean_up_objfile);
if (PyType_Ready (&objfile_object_type) < 0)
return;
Py_INCREF (&objfile_object_type);
PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type);
}
static PyGetSetDef objfile_getset[] =
{
{ "filename", objfpy_get_filename, NULL,
"The objfile's filename, or None.", NULL },
{ "pretty_printers", objfpy_get_printers, objfpy_set_printers,
"Pretty printers.", NULL },
{ NULL }
};
static PyTypeObject objfile_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"gdb.Objfile", /*tp_name*/
sizeof (objfile_object), /*tp_basicsize*/
0, /*tp_itemsize*/
objfpy_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 objfile 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 */
objfile_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 */
objfpy_new, /* tp_new */
};

View File

@ -22,6 +22,8 @@
#include "ui-out.h"
#include "cli/cli-script.h"
#include "gdbcmd.h"
#include "objfiles.h"
#include "observer.h"
#include <ctype.h>
@ -29,6 +31,10 @@
false otherwise. */
static int gdbpy_should_print_stack = 1;
/* This is true if we should auto-load python code when an objfile is
opened, false otherwise. */
static int gdbpy_auto_load = 1;
#ifdef HAVE_PYTHON
#include "python.h"
@ -301,6 +307,129 @@ gdbpy_print_stack (void)
PyErr_Clear ();
}
/* The "current" objfile. This is set when gdb detects that a new
objfile has been loaded. It is only set for the duration of a call
to gdbpy_new_objfile; it is NULL at other times. */
static struct objfile *gdbpy_current_objfile;
/* The file name we attempt to read. */
#define GDBPY_AUTO_FILENAME "-gdb.py"
/* This is a new_objfile observer callback which loads python code
based on the path to the objfile. */
static void
gdbpy_new_objfile (struct objfile *objfile)
{
char *realname;
char *filename, *debugfile;
int len;
FILE *input;
PyGILState_STATE state;
struct cleanup *cleanups;
if (!gdbpy_auto_load || !objfile || !objfile->name)
return;
state = PyGILState_Ensure ();
gdbpy_current_objfile = objfile;
realname = gdb_realpath (objfile->name);
len = strlen (realname);
filename = xmalloc (len + sizeof (GDBPY_AUTO_FILENAME));
memcpy (filename, realname, len);
strcpy (filename + len, GDBPY_AUTO_FILENAME);
input = fopen (filename, "r");
debugfile = filename;
cleanups = make_cleanup (xfree, filename);
make_cleanup (xfree, realname);
if (!input && debug_file_directory)
{
/* Also try the same file in the separate debug info directory. */
debugfile = xmalloc (strlen (filename)
+ strlen (debug_file_directory) + 1);
strcpy (debugfile, debug_file_directory);
/* FILENAME is absolute, so we don't need a "/" here. */
strcat (debugfile, filename);
make_cleanup (xfree, debugfile);
input = fopen (debugfile, "r");
}
if (!input && gdb_datadir)
{
/* Also try the same file in a subdirectory of gdb's data
directory. */
debugfile = xmalloc (strlen (gdb_datadir) + strlen (filename)
+ strlen ("/auto-load") + 1);
strcpy (debugfile, gdb_datadir);
strcat (debugfile, "/auto-load");
/* FILENAME is absolute, so we don't need a "/" here. */
strcat (debugfile, filename);
make_cleanup (xfree, debugfile);
input = fopen (debugfile, "r");
}
if (input)
{
/* We don't want to throw an exception here -- but the user
would like to know that something went wrong. */
if (PyRun_SimpleFile (input, debugfile))
gdbpy_print_stack ();
fclose (input);
}
do_cleanups (cleanups);
gdbpy_current_objfile = NULL;
PyGILState_Release (state);
}
/* Return the current Objfile, or None if there isn't one. */
static PyObject *
gdbpy_get_current_objfile (PyObject *unused1, PyObject *unused2)
{
PyObject *result;
if (! gdbpy_current_objfile)
Py_RETURN_NONE;
result = objfile_to_objfile_object (gdbpy_current_objfile);
if (result)
Py_INCREF (result);
return result;
}
/* Return a sequence holding all the Objfiles. */
static PyObject *
gdbpy_objfiles (PyObject *unused1, PyObject *unused2)
{
struct objfile *objf;
PyObject *list;
list = PyList_New (0);
if (!list)
return NULL;
ALL_OBJFILES (objf)
{
PyObject *item = objfile_to_objfile_object (objf);
if (!item || PyList_Append (list, item) == -1)
{
Py_DECREF (list);
return NULL;
}
}
return list;
}
#else /* HAVE_PYTHON */
/* Dummy implementation of the gdb "python" command. */
@ -399,6 +528,15 @@ Enables or disables printing of Python stack traces."),
&set_python_list,
&show_python_list);
add_setshow_boolean_cmd ("auto-load", class_maintenance,
&gdbpy_auto_load, _("\
Enable or disable auto-loading of Python code when an object is opened."), _("\
Show whether Python code will be auto-loaded when an object is opened."), _("\
Enables or disables auto-loading of Python code when an object is opened."),
NULL, NULL,
&set_python_list,
&show_python_list);
#ifdef HAVE_PYTHON
Py_Initialize ();
PyEval_InitThreads ();
@ -414,9 +552,12 @@ Enables or disables printing of Python stack traces."),
gdbpy_initialize_frames ();
gdbpy_initialize_commands ();
gdbpy_initialize_functions ();
gdbpy_initialize_objfile ();
PyRun_SimpleString ("import gdb");
observer_attach_new_objfile (gdbpy_new_objfile);
gdbpy_doc_cst = PyString_FromString ("__doc__");
/* Create a couple objects which are used for Python's stdout and
@ -465,6 +606,11 @@ static PyMethodDef GdbMethods[] =
{ "get_parameter", get_parameter, METH_VARARGS,
"Return a gdb parameter's value" },
{ "current_objfile", gdbpy_get_current_objfile, METH_NOARGS,
"Return the current Objfile being loaded, or None." },
{ "objfiles", gdbpy_objfiles, METH_NOARGS,
"Return a sequence of all loaded objfiles." },
{ "selected_frame", gdbpy_selected_frame, METH_NOARGS,
"selected_frame () -> gdb.Frame.\n\
Return the selected frame object." },

View File

@ -1,3 +1,10 @@
2009-05-27 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
tests.
* gdb.python/python-value.exp (py_objfile_tests): New proc.
Call it.
2009-05-27 Pedro Alves <pedro@codesourcery.com>
* gdb.mi/nsthrexec.c, gdb.mi/mi-nsthrexec.exp: New.

View File

@ -236,6 +236,15 @@ proc test_value_in_inferior {} {
gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
}
# A few objfile tests.
proc test_objfiles {} {
gdb_test "python\nok=False\nfor file in gdb.objfiles():\n if 'python-value' in file.filename:\n ok=True\nprint ok\nend" "True"
gdb_test "python print gdb.objfiles()\[0\].pretty_printers" "\\\[\\\]"
gdb_test "python gdb.objfiles()\[0\].pretty_printers = 0" \
"pretty_printers attribute must be a list.*Error while executing Python code."
}
# Start with a fresh gdb.
@ -256,6 +265,7 @@ test_value_creation
test_value_numeric_ops
test_value_boolean
test_value_compare
test_objfiles
# The following tests require execution.

View File

@ -71,3 +71,6 @@ gdb_py_test_multiple "indented multi-line python command" \
" print 'hello, world!'" "" \
"foo ()" "" \
"end" "hello, world!"
gdb_test "python print gdb.current_objfile()" "None"
gdb_test "python print gdb.objfiles()" "\\\[\\\]"