public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/1] Add support for gdb.Type initialization from within the Python API
@ 2023-01-05 23:56 dark.ryu.550
  2023-01-06 20:00 ` Simon Marchi
  0 siblings, 1 reply; 10+ messages in thread
From: dark.ryu.550 @ 2023-01-05 23:56 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 30500 bytes --]

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 <http://www.gnu.org/licenses/>.
*/

+

+#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 <http://www.gnu.org/licenses/>.
*/

+

+#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<char> 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\

 


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-01-16  4:58 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-05 23:56 [PATCH 1/1] Add support for gdb.Type initialization from within the Python API dark.ryu.550
2023-01-06 20:00 ` Simon Marchi
2023-01-11  0:58   ` [PATCH] Add support for creating new types from " Matheus Branco Borella
2023-06-27  3:52     ` [PING] " Matheus Branco Borella
2023-05-26  3:30   ` Matheus Branco Borella
2023-08-07 14:53     ` Andrew Burgess
2023-08-08 21:00       ` [PATCH v2] " Matheus Branco Borella
2024-01-13  1:37         ` [PATCH v3] " Matheus Branco Borella
2024-01-13  7:21           ` Eli Zaretskii
2024-01-16  4:55             ` Matheus Branco Borella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).