1 // SPDX-License-Identifier: MIT
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
16 #include <side/macros.h>
17 #include <side/endian.h>
20 * SIDE stands for "Software Instrumentation Dynamically Enabled"
22 * This is an instrumentation ABI for Linux user-space, which exposes an
23 * instrumentation type system and facilities allowing a kernel or
24 * user-space tracer to consume user-space instrumentation.
26 * The extensibility scheme for the SIDE ABI for event state is as
29 * * If the semantic of the "struct side_event_state_N" fields change,
30 * the SIDE_EVENT_STATE_ABI_VERSION should be increased. The
31 * "struct side_event_state_N" is not extensible and must have its
32 * ABI version increased whenever it is changed. Note that increasing
33 * the version of SIDE_EVENT_DESCRIPTION_ABI_VERSION is not necessary
34 * when changing the layout of "struct side_event_state_N".
37 #define SIDE_EVENT_STATE_ABI_VERSION 0
39 #include <side/abi/event-description.h>
40 #include <side/abi/type-argument.h>
41 #include <side/instrumentation-c-api.h>
49 SIDE_ERROR_EXITING
= 5,
53 * This structure is _not_ packed to allow atomic operations on its
54 * fields. Changes to this structure must bump the "Event state ABI
55 * version" and tracers _must_ learn how to deal with this ABI,
56 * otherwise they should reject the event.
59 struct side_event_state
{
60 uint32_t version
; /* Event state ABI version. */
63 struct side_event_state_0
{
64 struct side_event_state p
; /* Required first field. */
66 side_ptr_t(const struct side_callback
) callbacks
;
67 side_ptr_t(struct side_event_description
) desc
;
74 struct side_callback
{
76 void (*call
)(const struct side_event_description
*desc
,
77 const struct side_arg_vec
*side_arg_vec
,
79 void (*call_variadic
)(const struct side_event_description
*desc
,
80 const struct side_arg_vec
*side_arg_vec
,
81 const struct side_arg_dynamic_struct
*var_struct
,
87 extern const struct side_callback side_empty_callback
;
89 void side_call(const struct side_event_state
*state
,
90 const struct side_arg_vec
*side_arg_vec
);
91 void side_call_variadic(const struct side_event_state
*state
,
92 const struct side_arg_vec
*side_arg_vec
,
93 const struct side_arg_dynamic_struct
*var_struct
);
95 struct side_events_register_handle
*side_events_register(struct side_event_description
**events
,
97 void side_events_unregister(struct side_events_register_handle
*handle
);
100 * Userspace tracer registration API. This allows userspace tracers to
101 * register event notification callbacks to be notified of the currently
102 * registered instrumentation, and to register their callbacks to
105 typedef void (*side_tracer_callback_func
)(const struct side_event_description
*desc
,
106 const struct side_arg_vec
*side_arg_vec
,
108 typedef void (*side_tracer_callback_variadic_func
)(const struct side_event_description
*desc
,
109 const struct side_arg_vec
*side_arg_vec
,
110 const struct side_arg_dynamic_struct
*var_struct
,
113 int side_tracer_callback_register(struct side_event_description
*desc
,
114 side_tracer_callback_func call
,
116 int side_tracer_callback_variadic_register(struct side_event_description
*desc
,
117 side_tracer_callback_variadic_func call_variadic
,
119 int side_tracer_callback_unregister(struct side_event_description
*desc
,
120 side_tracer_callback_func call
,
122 int side_tracer_callback_variadic_unregister(struct side_event_description
*desc
,
123 side_tracer_callback_variadic_func call_variadic
,
126 enum side_tracer_notification
{
127 SIDE_TRACER_NOTIFICATION_INSERT_EVENTS
,
128 SIDE_TRACER_NOTIFICATION_REMOVE_EVENTS
,
131 /* Callback is invoked with side library internal lock held. */
132 struct side_tracer_handle
*side_tracer_event_notification_register(
133 void (*cb
)(enum side_tracer_notification notif
,
134 struct side_event_description
**events
, uint32_t nr_events
, void *priv
),
136 void side_tracer_event_notification_unregister(struct side_tracer_handle
*handle
);
139 * Explicit hooks to initialize/finalize the side instrumentation
140 * library. Those are also library constructor/destructor.
142 void side_init(void) __attribute__((constructor
));
143 void side_exit(void) __attribute__((destructor
));
146 * The following constructors/destructors perform automatic registration
147 * of the declared side events. Those may have to be called explicitly
148 * in a statically linked library.
152 * These weak symbols, the constructor, and destructor take care of
153 * registering only _one_ instance of the side instrumentation per
154 * shared-ojbect (or for the whole main program).
156 extern struct side_event_description
* __start_side_event_description_ptr
[]
157 __attribute__((weak
, visibility("hidden")));
158 extern struct side_event_description
* __stop_side_event_description_ptr
[]
159 __attribute__((weak
, visibility("hidden")));
160 int side_event_description_ptr_registered
161 __attribute__((weak
, visibility("hidden")));
162 struct side_events_register_handle
*side_events_handle
163 __attribute__((weak
, visibility("hidden")));
166 side_event_description_ptr_init(void)
167 __attribute__((no_instrument_function
))
168 __attribute__((constructor
));
170 side_event_description_ptr_init(void)
172 if (side_event_description_ptr_registered
++)
174 side_events_handle
= side_events_register(__start_side_event_description_ptr
,
175 __stop_side_event_description_ptr
- __start_side_event_description_ptr
);
179 side_event_description_ptr_exit(void)
180 __attribute__((no_instrument_function
))
181 __attribute__((destructor
));
183 side_event_description_ptr_exit(void)
185 if (--side_event_description_ptr_registered
)
187 side_events_unregister(side_events_handle
);
188 side_events_handle
= NULL
;
195 #endif /* _SIDE_TRACE_H */