From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by sourceware.org (Postfix) with ESMTPS id 8E37C3858D33 for ; Tue, 27 Jun 2023 03:53:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8E37C3858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-570002c9b38so42598327b3.1 for ; Mon, 26 Jun 2023 20:53:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1687837983; x=1690429983; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=3bSKKh/CCPoserB6091PHoCeUrtHTmxqrDqA1+iqg9M=; b=sfmf4vf2v9EODkzV6mTOat66e/e1twcJd590ioiXhtjOzonhjEJtK68thwS7dVIgnf zodA/Q4m1k9xGA8x+QM2Tqr5MQnZnHx4X+t6YGhjpPoaZId1kVc1VILRM5C09oV6Qh2m m4m7upRC2E39dpR6q/JFltOgHoOoeFiyKA9SFnlG00yDySCLz6bBhO64iI825KTZjaKX gPFHYMQ0Yg9e9mP6DDLiTKZ+6kH5s6yyE4ERDuhKQZ1bWj0qM9bE7+BorDdCNdfbZo5k pLN637NIDTR4dYWogKWidYq4YuQ3mAYUgOCU1QSQ18zhn7qkTGb3q35UUWCMwrYaw2FN bhDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1687837983; x=1690429983; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3bSKKh/CCPoserB6091PHoCeUrtHTmxqrDqA1+iqg9M=; b=eCUpvaUuGZ42n9B+u4cEdAhLUuFu0cf/+a3S+FBdHhY9+6oZkHnYL/p+WLqQTKMIz8 MOKSqGLUWzeRjN96A4pvYOAz/3kgQ5lqrSLPXegcWbLYOZCdH48sKV9IlBuOLh6rW/3V Dz/jp58C6SosrKR5m1N0awethY4k1R3XGTAwOd1rf+FnWqtQeIQFbqOvWgj4NmZXr4Fp Yk/O5Rpynl2fVwBUq63eTNTUYDPMDTQS4G9aRXMngFfdwKKi7eDBqV0yT4Y0k2XQbzi4 MP5iSytb83NoYtOXiQdMdq0XyEB35UOJu9KNhen1GRhQeYNDfr+lTIGWENB2sZgVIASf R5Vw== X-Gm-Message-State: AC+VfDwCYoPgT6ZZUvaxcfH02J2rRlRdC6RLEZOuRHl0XoiQn8FAxZPP yzMMZlnc0Ru+tiIEUFsJo4MYdoKWbzY5XhaDD5a0LNtJO00= X-Google-Smtp-Source: ACHHUZ6gLIUGu2rVU+aAKkc48axnHNRgq4DzSTgX7PGf8FUEl4eeDNPVkuFjAeO9ffm86HRAxX/r9orKEh0OHnEYGLI= X-Received: by 2002:a81:520c:0:b0:565:9a3d:fb27 with SMTP id g12-20020a81520c000000b005659a3dfb27mr31063343ywb.35.1687837982931; Mon, 26 Jun 2023 20:53:02 -0700 (PDT) MIME-Version: 1.0 References: <88e10ffd-8e87-b2bf-e6b3-f4567fb50e17@simark.ca> <20230111005828.952-1-dark.ryu.550@gmail.com> In-Reply-To: <20230111005828.952-1-dark.ryu.550@gmail.com> From: Matheus Branco Borella Date: Tue, 27 Jun 2023 00:52:51 -0300 Message-ID: Subject: [PING] Re: [PATCH] Add support for creating new types from the Python API To: gdb-patches@sourceware.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-8.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Following the contribution checklist, so, pinging this. On Tue, Jan 10, 2023 at 9:58=E2=80=AFPM Matheus Branco Borella wrote: > > This patch adds support for creating types from within the Python API. It= does > so by exposing the `init_*_type` family of functions, defined in `gdbtype= s.h` to > Python and having them return `gdb.Type` objects connected to the newly m= inted > types. > > These functions are accessible in the root of the gdb module and all requ= ire > a reference to a `gdb.Objfile`. Types created from this API are exclusive= ly > objfile-owned. > > This patch also adds an extra type - `gdb.FloatFormat` - to support creat= ion of > floating point types by letting users control the format from within Pyth= on. It > is missing, however, a way to specify half formats and validation functio= ns. > > It is important to note that types created using this interface are not > automatically registered as a symbol, and so, types will become unreachab= le > unless used to create a value that otherwise references it or saved in so= me way. > > The main drawback of using the `init_*_type` family over implementing typ= e > initialization by hand is that any type that's created gets immediately > allocated on its owner objfile's obstack, regardless of what its real > lifetime requirements are. The main implication of this is that types tha= t > become unreachable will leak their memory for the lifetime of the objfile= . > > Keeping track of the initialization of the type by hand would require a > deeper change to the existing type object infrastructure. A bit too ambit= ious > for a first patch, I'd say. > > if it were to be done though, we would gain the ability to only keep in t= he > obstack types that are known to be referenced in some other way - by allo= cating > and copying the data to the obstack as other objects are created that ref= erence > it (eg. symbols). > --- > gdb/Makefile.in | 2 + > gdb/python/py-float-format.c | 297 +++++++++++++++++++++++++++ > gdb/python/py-objfile.c | 12 ++ > gdb/python/py-type-init.c | 388 +++++++++++++++++++++++++++++++++++ > gdb/python/python-internal.h | 17 ++ > gdb/python/python.c | 44 +++- > 6 files changed, 759 insertions(+), 1 deletion(-) > create mode 100644 gdb/python/py-float-format.c > create mode 100644 gdb/python/py-type-init.c > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index fb4d42c7baa..789f7dce224 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -432,6 +432,8 @@ SUBDIR_PYTHON_SRCS =3D \ > python/py-threadevent.c \ > python/py-tui.c \ > python/py-type.c \ > + python/py-type-init.c \ > + python/py-float-format.c \ > python/py-unwind.c \ > python/py-utils.c \ > python/py-value.c \ > diff --git a/gdb/python/py-float-format.c b/gdb/python/py-float-format.c > new file mode 100644 > index 00000000000..e517e410899 > --- /dev/null > +++ b/gdb/python/py-float-format.c > @@ -0,0 +1,297 @@ > +/* Accessibility of float format controls from inside the Python API > + > + Copyright (C) 2008-2023 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 .= */ > + > +#include "defs.h" > +#include "python-internal.h" > +#include "floatformat.h" > + > +/* Structure backing the float format Python interface. */ > + > +struct float_format_object > +{ > + PyObject_HEAD > + struct floatformat format; > + > + struct floatformat *float_format () > + { > + return &this->format; > + } > +}; > + > +/* Initializes the float format type and registers it with the Python in= terpreter. */ > + > +int > +gdbpy_initialize_float_format (void) > +{ > + if (PyType_Ready (&float_format_object_type) < 0) > + return -1; > + > + if (gdb_pymodule_addobject (gdb_module, "FloatFormat", > + (PyObject *) &float_format_object_type) < 0) > + return -1; > + > + return 0; > +} > + > +#define INSTANCE_FIELD_GETTER(getter_name, field_name, field_type, field= _conv) \ > + static PyObject * = \ > + getter_name (PyObject *self, void *closure) = \ > + { = \ > + float_format_object *ff =3D (float_format_object*) self; = \ > + field_type value =3D ff->float_format ()->field_name; = \ > + return field_conv (value); = \ > + } > + > +#define INSTANCE_FIELD_SETTER(getter_name, field_name, field_type, field= _conv) \ > + static int = \ > + getter_name (PyObject *self, PyObject* value, void *closure) = \ > + { = \ > + field_type native_value; = \ > + if (!field_conv (value, &native_value)) = \ > + return -1; = \ > + float_format_object *ff =3D (float_format_object*) self; = \ > + ff->float_format ()->field_name =3D native_value; = \ > + return 0; = \ > + } > + > +/* Converts from the intbit enum to a Python boolean. */ > + > +static PyObject * > +intbit_to_py (enum floatformat_intbit intbit) > +{ > + gdb_assert (intbit =3D=3D floatformat_intbit_yes || intbit =3D=3D floa= tformat_intbit_no); > + if (intbit =3D=3D floatformat_intbit_no) > + Py_RETURN_FALSE; > + else > + Py_RETURN_TRUE; > +} > + > +/* Converts from a Python boolean to the intbit enum. */ > + > +static bool > +py_to_intbit (PyObject *object, enum floatformat_intbit *intbit) > +{ > + if (!PyObject_IsInstance (object, (PyObject*) &PyBool_Type)) > + { > + PyErr_SetString (PyExc_TypeError, "intbit must be True or False"); > + return false; > + } > + > + *intbit =3D PyObject_IsTrue (object) ? floatformat_intbit_yes : floatf= ormat_intbit_no; > + return true; > +} > + > +/* Converts from a Python integer to a unsigned integer. */ > + > +static bool > +py_to_unsigned_int (PyObject *object, unsigned int *val) > +{ > + if (!PyObject_IsInstance (object, (PyObject*) &PyLong_Type)) > + { > + PyErr_SetString (PyExc_TypeError, "value must be an integer"); > + return false; > + } > + > + long native_val =3D PyLong_AsLong (object); > + if (native_val > (long) UINT_MAX) > + { > + PyErr_SetString (PyExc_ValueError, "value is too large"); > + return false; > + } > + if (native_val < 0) > + { > + PyErr_SetString (PyExc_ValueError, "value must not be smaller than z= ero"); > + return false; > + } > + > + *val =3D (unsigned int) native_val; > + return true; > +} > + > +/* Converts from a Python integer to a signed integer. */ > + > +static bool > +py_to_int(PyObject *object, int *val) > +{ > + if(!PyObject_IsInstance(object, (PyObject*)&PyLong_Type)) > + { > + PyErr_SetString(PyExc_TypeError, u8"value must be an integer"); > + return false; > + } > + > + long native_val =3D PyLong_AsLong(object); > + if(native_val > (long)INT_MAX) > + { > + PyErr_SetString(PyExc_ValueError, u8"value is too large"); > + return false; > + } > + > + *val =3D (int)native_val; > + return true; > +} > + > +INSTANCE_FIELD_GETTER (ffpy_get_totalsize, totalsize, unsigned int, PyLo= ng_FromLong) > +INSTANCE_FIELD_GETTER (ffpy_get_sign_start, sign_start, unsigned int, Py= Long_FromLong) > +INSTANCE_FIELD_GETTER (ffpy_get_exp_start, exp_start, unsigned int, PyLo= ng_FromLong) > +INSTANCE_FIELD_GETTER (ffpy_get_exp_len, exp_len, unsigned int, PyLong_F= romLong) > +INSTANCE_FIELD_GETTER (ffpy_get_exp_bias, exp_bias, int, PyLong_FromLong= ) > +INSTANCE_FIELD_GETTER (ffpy_get_exp_nan, exp_nan, unsigned int, PyLong_F= romLong) > +INSTANCE_FIELD_GETTER (ffpy_get_man_start, man_start, unsigned int, PyLo= ng_FromLong) > +INSTANCE_FIELD_GETTER (ffpy_get_man_len, man_len, unsigned int, PyLong_F= romLong) > +INSTANCE_FIELD_GETTER (ffpy_get_intbit, intbit, enum floatformat_intbit,= intbit_to_py) > +INSTANCE_FIELD_GETTER (ffpy_get_name, name, const char *, PyUnicode_From= String) > + > +INSTANCE_FIELD_SETTER (ffpy_set_totalsize, totalsize, unsigned int, py_t= o_unsigned_int) > +INSTANCE_FIELD_SETTER (ffpy_set_sign_start, sign_start, unsigned int, py= _to_unsigned_int) > +INSTANCE_FIELD_SETTER (ffpy_set_exp_start, exp_start, unsigned int, py_t= o_unsigned_int) > +INSTANCE_FIELD_SETTER (ffpy_set_exp_len, exp_len, unsigned int, py_to_un= signed_int) > +INSTANCE_FIELD_SETTER (ffpy_set_exp_bias, exp_bias, int, py_to_int) > +INSTANCE_FIELD_SETTER (ffpy_set_exp_nan, exp_nan, unsigned int, py_to_un= signed_int) > +INSTANCE_FIELD_SETTER (ffpy_set_man_start, man_start, unsigned int, py_t= o_unsigned_int) > +INSTANCE_FIELD_SETTER (ffpy_set_man_len, man_len, unsigned int, py_to_un= signed_int) > +INSTANCE_FIELD_SETTER (ffpy_set_intbit, intbit, enum floatformat_intbit,= py_to_intbit) > + > +/* Makes sure float formats created from Python always test as valid. */ > + > +static int > +ffpy_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED, > + const void *from ATTRIBUTE_UNUSED) > +{ > + return 1; > +} > + > +/* Initializes new float format objects. */ > + > +static int > +ffpy_init (PyObject *self, > + PyObject *args ATTRIBUTE_UNUSED, > + PyObject *kwds ATTRIBUTE_UNUSED) > +{ > + auto ff =3D (float_format_object*) self; > + ff->format =3D floatformat (); > + ff->float_format ()->name =3D ""; > + ff->float_format ()->is_valid =3D ffpy_always_valid; > + return 0; > +} > + > +/* Retrieves a pointer to the underlying float format structure. */ > + > +struct floatformat * > +float_format_object_as_float_format (PyObject *self) > +{ > + if (!PyObject_IsInstance (self, (PyObject*) &float_format_object_type)= ) > + return nullptr; > + return ((float_format_object*) self)->float_format (); > +} > + > +static gdb_PyGetSetDef float_format_object_getset[] =3D > +{ > + { "totalsize", ffpy_get_totalsize, ffpy_set_totalsize, > + "The total size of the floating point number, in bits.", nullptr }, > + { "sign_start", ffpy_get_sign_start, ffpy_set_sign_start, > + "The bit offset of the sign bit.", nullptr }, > + { "exp_start", ffpy_get_exp_start, ffpy_set_exp_start, > + "The bit offset of the start of the exponent.", nullptr }, > + { "exp_len", ffpy_get_exp_len, ffpy_set_exp_len, > + "The size of the exponent, in bits.", nullptr }, > + { "exp_bias", ffpy_get_exp_bias, ffpy_set_exp_bias, > + "Bias added to a \"true\" exponent to form the biased exponent.", nu= llptr }, > + { "exp_nan", ffpy_get_exp_nan, ffpy_set_exp_nan, > + "Exponent value which indicates NaN.", nullptr }, > + { "man_start", ffpy_get_man_start, ffpy_set_man_start, > + "The bit offset of the start of the mantissa.", nullptr }, > + { "man_len", ffpy_get_man_len, ffpy_set_man_len, > + "The size of the mantissa, in bits.", nullptr }, > + { "intbit", ffpy_get_intbit, ffpy_set_intbit, > + "Is the integer bit explicit or implicit?", nullptr }, > + { "name", ffpy_get_name, nullptr, > + "Internal name for debugging.", nullptr }, > + { nullptr } > +}; > + > +static PyMethodDef float_format_object_methods[] =3D > +{ > + { NULL } > +}; > + > +static PyNumberMethods float_format_object_as_number =3D { > + nullptr, /* nb_add */ > + nullptr, /* nb_subtract */ > + nullptr, /* nb_multiply */ > + nullptr, /* nb_remainder */ > + nullptr, /* nb_divmod */ > + nullptr, /* nb_power */ > + nullptr, /* nb_negative */ > + nullptr, /* nb_positive */ > + nullptr, /* nb_absolute */ > + nullptr, /* nb_nonzero */ > + nullptr, /* nb_invert */ > + nullptr, /* nb_lshift */ > + nullptr, /* nb_rshift */ > + nullptr, /* nb_and */ > + nullptr, /* nb_xor */ > + nullptr, /* nb_or */ > + nullptr, /* nb_int */ > + nullptr, /* reserved */ > + nullptr, /* nb_float */ > +}; > + > +PyTypeObject float_format_object_type =3D > +{ > + PyVarObject_HEAD_INIT (NULL, 0) > + "gdb.FloatFormat", /*tp_name*/ > + sizeof (float_format_object), /*tp_basicsize*/ > + 0, /*tp_itemsize*/ > + nullptr, /*tp_dealloc*/ > + 0, /*tp_print*/ > + nullptr, /*tp_getattr*/ > + nullptr, /*tp_setattr*/ > + nullptr, /*tp_compare*/ > + nullptr, /*tp_repr*/ > + &float_format_object_as_number, /*tp_as_number*/ > + nullptr, /*tp_as_sequence*/ > + nullptr, /*tp_as_mapping*/ > + nullptr, /*tp_hash */ > + nullptr, /*tp_call*/ > + nullptr, /*tp_str*/ > + nullptr, /*tp_getattro*/ > + nullptr, /*tp_setattro*/ > + nullptr, /*tp_as_buffer*/ > + Py_TPFLAGS_DEFAULT, /*tp_flags*/ > + "GDB float format object", /* tp_doc */ > + nullptr, /* tp_traverse */ > + nullptr, /* tp_clear */ > + nullptr, /* tp_richcompare */ > + 0, /* tp_weaklistoffset */ > + nullptr, /* tp_iter */ > + nullptr, /* tp_iternext */ > + float_format_object_methods, /* tp_methods */ > + nullptr, /* tp_members */ > + float_format_object_getset, /* tp_getset */ > + nullptr, /* tp_base */ > + nullptr, /* tp_dict */ > + nullptr, /* tp_descr_get */ > + nullptr, /* tp_descr_set */ > + 0, /* tp_dictoffset */ > + ffpy_init, /* tp_init */ > + nullptr, /* tp_alloc */ > + PyType_GenericNew, /* tp_new */ > +}; > + > + > diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c > index c278925531b..28a7c9a7873 100644 > --- a/gdb/python/py-objfile.c > +++ b/gdb/python/py-objfile.c > @@ -704,6 +704,18 @@ objfile_to_objfile_object (struct objfile *objfile) > return gdbpy_ref<>::new_reference (result); > } > > +struct objfile * > +objfile_object_to_objfile (PyObject *self) > +{ > + if (!PyObject_TypeCheck (self, &objfile_object_type)) > + return nullptr; > + > + auto objfile_object =3D (struct objfile_object*) self; > + OBJFPY_REQUIRE_VALID (objfile_object); > + > + return objfile_object->objfile; > +} > + > int > gdbpy_initialize_objfile (void) > { > diff --git a/gdb/python/py-type-init.c b/gdb/python/py-type-init.c > new file mode 100644 > index 00000000000..f3b6813c3ad > --- /dev/null > +++ b/gdb/python/py-type-init.c > @@ -0,0 +1,388 @@ > +/* Functionality for creating new types accessible from python. > + > + Copyright (C) 2008-2023 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 .= */ > + > +#include "defs.h" > +#include "python-internal.h" > +#include "gdbtypes.h" > +#include "floatformat.h" > +#include "objfiles.h" > +#include "gdbsupport/gdb_obstack.h" > + > + > +/* Copies a null-terminated string into an objfile's obstack. */ > + > +static const char * > +copy_string (struct objfile *objfile, const char *py_str) > +{ > + unsigned int len =3D strlen (py_str); > + return obstack_strndup (&objfile->per_bfd->storage_obstack, > + py_str, len); > +} > + > +/* Creates a new type and returns a new gdb.Type associated with it. */ > + > +PyObject * > +gdbpy_init_type (PyObject *self, PyObject *args) > +{ > + PyObject *objfile_object; > + enum type_code code; > + int bit_length; > + const char *py_name; > + > + if(!PyArg_ParseTuple (args, "Oiis", &objfile_object, &code, &bit_lengt= h, &py_name)) > + return nullptr; > + > + struct objfile* objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_type (objfile, code, bit_length, name); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > + > +/* Creates a new integer type and returns a new gdb.Type associated with= it. */ > + > +PyObject * > +gdbpy_init_integer_type (PyObject *self, PyObject *args) > +{ > + PyObject *objfile_object; > + int bit_size; > + int unsigned_p; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsi= gned_p, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_integer_type (objfile, bit_size, unsigned_p, name); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object(type); > +} > + > +/* Creates a new character type and returns a new gdb.Type associated wi= th it. */ > + > +PyObject * > +gdbpy_init_character_type (PyObject *self, PyObject *args) > +{ > + > + PyObject *objfile_object; > + int bit_size; > + int unsigned_p; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsi= gned_p, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_character_type (objfile, bit_size, unsigned_p, name); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > + > +/* Creates a new boolean type and returns a new gdb.Type associated with= it. */ > + > +PyObject * > +gdbpy_init_boolean_type (PyObject *self, PyObject *args) > +{ > + > + PyObject *objfile_object; > + int bit_size; > + int unsigned_p; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_size, &unsi= gned_p, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_boolean_type (objfile, bit_size, unsigned_p, name); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > + > +/* Creates a new float type and returns a new gdb.Type associated with i= t. */ > + > +PyObject * > +gdbpy_init_float_type (PyObject *self, PyObject *args) > +{ > + PyObject *objfile_object, *float_format_object; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "OOs", &objfile_object, &float_format_obj= ect, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + struct floatformat *local_ff =3D float_format_object_as_float_format (= float_format_object); > + if (local_ff =3D=3D nullptr) > + return nullptr; > + > + /* Persist a copy of the format in the objfile's obstack. This guarant= ees that > + * the format won't outlive the type being created from it and that ch= anges > + * made to the object used to create this type will not affect it afte= r > + * creation. */ > + auto ff =3D OBSTACK_CALLOC > + (&objfile->objfile_obstack, > + 1, > + struct floatformat); > + memcpy (ff, local_ff, sizeof (struct floatformat)); > + > + /* We only support creating float types in the architecture's endianne= ss, so > + * make sure init_float_type sees the float format structure we need i= t to. */ > + enum bfd_endian endianness =3D gdbarch_byte_order (objfile->arch()); > + gdb_assert (endianness < BFD_ENDIAN_UNKNOWN); > + > + const struct floatformat *per_endian[2] =3D { nullptr, nullptr }; > + per_endian[endianness] =3D ff; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_float_type (objfile, -1, name, per_endian, endianness)= ; > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > + > +/* Creates a new decimal float type and returns a new gdb.Type associate= d with it. */ > + > +PyObject * > +gdbpy_init_decfloat_type (PyObject *self, PyObject *args) > +{ > + PyObject *objfile_object; > + int bit_length; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "Ois", &objfile_object, &bit_length, &py_= name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_decfloat_type (objfile, bit_length, name); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > + > +/* Returns whether a given type can be used to create a complex type. */ > + > +PyObject * > +gdbpy_can_create_complex_type (PyObject *self, PyObject *args) > +{ > + > + PyObject *type_object; > + > + if (!PyArg_ParseTuple (args, "O", &type_object)) > + return nullptr; > + > + struct type *type =3D type_object_to_type (type_object); > + if (type =3D=3D nullptr) > + return nullptr; > + > + bool can_create_complex; > + try > + { > + can_create_complex =3D can_create_complex_type (type); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + if (can_create_complex) > + Py_RETURN_TRUE; > + else > + Py_RETURN_FALSE; > +} > + > +/* Creates a new complex type and returns a new gdb.Type associated with= it. */ > + > +PyObject * > +gdbpy_init_complex_type (PyObject *self, PyObject *args) > +{ > + > + PyObject *type_object; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "Os", &type_object, &py_name)) > + return nullptr; > + > + struct type *type =3D type_object_to_type (type_object); > + if (type =3D=3D nullptr) > + return nullptr; > + > + obstack *obstack; > + if (type->is_objfile_owned ()) > + obstack =3D &type->objfile_owner ()->objfile_obstack; > + else > + obstack =3D gdbarch_obstack (type->arch_owner ()); > + > + unsigned int len =3D strlen (py_name); > + const char *name =3D obstack_strndup (obstack, > + py_name, > + len); > + struct type *complex_type; > + try > + { > + complex_type =3D init_complex_type (name, type); > + gdb_assert (complex_type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (complex_type); > +} > + > +/* Creates a new pointer type and returns a new gdb.Type associated with= it. */ > + > +PyObject * > +gdbpy_init_pointer_type (PyObject *self, PyObject *args) > +{ > + PyObject *objfile_object, *type_object; > + int bit_length; > + const char *py_name; > + > + if (!PyArg_ParseTuple (args, "OOis", &objfile_object, &type_object, &b= it_length, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + struct type *type =3D type_object_to_type (type_object); > + if (type =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *pointer_type; > + try > + { > + pointer_type =3D init_pointer_type (objfile, bit_length, name, type)= ; > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (pointer_type); > +} > + > +/* Creates a new fixed point type and returns a new gdb.Type associated = with it. */ > + > +PyObject * > +gdbpy_init_fixed_point_type (PyObject *self, PyObject *args) > +{ > + > + PyObject *objfile_object; > + int bit_length; > + int unsigned_p; > + const char* py_name; > + > + if (!PyArg_ParseTuple (args, "Oips", &objfile_object, &bit_length, &un= signed_p, &py_name)) > + return nullptr; > + > + struct objfile *objfile =3D objfile_object_to_objfile (objfile_object)= ; > + if (objfile =3D=3D nullptr) > + return nullptr; > + > + const char *name =3D copy_string (objfile, py_name); > + struct type *type; > + try > + { > + type =3D init_fixed_point_type (objfile, bit_length, unsigned_p, nam= e); > + gdb_assert (type !=3D nullptr); > + } > + catch (gdb_exception_error& ex) > + { > + GDB_PY_HANDLE_EXCEPTION (ex); > + } > + > + return type_to_type_object (type); > +} > diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h > index 06357cc8c0b..3877f8a7ca9 100644 > --- a/gdb/python/python-internal.h > +++ b/gdb/python/python-internal.h > @@ -289,6 +289,8 @@ extern PyTypeObject frame_object_type > CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("frame_object"); > extern PyTypeObject thread_object_type > CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object"); > +extern PyTypeObject float_format_object_type > + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("float_format"); > > /* Ensure that breakpoint_object_type is initialized and return true. I= f > breakpoint_object_type can't be initialized then set a suitable Pytho= n > @@ -431,6 +433,17 @@ gdb::unique_xmalloc_ptr gdbpy_parse_command_na= me > PyObject *gdbpy_register_tui_window (PyObject *self, PyObject *args, > PyObject *kw); > > +PyObject *gdbpy_init_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_integer_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_character_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_boolean_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_float_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_decfloat_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_can_create_complex_type (PyObject *self, PyObject *args)= ; > +PyObject *gdbpy_init_complex_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_pointer_type (PyObject *self, PyObject *args); > +PyObject *gdbpy_init_fixed_point_type (PyObject *self, PyObject *args); > + > PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); > PyObject *symtab_to_symtab_object (struct symtab *symtab); > PyObject *symbol_to_symbol_object (struct symbol *sym); > @@ -481,6 +494,8 @@ struct symtab *symtab_object_to_symtab (PyObject *obj= ); > struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); > frame_info_ptr frame_object_to_frame_info (PyObject *frame_obj); > struct gdbarch *arch_object_to_gdbarch (PyObject *obj); > +struct objfile *objfile_object_to_objfile (PyObject *self); > +struct floatformat *float_format_object_as_float_format (PyObject *self)= ; > > /* Convert Python object OBJ to a program_space pointer. OBJ must be a > gdb.Progspace reference. Return nullptr if the gdb.Progspace is not > @@ -559,6 +574,8 @@ int gdbpy_initialize_micommands (void) > void gdbpy_finalize_micommands (); > int gdbpy_initialize_disasm () > CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; > +int gdbpy_initialize_float_format () > + CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; > > PyMODINIT_FUNC gdbpy_events_mod_func (); > > diff --git a/gdb/python/python.c b/gdb/python/python.c > index 4aa24421dec..1ed29ff4dea 100644 > --- a/gdb/python/python.c > +++ b/gdb/python/python.c > @@ -2153,7 +2153,8 @@ do_start_initialization () > || gdbpy_initialize_membuf () < 0 > || gdbpy_initialize_connection () < 0 > || gdbpy_initialize_tui () < 0 > - || gdbpy_initialize_micommands () < 0) > + || gdbpy_initialize_micommands () < 0 > + || gdbpy_initialize_float_format() < 0) > return false; > > #define GDB_PY_DEFINE_EVENT_TYPE(name, py_name, doc, base) \ > @@ -2529,6 +2530,47 @@ Return current recording object." }, > "stop_recording () -> None.\n\ > Stop current recording." }, > > + /* Type initialization functions. */ > + { "init_type", gdbpy_init_type, METH_VARARGS, > + "init_type (objfile, type_code, bit_length, name) -> type\n\ > + Creates a new type with the given bit length and type code, owned\ > + by the given objfile." }, > + { "init_integer_type", gdbpy_init_integer_type, METH_VARARGS, > + "init_integer_type (objfile, bit_length, unsigned, name) -> type\n\ > + Creates a new integer type with the given bit length and \ > + signedness, owned by the given objfile." }, > + { "init_character_type", gdbpy_init_character_type, METH_VARARGS, > + "init_character_type (objfile, bit_length, unsigned, name) -> type\n= \ > + Creates a new character type with the given bit length and \ > + signedness, owned by the given objfile." }, > + { "init_boolean_type", gdbpy_init_boolean_type, METH_VARARGS, > + "init_boolean_type (objfile, bit_length, unsigned, name) -> type\n\ > + Creates a new boolean type with the given bit length and \ > + signedness, owned by the given objfile." }, > + { "init_float_type", gdbpy_init_float_type, METH_VARARGS, > + "init_float_type (objfile, float_format, name) -> type\n\ > + Creates a new floating point type with the given bit length and \ > + format, owned by the given objfile." }, > + { "init_decfloat_type", gdbpy_init_decfloat_type, METH_VARARGS, > + "init_decfloat_type (objfile, bit_length, name) -> type\n\ > + Creates a new decimal float type with the given bit length,\ > + owned by the given objfile." }, > + { "can_create_complex_type", gdbpy_can_create_complex_type, METH_VARAR= GS, > + "can_create_complex_type (type) -> bool\n\ > + Returns whether a given type can form a new complex type." }, > + { "init_complex_type", gdbpy_init_complex_type, METH_VARARGS, > + "init_complex_type (base_type, name) -> type\n\ > + Creates a new complex type whose components belong to the\ > + given type, owned by the given objfile." }, > + { "init_pointer_type", gdbpy_init_pointer_type, METH_VARARGS, > + "init_pointer_type (objfile, target_type, bit_length, name) -> type\= n\ > + Creates a new pointer type with the given bit length, pointing\ > + to the given target type, and owned by the given objfile." }, > + { "init_fixed_point_type", gdbpy_init_fixed_point_type, METH_VARARGS, > + "init_fixed_point_type (objfile, bit_length, unsigned, name) -> type\= n\ > + Creates a new fixed point type with the given bit length and\ > + signedness, owned by the given objfile." }, > + > { "lookup_type", (PyCFunction) gdbpy_lookup_type, > METH_VARARGS | METH_KEYWORDS, > "lookup_type (name [, block]) -> type\n\ > -- > 2.37.3.windows.1 >