public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom Tromey <tom@tromey.com>
To: Matheus Branco Borella <dark.ryu.550@gmail.com>
Cc: gdb-patches@sourceware.org,  eli@gnu.org
Subject: Re: [PATCH v4] Add support for creating new types from the Python API
Date: Tue, 06 Feb 2024 11:20:23 -0700	[thread overview]
Message-ID: <871q9pe9p4.fsf@tromey.com> (raw)
In-Reply-To: <20240116045439.171157-1-dark.ryu.550@gmail.com> (Matheus Branco Borella's message of "Tue, 16 Jan 2024 01:54:40 -0300")

>>>>> "Matheus" == Matheus Branco Borella <dark.ryu.550@gmail.com> writes:

Matheus> The main drawback of using the `init_*_type` family over implementing type
Matheus> initialization by hand is that any type that's created gets immediately
Matheus> allocated on its owner's obstack, regardless of what its real lifetime
Matheus> requirements are. The main implication of this is that types that become
Matheus> unreachable will remain live for the lifetime of the owner.

Yeah.  gdb leaks a lot of types this way, actually.  We've collectively
put off implementing "type GC", though I do think there's a bug for it.

Matheus> +  ** Functions that allow creation of instances of gdb.Type, and a new
Matheus> +     class gdb.FloatFormat that may be used to create floating point
Matheus> +     types.  The functions that allow new type creation are:
Matheus> +      - gdb.init_type: Create a new type given a type code.
Matheus> +      - gdb.init_integer_type: Create a new integer type.
Matheus> +      - gdb.init_character_type: Create a new character type.
Matheus> +      - gdb.init_boolean_type: Create a new boolean type.
Matheus> +      - gdb.init_float_type: Create a new floating point type.
Matheus> +      - gdb.init_decfloat_type: Create a new decimal floating point type.
Matheus> +      - gdb.can_create_complex_type: Whether a type can be used to create a
Matheus> +          new complex type.
Matheus> +      - gdb.init_complex_type: Create a new complex type.
Matheus> +      - gdb.init_pointer_type: Create a new pointer type.
Matheus> +          * This allows creating pointers of arbitrary size.
Matheus> +      - gdb.init_fixed_point_type: Create a new fixed point type.

I don't really love the "init_" prefixes here.  Like, I get that these
are the names internally, but I don't think they really make sense
externally.

WDYT about "make_" instead?

Matheus> +@findex gdb.init_type
Matheus> +@defun gdb.init_type (owner, type_code, bit_size, name)
Matheus> +This function creates a new @code{gdb.Type} instance corresponding to a
Matheus> +type owned by the given @var{owner}, with the given @var{type_code},
Matheus> +@var{name} and size.
Matheus> +
Matheus> +@var{owner} must be a reference to either a @code{gdb.Objfile} or a
Matheus> +@code{gdb.Architecture} object.  These correspond to objfile and
Matheus> +architecture-owned types, respectively.
Matheus> +
Matheus> +@var{type_code} is one of the @code{TYPE_CODE_} constants defined in
Matheus> +@ref{Types In Python}.
Matheus> +
Matheus> +@var{bit_size} is the size of instances of the newly created type, in
Matheus> +bits. Currently, accepted values are limited to multiples of 8.
Matheus> +@end defun

Making any sort of type without filling in the details is probably a
recipe for crashes.

Is there a specific situation you needed this for?

Matheus> +@findex gdb.init_pointer_type
Matheus> +@defun gdb.init_pointer_type (owner, target, bit_size, name)
Matheus> +This function creates a new @code{gdb.Type} instance corresponding to a
Matheus> +pointer type that points to @var{target} and is owned by the given
Matheus> +@var{owner}, with the given @var{name} and size.
Matheus> +
Matheus> +@var{target} is a @code{gdb.Type} object, corresponding to the type
Matheus> +that will be pointed to by the newly created pointer type.
Matheus> +@end defun

I'm curious whether this one is really needed, because
gdb.Type.pointer() exists.

Like is there a case where you'd want a pointer type that doesn't match
the architecture somehow?  Seems weird and/or not useful.

Matheus> +/* Converts from a Python integer to a unsigned integer. */
Matheus> +
Matheus> +static bool
Matheus> +py_to_unsigned_int (PyObject *object, unsigned int *val)
Matheus> +{
Matheus> +  if (!PyObject_IsInstance (object, (PyObject*) &PyLong_Type))
Matheus> +    {
Matheus> +      PyErr_SetString (PyExc_TypeError, "value must be an integer");
Matheus> +      return false;
Matheus> +    }
Matheus> +
Matheus> +  long native_val = PyLong_AsLong (object);
Matheus> +  if (native_val > (long) UINT_MAX)
Matheus> +    {
Matheus> +      PyErr_SetString (PyExc_ValueError, "value is too large");
Matheus> +      return false;
Matheus> +    }
Matheus> +  if (native_val < 0)
Matheus> +    {
Matheus> +      PyErr_SetString (PyExc_ValueError,
Matheus> +		       "value must not be smaller than zero");
Matheus> +      return false;
Matheus> +    }
Matheus> +
Matheus> +  *val = (unsigned int) native_val;
Matheus> +  return true;

See gdb_py_int_as_long.
I think the type-check isn't really needed (probably) and some of the
other error-handling can be simplified.
There's also gdb_py_long_as_ulongest.

Matheus> +/* Functionality for creating new types accessible from python.
Matheus> +
Matheus> +   Copyright (C) 2008-2023 Free Software Foundation, Inc.

Forgot to mention this elsewhere but I think these dates are wrong.

Matheus> +/* An abstraction covering the objects types that can own a type object. */
Matheus> +
Matheus> +class type_storage_owner
Matheus> +{
Matheus> +public:
Matheus> +  /* Creates a new type owner from the given python object. If the object is
Matheus> +   * of a type that is not supported, the newly created instance will be
Matheus> +   * marked as invalid and nothing should be done with it. */
Matheus> +
Matheus> +  type_storage_owner (PyObject *owner)
Matheus> +  {
Matheus> +    if (gdbpy_is_architecture (owner))
Matheus> +      {
Matheus> +	this->kind = owner_kind::arch;
Matheus> +	this->owner.arch = arch_object_to_gdbarch (owner);
Matheus> +	return;
Matheus> +      }
Matheus> +
Matheus> +    this->kind = owner_kind::objfile;
Matheus> +    this->owner.objfile = objfile_object_to_objfile (owner);
Matheus> +    if (this->owner.objfile != nullptr)
Matheus> +	return;

It seems like this could all just create a type_allocator directly and
be simpler, like the 'kind' isn't needed.

Matheus> +
Matheus> +    this->kind = owner_kind::none;
Matheus> +    PyErr_SetString(PyExc_TypeError, "unsupported owner type");

Spaces before parens in a lot of spots...

Matheus> +    /* Should never be reached, but it's better to fail in a safe way than try
Matheus> +     * to instance the allocator with arbitraty parameters here. */
Matheus> +    abort ();

gdb uses gdb_assert_not_reached instead.

Matheus> +  /* Get a reference to the owner's obstack. */
Matheus> +
Matheus> +  obstack *get_obstack ()
Matheus> +  {

I think the uses of this could probably use TYPE_ALLOC instead.

Matheus> +  struct gdbarch *get_arch ()
Matheus> +  {

This could use the type allocator's arch.

Matheus> +  enum class owner_kind { arch, objfile, none };

Is the none case really possible?
It might be better to just throw an exception from the constructor or
during argument validation or something like that.

thanks,
Tom

  parent reply	other threads:[~2024-02-06 18:20 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-16  4:54 Matheus Branco Borella
2024-01-16 12:45 ` Eli Zaretskii
2024-01-16 17:50   ` Matheus Branco Borella
2024-01-16 18:20   ` [PATCH v4] Add support for creating new types from the Python API Matheus Branco Borella
2024-01-16 18:56     ` Eli Zaretskii
2024-01-16 21:27       ` Matheus Branco Borella
2024-02-06 18:20 ` Tom Tromey [this message]
2024-02-21 18:11   ` Matheus Branco Borella

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=871q9pe9p4.fsf@tromey.com \
    --to=tom@tromey.com \
    --cc=dark.ryu.550@gmail.com \
    --cc=eli@gnu.org \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).