2009-05-27  Tom Tromey  <tromey@redhat.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Phil Muldoon  <pmuldoon@redhat.com>
	    Paul Pluzhnikov  <ppluzhnikov@google.com>

	* python/python.c (_initialize_python): Call
	gdbpy_initialize_types.
	(GdbMethods): Add "lookup_type".
	* python/python-value.c (value_object) <type>: New field.
	(valpy_dealloc): Decref type.
	(valpy_new): Initialize type.
	(valpy_get_type): New function.
	(value_to_value_object): Initialize type.
	(valpy_cast): New function.
	(value_object_getset): Add "type".
	(value_object_methods): Add "cast".
	* python/python-internal.h (type_to_type_object): Declare.
	(type_object_to_type): Likewise.
	(gdbpy_initialize_types): Likewise.
	(gdbpy_lookup_type): Declare.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-type.o.
	(SUBDIR_PYTHON_SRCS): Add python-type.c.
	(python-type.o): New target.
	* python/python-type.c: New file.

gdb/doc

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

	* gdb.texinfo (Types In Python): New node.
	(Values From Inferior): "type" is now an attribute.
	(Python API): Update.


gdb/testsuite

2009-05-27  Thiago Jung Bauermann  <bauerman@br.ibm.com>
	    Tom Tromey  <tromey@redhat.com>
	    Pedro Alves  <pedro@codesourcery.com>
	    Paul Pluzhnikov  <ppluzhnikov@google.com>

	* gdb.python/python-template.exp: New file.
	* gdb.python/python-template.cc: New file.
	* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
	tests.
	* gdb.python/python-value.exp (py_objfile_tests): New proc.
	Call it.
	(test_value_after_death): New proc.
	* gdb.python/python-value.c (PTR): New typedef.
	(main): New variable 'x'.
This commit is contained in:
Tom Tromey 2009-05-28 00:47:20 +00:00
parent 89c73adef9
commit 2c74e83381
13 changed files with 1339 additions and 6 deletions

View File

@ -1,3 +1,28 @@
2009-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>
Paul Pluzhnikov <ppluzhnikov@google.com>
* python/python.c (_initialize_python): Call
gdbpy_initialize_types.
(GdbMethods): Add "lookup_type".
* python/python-value.c (value_object) <type>: New field.
(valpy_dealloc): Decref type.
(valpy_new): Initialize type.
(valpy_get_type): New function.
(value_to_value_object): Initialize type.
(valpy_cast): New function.
(value_object_getset): Add "type".
(value_object_methods): Add "cast".
* python/python-internal.h (type_to_type_object): Declare.
(type_object_to_type): Likewise.
(gdbpy_initialize_types): Likewise.
(gdbpy_lookup_type): Declare.
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-type.o.
(SUBDIR_PYTHON_SRCS): Add python-type.c.
(python-type.o): New target.
* python/python-type.c: New file.
2009-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>

View File

@ -268,6 +268,7 @@ SUBDIR_PYTHON_OBS = \
python-frame.o \
python-function.o \
python-objfile.o \
python-type.o \
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
@ -276,6 +277,7 @@ SUBDIR_PYTHON_SRCS = \
python/python-frame.c \
python/python-function.c \
python/python-objfile.c \
python/python-type.c \
python/python-utils.c \
python/python-value.c
SUBDIR_PYTHON_DEPS =
@ -1870,6 +1872,10 @@ python-objfile.o: $(srcdir)/python/python-objfile.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-objfile.c
$(POSTCOMPILE)
python-type.o: $(srcdir)/python/python-type.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-type.c
$(POSTCOMPILE)
python-utils.o: $(srcdir)/python/python-utils.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
$(POSTCOMPILE)

View File

@ -1,3 +1,10 @@
2009-05-27 Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Types In Python): New node.
(Values From Inferior): "type" is now an attribute.
(Python API): Update.
2009-05-27 Tom Tromey <tromey@redhat.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Phil Muldoon <pmuldoon@redhat.com>

View File

