From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ot1-x32a.google.com (mail-ot1-x32a.google.com [IPv6:2607:f8b0:4864:20::32a]) by sourceware.org (Postfix) with ESMTPS id 74B2B3858D28 for ; Thu, 5 Jan 2023 23:56:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 74B2B3858D28 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-ot1-x32a.google.com with SMTP id p17-20020a9d6951000000b00678306ceb94so120919oto.5 for ; Thu, 05 Jan 2023 15:56:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=thread-index:content-language:mime-version:message-id:date:subject :to:from:from:to:cc:subject:date:message-id:reply-to; bh=r9ox9BBB+1YFZD9cM5OWS4PQ8lonlkirO7f5j+Dx2YE=; b=YThh9NYSdREqkVGazpDneMpnp/PpiS9E2QPV4D9hqMLAkq4CQ9OVqeDlA0ZOwu1Nef UyHYtQeOoQf4rxhtkQZgdPJiNF2Rfau0pX9xGW8UJD0itoXXyx0oRy5zf9/VfcVLDCSk MvhJOZtmqPnjG3tFAz+34UriQ7GImCnr3285iTMlFpdTgKGXDJl9Znktxq6zx/SWYVCB qpQNmezzXxaQs+nkF0+w49ERz5ouBvCi9DvQc6If9KSzRNQ7X4V791DtkQX1yzujkkCP SWtJrVtMGX6X9MeMUFggc2CYZa0DHqdeRgy4+QOpAtAlMZiL7CbmTnmUw6j6wpyXJ1cY 0cPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=thread-index:content-language:mime-version:message-id:date:subject :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=r9ox9BBB+1YFZD9cM5OWS4PQ8lonlkirO7f5j+Dx2YE=; b=MkRjTHdcURTPb+d/tPKu2MQEFOnDiT/bJJTcZecX37RY+X8+7QGadaRNSIuAvCkpUE WK9XucE2PDRdvzu/G2oF8gAYvRVzQuB5WT36Z4/otcaueQO/7TNNqSyCVG6CRDmxHktL eyrtkDFpaf7kwkDy2sO3hugZxEe4LRwpEWFAsVpDi9MTgiiVvJ2G5B8RtQxCvDxcwy75 V6t07Od4gccOf+AzuqbHdPxEeWMf5a10oXlHGg4cDqy8oJaVCS9kzfHT4LdtbiUfgakA zweMhBXIZsayXvb/Lx/ZeNmMlxHF4houCpO3Z8FWuFeBc4SBEKnLagtrtmOYiMwGbzfc Zo1A== X-Gm-Message-State: AFqh2kqtLfDSewLNDc02IZJIgXcQ285NAmT9ONUhw8d87K4ga6QM2WMh wrYZMD/FkPTLuN3F2zJyGY/xy+OD7Gu7JQ== X-Google-Smtp-Source: AMrXdXts9qkZGsEE4w14RmbWBXhZGZf6CmbQyg31RKmsEyAJAb8gnVWJbmYzQeBE3FvuViNuJl5jng== X-Received: by 2002:a05:6830:1558:b0:670:6fee:c847 with SMTP id l24-20020a056830155800b006706feec847mr25836936otp.34.1672962998964; Thu, 05 Jan 2023 15:56:38 -0800 (PST) Received: from Diamond ([177.200.77.147]) by smtp.gmail.com with ESMTPSA id m1-20020a05683026c100b0067c87f23476sm17973013otu.57.2023.01.05.15.56.37 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Jan 2023 15:56:38 -0800 (PST) From: To: Subject: [PATCH 1/1] Add support for gdb.Type initialization from within the Python API Date: Thu, 5 Jan 2023 20:56:14 -0300 Message-ID: <5c5201d92161$5908e600$0b1ab200$@gmail.com> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_5C53_01D92148.33C4FCD0" X-Mailer: Microsoft Outlook 16.0 Content-Language: en-us Thread-Index: AdkhYUhud3OAvq9ySQCaGYKTwrXg2g== X-Spam-Status: No, score=-8.9 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,HTML_MESSAGE,KAM_SHORT,RCVD_IN_BARRACUDACENTRAL,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP 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: This is a multipart message in MIME format. ------=_NextPart_000_5C53_01D92148.33C4FCD0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 `gdbtypes.h` to Python and having them return `gdb.Type` objects connected to the newly minted types. These functions are accessible in the root of the gdb module and all require a reference to a `gdb.Objfile`. Types created from this API are exclusively objfile-owned. This patch also adds an extra type - `gdb.FloatFormat` - to support creation of floating point types by letting users control the format from within Python. It is missing, however, a way to specify half formats and validation functions. It is important to note that types created using this interface are not automatically registered as a symbol, and so, types will become unreachable unless used to create a value that otherwise references it or saved in some way. The main drawback of using the `init_*_type` family over implementing type 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 that 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 ambitious for a first patch, I'd say. if it were to be done though, we would gain the ability to only keep in the obstack types that are known to be referenced in some other way - by allocating and copying the data to the obstack as other objects are created that reference it (eg. symbols). --- 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 = \ 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..a1da4dcd3f0 --- /dev/null +++ b/gdb/python/py-float-format.c @@ -0,0 +1,278 @@ +/* Accessibility of float format controls from inside the Python API + + Copyright (C) 2008-2022 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" + +struct float_format_object +{ + PyObject_HEAD + struct floatformat format; + + struct floatformat *float_format() + { + return &this->format; + } +}; + +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 = (float_format_object*) self; \ + field_type value = 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 = (float_format_object*) self; \ + ff->float_format()->field_name = native_value; \ + return 0; \ + } + +static PyObject * +intbit_to_py(enum floatformat_intbit intbit) +{ + gdb_assert(intbit == floatformat_intbit_yes || intbit == floatformat_intbit_no); + if (intbit == floatformat_intbit_no) + Py_RETURN_FALSE; + else + Py_RETURN_TRUE; +} + +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 = PyObject_IsTrue(object) ? floatformat_intbit_yes : floatformat_intbit_no; + return true; +} + +static bool +py_to_unsigned_int(PyObject *object, unsigned int *val) +{ + if (!PyObject_IsInstance(object, (PyObject*)&PyLong_Type)) + { + PyErr_SetString(PyExc_TypeError, u8"value must be an integer"); + return false; + } + + long native_val = PyLong_AsLong(object); + if (native_val > (long)UINT_MAX) + { + PyErr_SetString(PyExc_ValueError, u8"value is too large"); + return false; + } + if (native_val < 0) + { + PyErr_SetString(PyExc_ValueError, u8"value must not be smaller than zero"); + return false; + } + + *val = (unsigned int)native_val; + return true; +} + +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 = PyLong_AsLong(object); + if (native_val > (long)INT_MAX) + { + PyErr_SetString(PyExc_ValueError, u8"value is too large"); + return false; + } + + *val = (int)native_val; + return true; +} + +INSTANCE_FIELD_GETTER(ffpy_get_totalsize, totalsize, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_sign_start, sign_start, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_exp_start, exp_start, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_exp_len, exp_len, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_exp_bias, exp_bias, int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_exp_nan, exp_nan, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_man_start, man_start, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_man_len, man_len, unsigned int, PyLong_FromLong) +INSTANCE_FIELD_GETTER(ffpy_get_intbit, intbit, enum floatformat_intbit, intbit_to_py) +INSTANCE_FIELD_GETTER(ffpy_get_name, name, const char *, PyUnicode_FromString) + +INSTANCE_FIELD_SETTER(ffpy_set_totalsize, totalsize, unsigned int, py_to_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_to_unsigned_int) +INSTANCE_FIELD_SETTER(ffpy_set_exp_len, exp_len, unsigned int, py_to_unsigned_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_unsigned_int) +INSTANCE_FIELD_SETTER(ffpy_set_man_start, man_start, unsigned int, py_to_unsigned_int) +INSTANCE_FIELD_SETTER(ffpy_set_man_len, man_len, unsigned int, py_to_unsigned_int) +INSTANCE_FIELD_SETTER(ffpy_set_intbit, intbit, enum floatformat_intbit, py_to_intbit) + +static int +ffpy_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED, + const void *from ATTRIBUTE_UNUSED) +{ + return 1; +} + + +static int +ffpy_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + float_format_object *ff = (float_format_object*) self; + ff->format = floatformat{}; + ff->float_format()->name = u8""; + ff->float_format()->is_valid = ffpy_always_valid; + return 0; +} + +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[] = +{ + { "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.", nullptr }, + { "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[] = +{ + { NULL } +}; + +static PyNumberMethods float_format_object_as_number = { + 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 = +{ + 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..9b884d4c414 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -704,6 +928,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 = (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..127f6eaa538 --- /dev/null +++ b/gdb/python/py-type-init.c @@ -0,0 +1,370 @@ +/* Functionality for creating new types accessible from python. + + Copyright (C) 2008-2022 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" + + +static const char * +copy_string(struct objfile *objfile, const char *py_str) +{ + unsigned int len = strlen(py_str); + return obstack_strndup (&objfile->per_bfd->storage_obstack, + py_str, + len); +} + +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_length, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_type(objfile, code, bit_length, name); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(type); +} + +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, &unsigned_p, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_integer_type(objfile, bit_size, unsigned_p, name); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(type); +} + +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, &unsigned_p, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_character_type(objfile, bit_size, unsigned_p, name); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(type); +} + +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, &unsigned_p, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_boolean_type(objfile, bit_size, unsigned_p, name); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(type); +} + +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_object, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + struct floatformat* local_ff = float_format_object_as_float_format(float_format_object); + if (local_ff == nullptr) + return nullptr; + + /* Persist a copy of the format in the objfile's obstack. This guarantees that + * the format won't outlive the type being created from it and that changes + * made to the object used to create this type will not affect it after + * creation. */ + auto* ff = 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 endianness, so + * make sure init_float_type sees the float format structure we need it to. */ + enum bfd_endian endianness = gdbarch_byte_order(objfile->arch()); + gdb_assert(endianness < 2); + + const struct floatformat* per_endian[2] = { nullptr, nullptr }; + per_endian[endianness] = ff; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_float_type(objfile, -1, name, per_endian, endianness); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(type); +} + +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 = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_decfloat_type(objfile, bit_length, name); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(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 = type_object_to_type(type_object); + if (type == nullptr) + return nullptr; + + bool can_create_complex; + try + { + can_create_complex = 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; +} + +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 = type_object_to_type(type_object); + if (type == nullptr) + return nullptr; + + obstack *obstack; + if (type->is_objfile_owned ()) + obstack = &type->objfile_owner()->objfile_obstack; + else + obstack = gdbarch_obstack(type->arch_owner()); + + unsigned int len = strlen (py_name); + const char *name = obstack_strndup (obstack, + py_name, + len); + struct type *complex_type; + try + { + complex_type = init_complex_type(name, type); + gdb_assert (complex_type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(complex_type); +} + +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, &bit_length, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + struct type* type = type_object_to_type(type_object); + if (type == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *pointer_type; + try + { + pointer_type = init_pointer_type(objfile, bit_length, name, type); + gdb_assert (type != nullptr); + } + catch(gdb_exception_error& ex) + { + GDB_PY_HANDLE_EXCEPTION (ex); + } + + return type_to_type_object(pointer_type); +} + +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, &unsigned_p, &py_name)) + return nullptr; + + struct objfile* objfile = objfile_object_to_objfile(objfile_object); + if (objfile == nullptr) + return nullptr; + + const char *name = copy_string(objfile, py_name); + struct type *type; + try + { + type = init_fixed_point_type(objfile, bit_length, unsigned_p, name); + gdb_assert (type != 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. If breakpoint_object_type can't be initialized then set a suitable Python @@ -431,6 +433,17 @@ gdb::unique_xmalloc_ptr gdbpy_parse_command_name 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..d852fa448df 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,28 @@ 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_VARARGS, + "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\ ------=_NextPart_000_5C53_01D92148.33C4FCD0--