From f46d690a288064e722cb196665c05fff1fe44bb8 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 27 Jul 2023 12:21:42 -0700 Subject: [PATCH] libsysprof-capture: add support for DBusMessage frames These are still captive to the max size of a SysprofCaptureFrame, but most messages fit into that. --- .../sysprof-capture-cursor.c | 4 ++ .../sysprof-capture-reader.c | 55 +++++++++++++++++++ .../sysprof-capture-reader.h | 2 + .../sysprof-capture-types.h | 22 +++++++- .../sysprof-capture-writer-cat.c | 17 ++++++ .../sysprof-capture-writer.c | 42 ++++++++++++++ .../sysprof-capture-writer.h | 8 +++ 7 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c index 376e8603..4cf46216 100644 --- a/src/libsysprof-capture/sysprof-capture-cursor.c +++ b/src/libsysprof-capture/sysprof-capture-cursor.c @@ -219,6 +219,10 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, delegate = READ_DELEGATE (sysprof_capture_reader_read_metadata); break; + case SYSPROF_CAPTURE_FRAME_DBUS_MESSAGE: + delegate = READ_DELEGATE (sysprof_capture_reader_read_dbus_message); + break; + case SYSPROF_CAPTURE_FRAME_FILE_CHUNK: delegate = READ_DELEGATE (sysprof_capture_reader_read_file); break; diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c index 6227af9b..eb8b85cd 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.c +++ b/src/libsysprof-capture/sysprof-capture-reader.c @@ -782,6 +782,61 @@ sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) return metadata; } +static inline void +sysprof_capture_reader_bswap_dbus_message (SysprofCaptureReader *self, + SysprofCaptureDBusMessage *dbus_message) +{ + assert (self != NULL); + assert (dbus_message != NULL); + + /* This only swaps the frame, not the endianness of the message data + * which is automatically handled by dbus libraries such as GDBus. + */ + + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + { + dbus_message->flags = bswap_16 (dbus_message->flags); + dbus_message->message_len = bswap_16 (dbus_message->message_len); + } +} + +const SysprofCaptureDBusMessage * +sysprof_capture_reader_read_dbus_message (SysprofCaptureReader *self) +{ + SysprofCaptureDBusMessage *dbus_message; + + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); + + if (!sysprof_capture_reader_ensure_space_for (self, sizeof *dbus_message)) + return NULL; + + dbus_message = (SysprofCaptureDBusMessage *)(void *)&self->buf[self->pos]; + + sysprof_capture_reader_bswap_frame (self, &dbus_message->frame); + + if (dbus_message->frame.type != SYSPROF_CAPTURE_FRAME_DBUS_MESSAGE) + return NULL; + + sysprof_capture_reader_bswap_dbus_message (self, dbus_message); + + if (dbus_message->frame.len < (sizeof *dbus_message + dbus_message->message_len)) + return NULL; + + if (!sysprof_capture_reader_ensure_space_for (self, dbus_message->frame.len)) + return NULL; + + dbus_message = (SysprofCaptureDBusMessage *)(void *)&self->buf[self->pos]; + + self->pos += dbus_message->frame.len; + + if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0) + return NULL; + + return dbus_message; +} + const SysprofCaptureProcess * sysprof_capture_reader_read_process (SysprofCaptureReader *self) { diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h index fbf6f143..79a929fd 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.h +++ b/src/libsysprof-capture/sysprof-capture-reader.h @@ -101,6 +101,8 @@ const SysprofCaptureMark *sysprof_capture_reader_read_mark ( SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureMetadata *sysprof_capture_reader_read_metadata (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL +const SysprofCaptureDBusMessage *sysprof_capture_reader_read_dbus_message (SysprofCaptureReader *self); +SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureExit *sysprof_capture_reader_read_exit (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureFork *sysprof_capture_reader_read_fork (SysprofCaptureReader *self); diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h index 9be4a0eb..2b835730 100644 --- a/src/libsysprof-capture/sysprof-capture-types.h +++ b/src/libsysprof-capture/sysprof-capture-types.h @@ -141,10 +141,11 @@ typedef enum SYSPROF_CAPTURE_FRAME_ALLOCATION = 14, SYSPROF_CAPTURE_FRAME_OVERLAY = 15, SYSPROF_CAPTURE_FRAME_TRACE = 16, + SYSPROF_CAPTURE_FRAME_DBUS_MESSAGE = 17, } SysprofCaptureFrameType; /* Not part of ABI */ -#define SYSPROF_CAPTURE_FRAME_LAST 17 +#define SYSPROF_CAPTURE_FRAME_LAST 18 SYSPROF_ALIGNED_BEGIN(1) typedef struct @@ -364,6 +365,24 @@ typedef struct } SysprofCaptureAllocation SYSPROF_ALIGNED_END(1); +SYSPROF_ALIGNED_BEGIN(1) +typedef struct +{ + SysprofCaptureFrame frame; + uint16_t bus_type : 2; + uint16_t flags : 14; + uint16_t message_len; + uint8_t message[0]; +} SysprofCaptureDBusMessage +SYSPROF_ALIGNED_END(1); + +#define SYSPROF_CAPTURE_DBUS_TYPE_SYSTEM 0 +#define SYSPROF_CAPTURE_DBUS_TYPE_SESSION 1 +#define SYSPROF_CAPTURE_DBUS_TYPE_A11Y 2 +#define SYSPROF_CAPTURE_DBUS_TYPE_OTHER 3 + +#define SYSPROF_CAPTURE_DBUS_FLAGS_MESSAGE_TOO_LARGE (1<<0) + SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256, "SysprofCaptureFileHeader changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24, "SysprofCaptureFrame changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56, "SysprofCaptureMap changed size"); @@ -384,6 +403,7 @@ SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64, "SysprofCaptureLog chan SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284, "SysprofCaptureFileChunk changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureAllocation) == 48, "SysprofCaptureAllocation changed size"); SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureOverlay) == 32, "SysprofCaptureOverlay changed size"); +SYSPROF_STATIC_ASSERT (sizeof (SysprofCaptureDBusMessage) == 28, "SysprofCaptureDBusMessage changed size"); SYSPROF_STATIC_ASSERT ((offsetof (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureAllocation.addrs is not aligned"); SYSPROF_STATIC_ASSERT ((offsetof (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureSample.addrs is not aligned"); diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c b/src/libsysprof-capture/sysprof-capture-writer-cat.c index e8de2367..23a19b4c 100644 --- a/src/libsysprof-capture/sysprof-capture-writer-cat.c +++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c @@ -391,6 +391,23 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, break; } + case SYSPROF_CAPTURE_FRAME_DBUS_MESSAGE: + { + const SysprofCaptureDBusMessage *frame; + + if (!(frame = sysprof_capture_reader_read_dbus_message (reader))) + goto panic; + + sysprof_capture_writer_add_dbus_message (self, + frame->frame.time, + frame->frame.cpu, + frame->frame.pid, + frame->flags, + frame->message, + frame->message_len); + break; + } + case SYSPROF_CAPTURE_FRAME_SAMPLE: { const SysprofCaptureSample *frame; diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c index fe654626..28baeec5 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.c +++ b/src/libsysprof-capture/sysprof-capture-writer.c @@ -767,6 +767,48 @@ sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, return true; } +bool +sysprof_capture_writer_add_dbus_message (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + uint32_t flags, + const uint8_t *message_data, + size_t message_len) +{ + SysprofCaptureDBusMessage *ev; + size_t len; + + assert (self != NULL); + assert (message_data != NULL || message_len == 0); + + if (message_len > (1<<16) - sizeof *ev - 16) + { + flags |= SYSPROF_CAPTURE_DBUS_FLAGS_MESSAGE_TOO_LARGE; + message_data = NULL; + message_len = 0; + } + + len = sizeof *ev + message_len; + + ev = (SysprofCaptureDBusMessage *)sysprof_capture_writer_allocate (self, &len); + if (!ev) + return false; + + sysprof_capture_writer_frame_init (&ev->frame, + len, + cpu, + pid, + time, + SYSPROF_CAPTURE_FRAME_DBUS_MESSAGE); + + ev->flags = flags; + ev->message_len = message_len; + memcpy (ev->message, message_data, message_len); + + return true; +} + SysprofCaptureAddress sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, const char *name) diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h index ffbb8edc..3ec27503 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.h +++ b/src/libsysprof-capture/sysprof-capture-writer.h @@ -230,6 +230,14 @@ bool sysprof_capture_writer_add_overlay (Sy const char *src, const char *dst); SYSPROF_AVAILABLE_IN_ALL +bool sysprof_capture_writer_add_dbus_message (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + uint32_t flags, + const uint8_t *message_data, + size_t message_len); +SYSPROF_AVAILABLE_IN_ALL bool sysprof_capture_writer_flush (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL bool sysprof_capture_writer_save_as (SysprofCaptureWriter *self,