@ -18516,6 +18516,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
* Exception Handling::
* Auto-loading:: Automatically loading Python code.
* Values From Inferior::
* Types In Python:: Python representation of types.
* Commands In Python:: Implementing new commands in Python.
* Functions In Python:: Writing new convenience functions.
* Objfiles In Python:: Object files.
@ -18701,17 +18702,22 @@ Again, @code{bar} will also be a @code{gdb.Value} object.
The following attributes are provided:
@table @code
@defmethod Value address
@defivar Value address
If this object is addressable, this read-only attribute holds a
@code{gdb.Value} object representing the address. Otherwise,
this attribute holds @code{None}.
@end defmethod
@end defivar
@cindex optimized out value in Python
@defmethod Value is_optimized_out
@defivar Value is_optimized_out
This read-only boolean attribute is true if the compiler optimized out
this value, thus it is not available for fetching from the inferior.
@end defmethod
@end defivar
@defivar Value type
The type of this @code{gdb.Value}. The value of this attribute is a
@code{gdb.Type} object.
@end defivar
@end table
The following methods are provided:
@ -18766,6 +18772,278 @@ argument to Python's @code{string.decode} method.
@end defmethod
@end table
@node Types In Python
@subsubsection Types In Python
@cindex types in Python
@cindex Python, working with types
@tindex gdb.Type
@value{GDBN} represents types from the inferior using the class
@code{gdb.Type}.
The following type-related functions are available in the @code{gdb}
module:
@findex gdb.lookup_type
@defun lookup_type name [block]
This function looks up a type by name. @var{name} is the name of the
type to look up. It must be a string.
Ordinarily, this function will return an instance of @code{gdb.Type}.
If the named type cannot be found, it will throw an exception.
@end defun
An instance of @code{Type} has the following attributes:
@table @code
@defivar Type code
The type code for this type. The type code will be one of the
@code{TYPE_CODE_} constants defined below.
@end defivar
@defivar Type sizeof
The size of this type, in target @code{char} units. Usually, a
target's @code{char} type will be an 8-bit byte. However, on some
unusual platforms, this type may have a different size.
@end defivar
@defivar Type tag
The tag name for this type. The tag name is the name after
@code{struct}, @code{union}, or @code{enum} in C and C@t{++}; not all
languages have this concept. If this type has no tag name, then
@code{None} is returned.
@end defivar
@end table
The following methods are provided:
@table @code
@defmethod Type fields
For structure and union types, this method returns the fields. Range
types have two fields, the minimum and maximum values. Enum types
have one field per enum constant. Function and method types have one
field per parameter. The base types of C@t{++} classes are also
represented as fields. If the type has no fields, or does not fit
into one of these categories, an empty sequence will be returned.
Each field is an object, with some pre-defined attributes:
@table @code
@item bitpos
This attribute is not available for @code{static} fields (as in
C@t{++} or Java). For non-@code{static} fields, the value is the bit
position of the field.
@item name
The name of the field, or @code{None} for anonymous fields.
@item artificial
This is @code{True} if the field is artificial, usually meaning that
it was provided by the compiler and not the user. This attribute is
always provided, and is @code{False} if the field is not artificial.
@item bitsize
If the field is packed, or is a bitfield, then this will have a
non-zero value, which is the size of the field in bits. Otherwise,
this will be zero; in this case the field's size is given by its type.
@item type
The type of the field. This is usually an instance of @code{Type},
but it can be @code{None} in some situations.
@end table
@end defmethod
@defmethod Type const
Return a new @code{gdb.Type} object which represents a
@code{const}-qualified variant of this type.
@end defmethod
@defmethod Type volatile
Return a new @code{gdb.Type} object which represents a
@code{volatile}-qualified variant of this type.
@end defmethod
@defmethod Type unqualified
Return a new @code{gdb.Type} object which represents an unqualified
variant of this type. That is, the result is neither @code{const} nor
@code{volatile}.
@end defmethod
@defmethod Type reference
Return a new @code{gdb.Type} object which represents a reference to this
type.
@end defmethod
@defmethod Type strip_typedefs
Return a new @code{gdb.Type} that represents the real type,
after removing all layers of typedefs.
@end defmethod
@defmethod Type target
Return a new @code{gdb.Type} object which represents the target type
of this type.
For a pointer type, the target type is the type of the pointed-to
object. For an array type (meaning C-like arrays), the target type is
the type of the elements of the array. For a function or method type,
the target type is the type of the return value. For a complex type,
the target type is the type of the elements. For a typedef, the
target type is the aliased type.
If the type does not have a target, this method will throw an
exception.
@end defmethod
@defmethod Type template_argument n
If this @code{gdb.Type} is an instantiation of a template, this will
return a new @code{gdb.Type} which represents the type of the
@var{n}th template argument.
If this @code{gdb.Type} is not a template type, this will throw an
exception. Ordinarily, only C@t{++} code will have template types.
@var{name} is searched for globally.
@end defmethod
@end table
Each type has a code, which indicates what category this type falls
into. The available type categories are represented by constants
defined in the @code{gdb} module:
@table @code
@findex TYPE_CODE_PTR
@findex gdb.TYPE_CODE_PTR
@item TYPE_CODE_PTR
The type is a pointer.
@findex TYPE_CODE_ARRAY
@findex gdb.TYPE_CODE_ARRAY
@item TYPE_CODE_ARRAY
The type is an array.
@findex TYPE_CODE_STRUCT
@findex gdb.TYPE_CODE_STRUCT
@item TYPE_CODE_STRUCT
The type is a structure.
@findex TYPE_CODE_UNION
@findex gdb.TYPE_CODE_UNION
@item TYPE_CODE_UNION
The type is a union.
@findex TYPE_CODE_ENUM
@findex gdb.TYPE_CODE_ENUM
@item TYPE_CODE_ENUM
The type is an enum.
@findex TYPE_CODE_FLAGS
@findex gdb.TYPE_CODE_FLAGS
@item TYPE_CODE_FLAGS
A bit flags type, used for things such as status registers.
@findex TYPE_CODE_FUNC
@findex gdb.TYPE_CODE_FUNC
@item TYPE_CODE_FUNC
The type is a function.
@findex TYPE_CODE_INT
@findex gdb.TYPE_CODE_INT
@item TYPE_CODE_INT
The type is an integer type.
@findex TYPE_CODE_FLT
@findex gdb.TYPE_CODE_FLT
@item TYPE_CODE_FLT
A floating point type.
@findex TYPE_CODE_VOID
@findex gdb.TYPE_CODE_VOID
@item TYPE_CODE_VOID
The special type @code{void}.
@findex TYPE_CODE_SET
@findex gdb.TYPE_CODE_SET
@item TYPE_CODE_SET
A Pascal set type.
@findex TYPE_CODE_RANGE
@findex gdb.TYPE_CODE_RANGE
@item TYPE_CODE_RANGE
A range type, that is, an integer type with bounds.
@findex TYPE_CODE_STRING
@findex gdb.TYPE_CODE_STRING
@item TYPE_CODE_STRING
A string type. Note that this is only used for certain languages with
language-defined string types; C strings are not represented this way.
@findex TYPE_CODE_BITSTRING
@findex gdb.TYPE_CODE_BITSTRING
@item TYPE_CODE_BITSTRING
A string of bits.
@findex TYPE_CODE_ERROR
@findex gdb.TYPE_CODE_ERROR
@item TYPE_CODE_ERROR
An unknown or erroneous type.
@findex TYPE_CODE_METHOD
@findex gdb.TYPE_CODE_METHOD
@item TYPE_CODE_METHOD
A method type, as found in C@t{++} or Java.
@findex TYPE_CODE_METHODPTR
@findex gdb.TYPE_CODE_METHODPTR
@item TYPE_CODE_METHODPTR
A pointer-to-member-function.
@findex TYPE_CODE_MEMBERPTR
@findex gdb.TYPE_CODE_MEMBERPTR
@item TYPE_CODE_MEMBERPTR
A pointer-to-member.
@findex TYPE_CODE_REF
@findex gdb.TYPE_CODE_REF
@item TYPE_CODE_REF
A reference type.
@findex TYPE_CODE_CHAR
@findex gdb.TYPE_CODE_CHAR
@item TYPE_CODE_CHAR
A character type.
@findex TYPE_CODE_BOOL
@findex gdb.TYPE_CODE_BOOL
@item TYPE_CODE_BOOL
A boolean type.
@findex TYPE_CODE_COMPLEX
@findex gdb.TYPE_CODE_COMPLEX
@item TYPE_CODE_COMPLEX
A complex float type.
@findex TYPE_CODE_TYPEDEF
@findex gdb.TYPE_CODE_TYPEDEF
@item TYPE_CODE_TYPEDEF
A typedef to some other type.
@findex TYPE_CODE_NAMESPACE
@findex gdb.TYPE_CODE_NAMESPACE
@item TYPE_CODE_NAMESPACE
A C@t{++} namespace.
@findex TYPE_CODE_DECFLOAT
@findex gdb.TYPE_CODE_DECFLOAT
@item TYPE_CODE_DECFLOAT
A decimal floating point type.
@findex TYPE_CODE_INTERNAL_FUNCTION
@findex gdb.TYPE_CODE_INTERNAL_FUNCTION
@item TYPE_CODE_INTERNAL_FUNCTION
A function internal to @value{GDBN}. This is the type used to represent
convenience functions.
@end table
@node Commands In Python
@subsubsection Commands In Python

