How to use wl_object in wl_protocol_logger API?

2024-04-16 Thread Chloe Pelling
Hi,

I'm attempting to use the wl_protocol_logger API to replicate the
functionality of WAYLAND_DEBUG=1 in my project, but logging to
https://perfetto.dev/ rather than stderr. I'm having some trouble
decoding message arguments of type object, since `wl_object` is an
opaque struct and there doesn't appear to be a "blessed" way to
interrogate it. In particular, there's no API to access
`wl_object::id`.

Am I missing something? Would a patch adding wl_object_get_id() and
wl_object_get_class() functions be welcome?

Here's what I've figured out so far:

* Decoding the arguments requires inspecting the wl_argument unions in
`wl_protocol_logger_message::arguments`, according to the type
indications in `wl_protocol_logger_message::message->signature`.

* Object arguments are denoted by "o" in the signature, indicating we
should examine `wl_argument::o` of type wl_object.

* wl_object is an opaque struct, and there are no
wl_object_get_class() or wl_object_get_id() functions.

* I can work around the lack of wl_object_get_class() by inspecting
wl_protocol_logger_message::message->types[i] for argument
wl_protocol_logger_message::arguments[i]. However, no such workaround
exists to retrieve the wl_object's id.

* https://github.com/KDAB/GammaRay works around this problem by
casting wl_argument::o to wl_resource* and using
wl_resource_get_class() and wl_resource_get_id().

* This works because wl_resource's first member is wl_object, and
wl_resource_get_class() and wl_resource_get_id() are implemented only
by accessing that first member.
*  While comments in wl_resource indicate that the struct layout
cannot be changed. It's unclear if that will be true forever.
* There is no guarantee that wl_resource_get_class() and
wl_resource_get_id() won't start accessing members of wl_resource
other than `object`. If they did, this technique could cause invalid
memory access due to overflowing the size of wl_object.

I believe these are my current options:

A) Cast wl_object* to wl_resource* like GammaRay does. I'm
uncomfortable with this, for the reasons above.

B) Copy the definition of `struct wl_object` from wayland-private.h
into my project and access `id` directly. This might be safer than (A)
in practice, but I still don't like it.

C) Submit a patch adding wl_object_get_class() and wl_object_get_id()
accessor functions.

Have I missed something? Any advice would be helpful.

Best regards,
Chloe


Re: How to use wl_object in wl_protocol_logger API?

2024-05-01 Thread Chloe Pelling
I found a solution, but my offer to send a pull request adding
wl_object_get_class() and wl_object_get_id() still stands. Let me know!

To recap, my key question was: "The wl_protocol_logger API exposes a
wl_object struct. How can I get the object class and ID from a wl_object?"

To answer my own question: wl_object is actually declared here, behind an
#ifndef:
https://gitlab.freedesktop.org/wayland/wayland/-/blob/69633202180acce9d0d5ab4037d80291c71b2307/src/wayland-server.h#L58

The declaration is deprecated, though. I'm using it anyway for now, but I
think accessor functions would be better so that I can treat wl_object as
opaque. I'm happy to contribute if desired.

Best regards,
Chloe

On Tue, Apr 16, 2024 at 10:56 AM Chloe Pelling  wrote:

> Hi,
>
> I'm attempting to use the wl_protocol_logger API to replicate the
> functionality of WAYLAND_DEBUG=1 in my project, but logging to
> https://perfetto.dev/ rather than stderr. I'm having some trouble
> decoding message arguments of type object, since `wl_object` is an
> opaque struct and there doesn't appear to be a "blessed" way to
> interrogate it. In particular, there's no API to access
> `wl_object::id`.
>
> Am I missing something? Would a patch adding wl_object_get_id() and
> wl_object_get_class() functions be welcome?
>
> Here's what I've figured out so far:
>
> * Decoding the arguments requires inspecting the wl_argument unions in
> `wl_protocol_logger_message::arguments`, according to the type
> indications in `wl_protocol_logger_message::message->signature`.
>
> * Object arguments are denoted by "o" in the signature, indicating we
> should examine `wl_argument::o` of type wl_object.
>
> * wl_object is an opaque struct, and there are no
> wl_object_get_class() or wl_object_get_id() functions.
>
> * I can work around the lack of wl_object_get_class() by inspecting
> wl_protocol_logger_message::message->types[i] for argument
> wl_protocol_logger_message::arguments[i]. However, no such workaround
> exists to retrieve the wl_object's id.
>
> * https://github.com/KDAB/GammaRay works around this problem by
> casting wl_argument::o to wl_resource* and using
> wl_resource_get_class() and wl_resource_get_id().
>
> * This works because wl_resource's first member is wl_object, and
> wl_resource_get_class() and wl_resource_get_id() are implemented only
> by accessing that first member.
> *  While comments in wl_resource indicate that the struct layout
> cannot be changed. It's unclear if that will be true forever.
> * There is no guarantee that wl_resource_get_class() and
> wl_resource_get_id() won't start accessing members of wl_resource
> other than `object`. If they did, this technique could cause invalid
> memory access due to overflowing the size of wl_object.
>
> I believe these are my current options:
>
> A) Cast wl_object* to wl_resource* like GammaRay does. I'm
> uncomfortable with this, for the reasons above.
>
> B) Copy the definition of `struct wl_object` from wayland-private.h
> into my project and access `id` directly. This might be safer than (A)
> in practice, but I still don't like it.
>
> C) Submit a patch adding wl_object_get_class() and wl_object_get_id()
> accessor functions.
>
> Have I missed something? Any advice would be helpful.
>
> Best regards,
> Chloe
>