Add Python support for dynamic types

This changes the gdb Python API to add support for dynamic types.  In
particular, this adds an attribute to gdb.Type, and updates some
attributes to reflect dynamic sizes and field offsets.

There's still no way to get the dynamic type from one of its concrete
instances.  This could perhaps be added if needed.

gdb/ChangeLog
2020-04-24  Tom Tromey  <tromey@adacore.com>

	PR python/23662:
	* python/py-type.c (convert_field): Handle
	FIELD_LOC_KIND_DWARF_BLOCK.
	(typy_get_sizeof): Handle TYPE_HAS_DYNAMIC_LENGTH.
	(typy_get_dynamic): Nw function.
	(type_object_getset): Add "dynamic".
	* NEWS: Add entry.

gdb/doc/ChangeLog
2020-04-24  Tom Tromey  <tromey@adacore.com>

	PR python/23662:
	* python.texi (Types In Python): Document new features.

gdb/testsuite/ChangeLog
2020-04-24  Tom Tromey  <tromey@adacore.com>

	PR python/23662:
	* gdb.ada/variant.exp: Add Python checks.
	* gdb.rust/simple.exp: Add dynamic type checks.
This commit is contained in:
Tom Tromey 2020-04-24 13:40:31 -06:00
parent adfb981595
commit 1acda8039b
8 changed files with 91 additions and 4 deletions

View file

@ -1,3 +1,13 @@
2020-04-24 Tom Tromey <tromey@adacore.com>
PR python/23662:
* python/py-type.c (convert_field): Handle
FIELD_LOC_KIND_DWARF_BLOCK.
(typy_get_sizeof): Handle TYPE_HAS_DYNAMIC_LENGTH.
(typy_get_dynamic): Nw function.
(type_object_getset): Add "dynamic".
* NEWS: Add entry.
2020-04-24 Tom Tromey <tromey@adacore.com> 2020-04-24 Tom Tromey <tromey@adacore.com>
* ada-typeprint.c (print_choices, print_variant_part) * ada-typeprint.c (print_choices, print_variant_part)

View file

@ -68,6 +68,11 @@ GNU/Linux/RISC-V (gdbserver) riscv*-*-linux*
** gdb.register_window_type can be used to implement new TUI windows ** gdb.register_window_type can be used to implement new TUI windows
in Python. in Python.
** Dynamic types can now be queried. gdb.Type has a new attribute,
"dynamic", and gdb.Type.sizeof can be None for a dynamic type. A
field of a dynamic type may have None for its "bitpos" attribute
as well.
*** Changes in GDB 9 *** Changes in GDB 9
* 'thread-exited' event is now available in the annotations interface. * 'thread-exited' event is now available in the annotations interface.

View file

@ -1,3 +1,8 @@
2020-04-24 Tom Tromey <tromey@adacore.com>
PR python/23662:
* python.texi (Types In Python): Document new features.
2020-04-15 Artur Shepilko <nomadbyte@gmail.com> 2020-04-15 Artur Shepilko <nomadbyte@gmail.com>
* gdb.texinfo: Transform @var{[host]} to [@var{host}]; this * gdb.texinfo: Transform @var{[host]} to [@var{host}]; this

View file

@ -1068,6 +1068,12 @@ The type code for this type. The type code will be one of the
@code{TYPE_CODE_} constants defined below. @code{TYPE_CODE_} constants defined below.
@end defvar @end defvar
@defvar Type.dynamic
A boolean indicating whether this type is dynamic. In some
situations, such as Rust @code{enum} types or Ada variant records, the
concrete type of a value may vary depending on its contents.
@end defvar
@defvar Type.name @defvar Type.name
The name of this type. If this type has no name, then @code{None} The name of this type. If this type has no name, then @code{None}
is returned. is returned.
@ -1076,7 +1082,9 @@ is returned.
@defvar Type.sizeof @defvar Type.sizeof
The size of this type, in target @code{char} units. Usually, a 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 target's @code{char} type will be an 8-bit byte. However, on some
unusual platforms, this type may have a different size. unusual platforms, this type may have a different size. A dynamic
type may not have a fixed size; in this case, this attribute's value
will be @code{None}.
@end defvar @end defvar
@defvar Type.tag @defvar Type.tag
@ -1106,7 +1114,9 @@ Each field is a @code{gdb.Field} object, with some pre-defined attributes:
@item bitpos @item bitpos
This attribute is not available for @code{enum} or @code{static} This attribute is not available for @code{enum} or @code{static}
(as in C@t{++}) fields. The value is the position, counting (as in C@t{++}) fields. The value is the position, counting
in bits, from the start of the containing type. in bits, from the start of the containing type. Note that, in a
dynamic type, the position of a field may not be constant. In this
case, the value will be @code{None}.
@item enumval @item enumval
This attribute is only available for @code{enum} fields, and its value This attribute is only available for @code{enum} fields, and its value

View file