View File

@ -66,17 +66,21 @@ extern PyTypeObject value_object_type;
PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
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 value *convert_value_from_python (PyObject *obj);
struct type *type_object_to_type (PyObject *obj);
void gdbpy_initialize_values (void);
void gdbpy_initialize_frames (void);
void gdbpy_initialize_commands (void);
void gdbpy_initialize_types (void);
void gdbpy_initialize_functions (void);
void gdbpy_initialize_objfile (void);

799
gdb/python/python-type.c Normal file
View File

@ -0,0 +1,799 @@
/* Python interface to types.
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 "value.h"
#include "exceptions.h"
#include "python-internal.h"
#include "charset.h"
#include "gdbtypes.h"
#include "cp-support.h"
#include "demangle.h"
#include "objfiles.h"
typedef struct pyty_type_object
{
PyObject_HEAD
struct type *type;
/* If a Type object is associated with an objfile, it is kept on a
doubly-linked list, rooted in the objfile. This lets us copy the
underlying struct type when the objfile is deleted. */
struct pyty_type_object *prev;
struct pyty_type_object *next;
} type_object;
static PyTypeObject type_object_type;
/* A Field object. */
typedef struct pyty_field_object
{
PyObject_HEAD
/* Dictionary holding our attributes. */
PyObject *dict;
} field_object;
static PyTypeObject field_object_type;
/* This is used to initialize various gdb.TYPE_ constants. */
struct pyty_code
{
/* The code. */
enum type_code code;
/* The name. */
const char *name;
};
#define ENTRY(X) { X, #X }
static struct pyty_code pyty_codes[] =
{
ENTRY (TYPE_CODE_PTR),
ENTRY (TYPE_CODE_ARRAY),
ENTRY (TYPE_CODE_STRUCT),
ENTRY (TYPE_CODE_UNION),
ENTRY (TYPE_CODE_ENUM),
ENTRY (TYPE_CODE_FLAGS),
ENTRY (TYPE_CODE_FUNC),
ENTRY (TYPE_CODE_INT),
ENTRY (TYPE_CODE_FLT),
ENTRY (TYPE_CODE_VOID),
ENTRY (TYPE_CODE_SET),
ENTRY (TYPE_CODE_RANGE),
ENTRY (TYPE_CODE_STRING),
ENTRY (TYPE_CODE_BITSTRING),
ENTRY (TYPE_CODE_ERROR),
ENTRY (TYPE_CODE_METHOD),
ENTRY (TYPE_CODE_METHODPTR),
ENTRY (TYPE_CODE_MEMBERPTR),
ENTRY (TYPE_CODE_REF),
ENTRY (TYPE_CODE_CHAR),
ENTRY (TYPE_CODE_BOOL),
ENTRY (TYPE_CODE_COMPLEX),
ENTRY (TYPE_CODE_TYPEDEF),
ENTRY (TYPE_CODE_NAMESPACE),
ENTRY (TYPE_CODE_DECFLOAT),
ENTRY (TYPE_CODE_INTERNAL_FUNCTION),
{ TYPE_CODE_UNDEF, NULL }
};
static void
field_dealloc (PyObject *obj)
{
field_object *f = (field_object *) obj;
Py_XDECREF (f->dict);
f->ob_type->tp_free (obj);
}
static PyObject *
field_new (void)
{
field_object *result = PyObject_New (field_object, &field_object_type);
if (result)
{
result->dict = PyDict_New ();
if (!result->dict)
{
Py_DECREF (result);
result = NULL;
}
}
return (PyObject *) result;
}
/* Return the code for this type. */
static PyObject *
typy_get_code (PyObject *self, void *closure)
{
struct type *type = ((type_object *) self)->type;
return PyInt_FromLong (TYPE_CODE (type));
}
/* Helper function for typy_fields which converts a single field to a
dictionary. Returns NULL on error. */
static PyObject *
convert_field (struct type *type, int field)
{
PyObject *result = field_new ();
PyObject *arg;
if (!result)
return NULL;
if (!field_is_static (&TYPE_FIELD (type, field)))
{
arg = PyLong_FromLong (TYPE_FIELD_BITPOS (type, field));
if (!arg)
goto fail;
if (PyObject_SetAttrString (result, "bitpos", arg) < 0)
goto failarg;
}
if (TYPE_FIELD_NAME (type, field))
arg = PyString_FromString (TYPE_FIELD_NAME (type, field));
else
{
arg = Py_None;
Py_INCREF (arg);
}
if (!arg)
goto fail;
if (PyObject_SetAttrString (result, "name", arg) < 0)
goto failarg;
arg = TYPE_FIELD_ARTIFICIAL (type, field) ? Py_True : Py_False;
Py_INCREF (arg);
if (PyObject_SetAttrString (result, "artificial", arg) < 0)
goto failarg;
arg = PyLong_FromLong (TYPE_FIELD_BITSIZE (type, field));
if (!arg)
goto fail;
if (PyObject_SetAttrString (result, "bitsize", arg) < 0)
goto failarg;
/* A field can have a NULL type in some situations. */
if (TYPE_FIELD_TYPE (type, field) == NULL)
{
arg = Py_None;
Py_INCREF (arg);
}
else
arg = type_to_type_object (TYPE_FIELD_TYPE (type, field));
if (!arg)
goto fail;
if (PyObject_SetAttrString (result, "type", arg) < 0)
goto failarg;
return result;
failarg:
Py_DECREF (arg);
fail:
Py_DECREF (result);
return NULL;
}
/* Return a sequence of all fields. Each field is a dictionary with
some pre-defined keys. */
static PyObject *
typy_fields (PyObject *self, PyObject *args)
{
PyObject *result;
int i;
struct type *type = ((type_object *) self)->type;
/* We would like to make a tuple here, make fields immutable, and
then memoize the result (and perhaps make Field.type() lazy).
However, that can lead to cycles. */
result = PyList_New (0);
for (i = 0; i < TYPE_NFIELDS (type); ++i)
{
PyObject *dict = convert_field (type, i);
if (!dict)
{
Py_DECREF (result);
return NULL;
}
if (PyList_Append (result, dict))
{
Py_DECREF (dict);
Py_DECREF (result);
return NULL;
}
}
return result;
}
/* Return the type's tag, or None. */
static PyObject *
typy_get_tag (PyObject *self, void *closure)
{
struct type *type = ((type_object *) self)->type;
if (!TYPE_TAG_NAME (type))
Py_RETURN_NONE;
return PyString_FromString (TYPE_TAG_NAME (type));
}
/* Return the type, stripped of typedefs. */
static PyObject *
typy_strip_typedefs (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
return type_to_type_object (check_typedef (type));
}
/* Return a Type object which represents a pointer to SELF. */
static PyObject *
typy_pointer (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
type = lookup_pointer_type (type);
}
GDB_PY_HANDLE_EXCEPTION (except);
return type_to_type_object (type);
}
/* Return a Type object which represents a reference to SELF. */
static PyObject *
typy_reference (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
type = lookup_reference_type (type);
}
GDB_PY_HANDLE_EXCEPTION (except);
return type_to_type_object (type);
}
/* Return a Type object which represents the target type of SELF. */
static PyObject *
typy_target (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
if (!TYPE_TARGET_TYPE (type))
{
PyErr_SetString (PyExc_RuntimeError, "type does not have a target");
return NULL;
}
return type_to_type_object (TYPE_TARGET_TYPE (type));
}
/* Return a const-qualified type variant. */
static PyObject *
typy_const (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
type = make_cv_type (1, 0, type, NULL);
}
GDB_PY_HANDLE_EXCEPTION (except);
return type_to_type_object (type);
}
/* Return a volatile-qualified type variant. */
static PyObject *
typy_volatile (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
type = make_cv_type (0, 1, type, NULL);
}
GDB_PY_HANDLE_EXCEPTION (except);
return type_to_type_object (type);
}
/* Return an unqualified type variant. */
static PyObject *
typy_unqualified (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
type = make_cv_type (0, 0, type, NULL);
}
GDB_PY_HANDLE_EXCEPTION (except);
return type_to_type_object (type);
}
/* Return the size of the type represented by SELF, in bytes. */
static PyObject *
typy_get_sizeof (PyObject *self, void *closure)
{
struct type *type = ((type_object *) self)->type;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
check_typedef (type);
}
/* Ignore exceptions. */
return PyLong_FromLong (TYPE_LENGTH (type));
}
static struct type *
typy_lookup_typename (char *type_name)
{
struct type *type = NULL;
volatile struct gdb_exception except;
TRY_CATCH (except, RETURN_MASK_ALL)
{
if (!strncmp (type_name, "struct ", 7))
type = lookup_struct (type_name + 7, NULL);
else if (!strncmp (type_name, "union ", 6))
type = lookup_union (type_name + 6, NULL);
else if (!strncmp (type_name, "enum ", 5))
type = lookup_enum (type_name + 5, NULL);
else
type = lookup_typename (type_name, NULL, 0);
}
if (except.reason < 0)
{
PyErr_Format (except.reason == RETURN_QUIT
? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
"%s", except.message);
return NULL;
}
return type;
}
static struct type *
typy_lookup_type (struct demangle_component *demangled)
{
struct type *type;
char *type_name;
enum demangle_component_type demangled_type;
/* Save the type: typy_lookup_type() may (indirectly) overwrite
memory pointed by demangled. */
demangled_type = demangled->type;
if (demangled_type == DEMANGLE_COMPONENT_POINTER
|| demangled_type == DEMANGLE_COMPONENT_REFERENCE
|| demangled_type == DEMANGLE_COMPONENT_CONST
|| demangled_type == DEMANGLE_COMPONENT_VOLATILE)
{
type = typy_lookup_type (demangled->u.s_binary.left);
if (! type)
return NULL;
switch (demangled_type)
{
case DEMANGLE_COMPONENT_REFERENCE:
return lookup_reference_type (type);
case DEMANGLE_COMPONENT_POINTER:
return lookup_pointer_type (type);
case DEMANGLE_COMPONENT_CONST:
return make_cv_type (1, 0, type, NULL);
case DEMANGLE_COMPONENT_VOLATILE:
return make_cv_type (0, 1, type, NULL);
}
}
type_name = cp_comp_to_string (demangled, 10);
type = typy_lookup_typename (type_name);
xfree (type_name);
return type;
}
static PyObject *
typy_template_argument (PyObject *self, PyObject *args)
{
int i, argno, n_pointers;
struct type *type = ((type_object *) self)->type;
struct demangle_component *demangled;
const char *err;
struct type *argtype;
if (! PyArg_ParseTuple (args, "i", &argno))
return NULL;
type = check_typedef (type);
if (TYPE_CODE (type) == TYPE_CODE_REF)
type = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_NAME (type) == NULL)
{
PyErr_SetString (PyExc_RuntimeError, "null type name");
return NULL;
}
/* Note -- this is not thread-safe. */
demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
if (! demangled)
{
PyErr_SetString (PyExc_RuntimeError, err);
return NULL;
}
/* Strip off component names. */
while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
|| demangled->type == DEMANGLE_COMPONENT_LOCAL_NAME)
demangled = demangled->u.s_binary.right;
if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
{
PyErr_SetString (PyExc_RuntimeError, "type is not a template");
return NULL;
}
/* Skip from the template to the arguments. */
demangled = demangled->u.s_binary.right;
for (i = 0; demangled && i < argno; ++i)
demangled = demangled->u.s_binary.right;
if (! demangled)
{
PyErr_Format (PyExc_RuntimeError, "no argument %d in template",
argno);
return NULL;
}
argtype = typy_lookup_type (demangled->u.s_binary.left);
if (! argtype)
return NULL;
return type_to_type_object (argtype);
}
static PyObject *
typy_str (PyObject *self)
{
volatile struct gdb_exception except;
char *thetype = NULL;
PyObject *result;
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct cleanup *old_chain;
struct ui_file *stb;
long length;
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
type_print (type_object_to_type (self), "", stb, -1);
thetype = ui_file_xstrdup (stb, &length);
do_cleanups (old_chain);
}
if (except.reason < 0)
{
xfree (thetype);
GDB_PY_HANDLE_EXCEPTION (except);
}
result = PyUnicode_Decode (thetype, strlen (thetype), host_charset (), NULL);
xfree (thetype);
return result;
}
static const struct objfile_data *typy_objfile_data_key;
static void
clean_up_objfile_types (struct objfile *objfile, void *datum)
{
type_object *obj = datum;
htab_t copied_types;
struct cleanup *cleanup;
PyGILState_STATE state;
/* This prevents another thread from freeing the objects we're
operating on. */
state = PyGILState_Ensure ();
cleanup = make_cleanup_py_restore_gil (&state);
copied_types = create_copied_types_hash (objfile);
while (obj)
{
type_object *next = obj->next;
htab_empty (copied_types);
obj->type = copy_type_recursive (objfile, obj->type, copied_types);
obj->next = NULL;
obj->prev = NULL;
obj = next;
}
htab_delete (copied_types);
do_cleanups (cleanup);
}
static void
set_type (type_object *obj, struct type *type)
{
obj->type = type;
obj->prev = NULL;
if (type && TYPE_OBJFILE (type))
{
struct objfile *objfile = TYPE_OBJFILE (type);
obj->next = objfile_data (objfile, typy_objfile_data_key);
if (obj->next)
obj->next->prev = obj;
set_objfile_data (objfile, typy_objfile_data_key, obj);
}
else
obj->next = NULL;
}
static void
typy_dealloc (PyObject *obj)
{
type_object *type = (type_object *) obj;
if (type->prev)
type->prev->next = type->next;
else if (type->type && TYPE_OBJFILE (type->type))
{
/* Must reset head of list. */
struct objfile *objfile = TYPE_OBJFILE (type->type);
if (objfile)
set_objfile_data (objfile, typy_objfile_data_key, type->next);
}
if (type->next)
type->next->prev = type->prev;
type->ob_type->tp_free (type);
}
/* Create a new Type referring to TYPE. */
PyObject *
type_to_type_object (struct type *type)
{
type_object *type_obj;
type_obj = PyObject_New (type_object, &type_object_type);
if (type_obj)
set_type (type_obj, type);
return (PyObject *) type_obj;
}
struct type *
type_object_to_type (PyObject *obj)
{
if (! PyObject_TypeCheck (obj, &type_object_type))
return NULL;
return ((type_object *) obj)->type;
}
/* Implementation of gdb.lookup_type. */
PyObject *
gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
{
static char *keywords[] = { "name", NULL };
char *type_name = NULL;
struct type *type = NULL;
if (! PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &type_name))
return NULL;
type = typy_lookup_typename (type_name);
if (! type)
return NULL;
return (PyObject *) type_to_type_object (type);
}
void
gdbpy_initialize_types (void)
{
int i;
typy_objfile_data_key
= register_objfile_data_with_cleanup (clean_up_objfile_types);
if (PyType_Ready (&type_object_type) < 0)
return;
if (PyType_Ready (&field_object_type) < 0)
return;
for (i = 0; pyty_codes[i].name; ++i)
{
if (PyModule_AddIntConstant (gdb_module,
/* Cast needed for Python 2.4. */
(char *) pyty_codes[i].name,
pyty_codes[i].code) < 0)
return;
}
Py_INCREF (&type_object_type);
PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type);
Py_INCREF (&field_object_type);
PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type);
}
static PyGetSetDef type_object_getset[] =
{
{ "code", typy_get_code, NULL,
"The code for this type.", NULL },
{ "sizeof", typy_get_sizeof, NULL,
"The size of this type, in bytes.", NULL },
{ "tag", typy_get_tag, NULL,
"The tag name for this type, or None.", NULL },
{ NULL }
};
static PyMethodDef type_object_methods[] =
{
{ "const", typy_const, METH_NOARGS,
"const () -> Type\n\
Return a const variant of this type." },
{ "fields", typy_fields, METH_NOARGS,
"field () -> list\n\
Return a sequence holding all the fields of this type.\n\
Each field is a dictionary." },
{ "pointer", typy_pointer, METH_NOARGS,
"pointer () -> Type\n\
Return a type of pointer to this type." },
{ "reference", typy_reference, METH_NOARGS,
"reference () -> Type\n\
Return a type of reference to this type." },
{ "strip_typedefs", typy_strip_typedefs, METH_NOARGS,
"strip_typedefs () -> Type\n\
Return a type formed by stripping this type of all typedefs."},
{ "target", typy_target, METH_NOARGS,
"target () -> Type\n\
Return the target type of this type." },
{ "template_argument", typy_template_argument, METH_VARARGS,
"template_argument (arg) -> Type\n\
Return the type of a template argument." },
{ "unqualified", typy_unqualified, METH_NOARGS,
"unqualified () -> Type\n\
Return a variant of this type without const or volatile attributes." },
{ "volatile", typy_volatile, METH_NOARGS,
"volatile () -> Type\n\
Return a volatile variant of this type" },
{ NULL }
};
static PyTypeObject type_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"gdb.Type", /*tp_name*/
sizeof (type_object), /*tp_basicsize*/
0, /*tp_itemsize*/
typy_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*/
typy_str, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
"GDB type object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
type_object_methods, /* tp_methods */
0, /* tp_members */
type_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 */
0, /* tp_new */
};
static PyTypeObject field_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"gdb.Field", /*tp_name*/
sizeof (field_object), /*tp_basicsize*/
0, /*tp_itemsize*/
field_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 field 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 */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof (field_object, dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};

