Use structure size and version for event description extensibility
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 23 Nov 2023 21:22:54 +0000 (16:22 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 23 Nov 2023 21:22:54 +0000 (16:22 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/macros.h
include/side/trace.h
src/tracer.c

index 26fc0799975fb9ed410b198bcd8002fcf7e48002..10fcb66ffff07255314ed05a95f53cb2b2ad3cd4 100644 (file)
@@ -32,6 +32,9 @@
 
 #define SIDE_PARAM(...)        __VA_ARGS__
 
+#define side_offsetofend(type, member) \
+       (offsetof(type, member) + sizeof(((type *)0)->member))
+
 /*
  * SIDE_PARAM_SELECT_ARG1
  *
index 3a90b35c73a1b0d0f4b1ac882b9feb16511921ff..811a283e8f67f34e1c976ec5758457412390e63e 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdio.h>
 #include <math.h>
 #include <stdbool.h>
+#include <stddef.h>
 #include <side/macros.h>
 #include <side/endian.h>
 
  *   over the unknown type, both at event registration and when
  *   receiving the side_call arguments.
  *
- * TODO: extend event description with new fields ?
+ * * Event descriptions can be extended by adding fields at the end of
+ *   the structure. The "struct side_event_description" is therefore a
+ *   structure with flexible size and must not be used within arrays.
  */
 
-//TODO: as those structures will be ABI, we need to either consider them
-//fixed forever, or think of a scheme that would allow their binary
-//representation to be extended if need be.
+#define SIDE_ABI_VERSION       0
 
 struct side_arg;
 struct side_arg_vec;
@@ -712,19 +713,25 @@ struct side_arg_dynamic_field {
 side_check_size(struct side_arg_dynamic_field, 16 + sizeof(const struct side_arg));
 
 struct side_event_description {
+       uint32_t struct_size;   /* Size of this structure. */
+       uint32_t version;       /* ABI version. */
+
        side_ptr_t(struct side_event_state) state;
        side_ptr_t(const char) provider_name;
        side_ptr_t(const char) event_name;
        side_ptr_t(const struct side_event_field) fields;
        side_ptr_t(const struct side_attr) attr;
        uint64_t flags;
-       uint32_t version;
        uint16_t nr_side_type_label;
        uint16_t nr_side_attr_type;
        side_enum_t(enum side_loglevel, uint32_t) loglevel;
        uint32_t nr_fields;
        uint32_t nr_attr;
        uint32_t nr_callbacks;
+#define side_event_description_orig_abi_last   nr_callbacks
+       /* End of fields supported in the original ABI. */
+
+       char end[];     /* End with a flexible array to account for extensibility. */
 } SIDE_PACKED;
 
 /*
@@ -1877,13 +1884,14 @@ struct side_event_state {
        }; \
        _linkage struct side_event_description __attribute__((section("side_event_description"))) \
                        _identifier = { \
+               .struct_size = offsetof(struct side_event_description, end), \
+               .version = SIDE_ABI_VERSION, \
                .state = SIDE_PTR_INIT(&(side_event_state__##_identifier)), \
                .provider_name = SIDE_PTR_INIT(_provider), \
                .event_name = SIDE_PTR_INIT(_event), \
                .fields = SIDE_PTR_INIT(_fields), \
                .attr = SIDE_PTR_INIT(SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())), \
                .flags = (_flags), \
-               .version = 0, \
                .nr_side_type_label = _NR_SIDE_TYPE_LABEL, \
                .nr_side_attr_type = _NR_SIDE_ATTR_TYPE, \
                .loglevel = SIDE_ENUM_INIT(_loglevel), \
index 8d18952058984aa8efd48287396ca378df2172bd..dc902aaac2523cdae19a3ce48af917823214a014 100644 (file)
@@ -1797,8 +1797,17 @@ void tracer_event_notification(enum side_tracer_notification notif,
                /* Skip NULL pointers */
                if (!event)
                        continue;
+               if (event->version != SIDE_ABI_VERSION) {
+                       printf("Error: event SIDE ABI version (%u) does not match the SIDE ABI version supported by the tracer (%u)\n",
+                               event->version, SIDE_ABI_VERSION);
+                               return;
+               }
                printf("provider: %s, event: %s\n",
                        side_ptr_get(event->provider_name), side_ptr_get(event->event_name));
+               if (event->struct_size != side_offsetofend(struct side_event_description, side_event_description_orig_abi_last)) {
+                       printf("Warning: Event %s.%s contains fields unknown to the tracer\n",
+                               side_ptr_get(event->provider_name), side_ptr_get(event->event_name));
+               }
                if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) {
                        if (event->nr_side_type_label > _NR_SIDE_TYPE_LABEL) {
                                printf("Warning: event %s:%s may contain unknown field types (%u unknown types)\n",
This page took 0.045156 seconds and 4 git commands to generate.