@ -189,6 +189,9 @@ convert_field (struct type *type, int field)
} }
else else
{ {
if (TYPE_FIELD_LOC_KIND (type, field) == FIELD_LOC_KIND_DWARF_BLOCK)
arg = gdbpy_ref<>::new_reference (Py_None);
else
arg.reset (gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type, arg.reset (gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type,
field))); field)));
attrstring = "bitpos"; attrstring = "bitpos";
@ -710,9 +713,12 @@ typy_get_sizeof (PyObject *self, void *closure)
{ {
struct type *type = ((type_object *) self)->type; struct type *type = ((type_object *) self)->type;
bool size_varies = false;
try try
{ {
check_typedef (type); check_typedef (type);
size_varies = TYPE_HAS_DYNAMIC_LENGTH (type);
} }
catch (const gdb_exception &except) catch (const gdb_exception &except)
{ {
@ -720,6 +726,8 @@ typy_get_sizeof (PyObject *self, void *closure)
/* Ignore exceptions. */ /* Ignore exceptions. */
if (size_varies)
Py_RETURN_NONE;
return gdb_py_long_from_longest (TYPE_LENGTH (type)); return gdb_py_long_from_longest (TYPE_LENGTH (type));
} }
@ -744,6 +752,27 @@ typy_get_alignof (PyObject *self, void *closure)
return gdb_py_object_from_ulongest (align).release (); return gdb_py_object_from_ulongest (align).release ();
} }
/* Return whether or not the type is dynamic. */
static PyObject *
typy_get_dynamic (PyObject *self, void *closure)
{
struct type *type = ((type_object *) self)->type;
bool result = false;
try
{
result = is_dynamic_type (type);
}
catch (const gdb_exception &except)
{
/* Ignore exceptions. */
}
if (result)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
static struct type * static struct type *
typy_lookup_typename (const char *type_name, const struct block *block) typy_lookup_typename (const char *type_name, const struct block *block)
{ {
@ -1436,6 +1465,8 @@ static gdb_PyGetSetDef type_object_getset[] =
"The alignment of this type, in bytes.", NULL }, "The alignment of this type, in bytes.", NULL },
{ "code", typy_get_code, NULL, { "code", typy_get_code, NULL,
"The code for this type.", NULL }, "The code for this type.", NULL },
{ "dynamic", typy_get_dynamic, NULL,
"Whether this type is dynamic.", NULL },
{ "name", typy_get_name, NULL, { "name", typy_get_name, NULL,
"The name for this type, or None.", NULL }, "The name for this type, or None.", NULL },
{ "sizeof", typy_get_sizeof, NULL, { "sizeof", typy_get_sizeof, NULL,

View file

@ -1,3 +1,9 @@
2020-04-24 Tom Tromey <tromey@adacore.com>
PR python/23662:
* gdb.ada/variant.exp: Add Python checks.
* gdb.rust/simple.exp: Add dynamic type checks.
2020-04-24 Tom Tromey <tromey@adacore.com> 2020-04-24 Tom Tromey <tromey@adacore.com>
* gdb.ada/mi_var_array.exp: Try all -fgnat-encodings settings. * gdb.ada/mi_var_array.exp: Try all -fgnat-encodings settings.

View file

@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
load_lib "ada.exp" load_lib "ada.exp"
load_lib "gdb-python.exp"
standard_ada_testfile pkg standard_ada_testfile pkg
@ -43,4 +44,13 @@ foreach_with_prefix scenario {none all minimal} {
" = \\(one => 3, two => 0, str => \"zzz\", onevalue => 33, str2 => \"\"\\)" " = \\(one => 3, two => 0, str => \"zzz\", onevalue => 33, str2 => \"\"\\)"
gdb_test "print nav3" \ gdb_test "print nav3" \
" = \\(one => 3, two => 7, str => \"zzz\", onevalue => 33, str2 => \"qqqqqqq\", twovalue => 88\\)" " = \\(one => 3, two => 7, str => \"zzz\", onevalue => 33, str2 => \"qqqqqqq\", twovalue => 88\\)"
# This is only supported for the DWARF encoding.
if {$scenario == "minimal" && ![skip_python_tests]} {
gdb_test_no_output \
"python t = gdb.lookup_type('nested_and_variable')" \
"fetch type for python"
gdb_test "python print(t.dynamic)" "True"
gdb_test "python print(t\['onevalue'\].bitpos)" "None"
}
} }

View file

@ -364,3 +364,13 @@ if {[skip_python_tests]} {
} }
gdb_test "python print(gdb.lookup_type('simple::HiBob'))" "simple::HiBob" gdb_test "python print(gdb.lookup_type('simple::HiBob'))" "simple::HiBob"
gdb_test_no_output "python e = gdb.parse_and_eval('e')" \
"get value of e for python"
gdb_test "python print(len(e.type.fields()))" "2"
gdb_test "python print(e.type.fields()\[0\].artificial)" "True"
gdb_test "python print(e.type.fields()\[1\].name)" "Two"
gdb_test "python print(e.type.dynamic)" "False"
gdb_test "python print(gdb.lookup_type('simple::MoreComplicated').dynamic)" \
"True"