View File

@ -59,6 +59,7 @@ typedef struct {
PyObject_HEAD
struct value *value;
PyObject *address;
PyObject *type;
} value_object;
/* Called by the Python interpreter when deallocating a value object. */
@ -77,6 +78,11 @@ valpy_dealloc (PyObject *obj)
Py_DECREF (self->address);
}
if (self->type)
{
Py_DECREF (self->type);
}
self->ob_type->tp_free (self);
}
@ -111,6 +117,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
value_obj->value = value;
value_obj->address = NULL;
value_obj->type = NULL;
release_value (value);
value_prepend_to_list (&values_in_python, value);
@ -161,6 +168,24 @@ valpy_get_address (PyObject *self, void *closure)
return val_obj->address;
}
/* Return type of the value. */
static PyObject *
valpy_get_type (PyObject *self, void *closure)
{
value_object *obj = (value_object *) self;
if (!obj->type)
{
obj->type = type_to_type_object (value_type (obj->value));
if (!obj->type)
{
obj->type = Py_None;
Py_INCREF (obj->type);
}
}
Py_INCREF (obj->type);
return obj->type;
}
/* Implementation of gdb.Value.string ([encoding] [, errors]) -> string
Return Unicode string with value contents. If ENCODING is not given,
the string is assumed to be encoded in the target's charset. */
@ -195,6 +220,34 @@ valpy_string (PyObject *self, PyObject *args, PyObject *kw)
return unicode;
}
/* Cast a value to a given type. */
static PyObject *
valpy_cast (PyObject *self, PyObject *args)
{
PyObject *type_obj;
struct type *type;
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
volatile struct gdb_exception except;
if (! PyArg_ParseTuple (args, "O", &type_obj))
return NULL;
type = type_object_to_type (type_obj);
if (! type)
{
PyErr_SetString (PyExc_RuntimeError, "argument must be a Type");
return NULL;
}
TRY_CATCH (except, RETURN_MASK_ALL)
{
res_val = value_cast (type, ((value_object *) self)->value);
}
GDB_PY_HANDLE_EXCEPTION (except);
return value_to_value_object (res_val);
}
static Py_ssize_t
valpy_length (PyObject *self)
{
@ -744,6 +797,7 @@ value_to_value_object (struct value *val)
{
val_obj->value = val;
val_obj->address = NULL;
val_obj->type = NULL;
release_value (val);
value_prepend_to_list (&values_in_python, val);
}
@ -855,16 +909,20 @@ gdbpy_initialize_values (void)
values_in_python = NULL;
}
static PyGetSetDef value_object_getset[] = {
{ "address", valpy_get_address, NULL, "The address of the value.",
NULL },
{ "is_optimized_out", valpy_get_is_optimized_out, NULL,
"Boolean telling whether the value is optimized out (i.e., not available).",
NULL },
{ "type", valpy_get_type, NULL, "Type of the value.", NULL },
{NULL} /* Sentinel */
};
static PyMethodDef value_object_methods[] = {
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
"string ([encoding] [, errors]) -> string\n\

View File

@ -552,6 +552,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
gdbpy_initialize_frames ();
gdbpy_initialize_commands ();
gdbpy_initialize_functions ();
gdbpy_initialize_types ();
gdbpy_initialize_objfile ();
PyRun_SimpleString ("import gdb");
@ -618,6 +619,11 @@ Return the selected frame object." },
"stop_reason_string (Integer) -> String.\n\
Return a string explaining unwind stop reason." },
{ "lookup_type", (PyCFunction) gdbpy_lookup_type,
METH_VARARGS | METH_KEYWORDS,
"lookup_type (name [, block]) -> type\n\
Return a Type corresponding to the given name." },
{ "write", gdbpy_write, METH_VARARGS,
"Write a string using gdb's filtered stream." },
{ "flush", gdbpy_flush, METH_NOARGS,

View File

@ -1,3 +1,18 @@
2009-05-27 Thiago Jung Bauermann <bauerman@br.ibm.com>
Tom Tromey <tromey@redhat.com>
Pedro Alves <pedro@codesourcery.com>
Paul Pluzhnikov <ppluzhnikov@google.com>
* gdb.python/python-template.exp: New file.
* gdb.python/python-template.cc: New file.
* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile
tests.
* gdb.python/python-value.exp (py_objfile_tests): New proc.
Call it.
(test_value_after_death): New proc.
* gdb.python/python-value.c (PTR): New typedef.
(main): New variable 'x'.
2009-05-27 Tom Tromey <tromey@redhat.com>
* gdb.python/python.exp (gdb_py_test_multiple): Add two objfile

View File

@ -0,0 +1,30 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2008 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/>. */
template <typename T>
struct Foo {
};
#ifndef TYPE
#define TYPE int
#endif
int main()
{
Foo<TYPE> foo;
return 0; // break here
}

View File

@ -0,0 +1,75 @@
# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This file is part of the GDB testsuite. It tests the mechanism
# exposing values to Python.
if $tracelevel then {
strace $tracelevel
}
set testfile "python-template"
set srcfile ${testfile}.cc
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
{debug c++}] != "" } {
untested "Couldn't compile ${srcfile}"
return -1
}
# Start with a fresh gdb.
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_test_multiple "python print 23" "verify python support" {
-re "not supported.*$gdb_prompt $" {
unsupported "python support is disabled"
return -1
}
-re "$gdb_prompt $" {}
}
proc test_template_arg {type} {
global testfile srcdir subdir srcfile binfile
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
executable \
[list debug c++ additional_flags="-DTYPE=$type"]] != "" } {
untested $type
return -1
}
gdb_load ${binfile}
if ![runto_main ] then {
perror "couldn't run to breakpoint"
return
}
# There is no executable code in main(), so we are where we want to be
gdb_test "print foo" ""
gdb_test "python foo = gdb.history(0)" ""
# Replace '*' with '\*' in regex.
regsub -all {\*} $type {\*} t
gdb_test "python print foo.type.template_argument(0)" $t $type
}
test_template_arg "const int"
test_template_arg "volatile int"
test_template_arg "const int &"
test_template_arg "volatile int &"
test_template_arg "volatile int * const"
test_template_arg "volatile int * const *"
test_template_arg "const int * volatile"
test_template_arg "const int * volatile * const * volatile *"

