mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-03 04:12:10 +08:00
gdb
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:
parent
89c73adef9
commit
2c74e83381
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
799
gdb/python/python-type.c
Normal 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 */
|
||||
};
|
@ -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\
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
30
gdb/testsuite/gdb.python/python-template.cc
Normal file
30
gdb/testsuite/gdb.python/python-template.cc
Normal 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
|
||||
}
|
75
gdb/testsuite/gdb.python/python-template.exp
Normal file
75
gdb/testsuite/gdb.python/python-template.exp
Normal 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 *"
|
@ -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 */
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user