View File

@ -33,19 +33,21 @@ enum e
TWO = 2
};
typedef struct s *PTR;
enum e evalue = TWO;
int
main (int argc, char *argv[])
{
char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out. */
struct s s;
union u u;
PTR x = &s;
s.a = 3;
s.b = 5;
u.a = 7;
argv[0][0] = 'a'; /* Just to avoid getting argv optimized out. */
return 0; /* break to inspect struct and union */
}

View File

@ -246,6 +246,33 @@ proc test_objfiles {} {
"pretty_printers attribute must be a list.*Error while executing Python code."
}
proc test_value_after_death {} {
# Construct a type while the inferior is still running.
gdb_py_test_silent_cmd "python ptrtype = gdb.lookup_type('PTR')" \
"create PTR type" 1
# Kill the inferior and remove the symbols.
gdb_test "kill" "" "kill the inferior" \
"Kill the program being debugged. .y or n. $" \
"y"
gdb_test "file" "" "Discard the symbols" \
"Discard symbol table from.*y or n. $" \
"y"
# Now create a value using that type. Relies on arg0, created by
# test_value_in_inferior.
gdb_py_test_silent_cmd "python castval = arg0.cast(ptrtype.pointer())" \
"cast arg0 to PTR" 1
# Make sure the type is deleted.
gdb_py_test_silent_cmd "python ptrtype = None" \
"delete PTR type" 1
# Now see if the value's type is still valid.
gdb_test "python print castval.type" "PTR ." \
"print value's type"
}
# Start with a fresh gdb.
gdb_exit
@ -275,3 +302,4 @@ if ![runto_main] then {
}
test_value_in_inferior
test_value_after_death