1 // SPDX-License-Identifier: MIT
3 * Copyright 2022-2023 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 #ifndef SIDE_ABI_TYPE_DESCRIPTION_H
7 #define SIDE_ABI_TYPE_DESCRIPTION_H
10 #include <side/macros.h>
11 #include <side/endian.h>
13 #include <side/abi/type-value.h>
14 #include <side/abi/attribute.h>
15 #include <side/abi/visitor.h>
18 * SIDE ABI for type description.
20 * This instrumentation ABI exposes 3 type systems:
22 * * Stack-copy type system: This is the core type system which can
23 * represent all supported types and into which all other type systems
24 * can be nested. This type system requires that every type is
25 * statically or dynamically declared and then registered, thus giving
26 * tracers a complete description of the events and their associated
27 * fields before the associated instrumentation is invoked. The
28 * application needs to copy each argument (side_arg_...()) onto the
29 * stack when calling the instrumentation.
31 * This is the most expressive of the 3 type systems, althrough not the
32 * fastest due to the extra copy of the arguments.
34 * * Data-gathering type system: This type system requires every type to
35 * be statically or dynamically declared and registered, but does not
36 * require the application to copy its arguments onto the stack.
37 * Instead, the type description contains all the required information
38 * to fetch the data from the application memory. The only argument
39 * required from the instrumentation is the base pointer from which
40 * the data should be fetched.
42 * This type system can be used as an event field, or nested within
43 * the stack-copy type system. Nesting of gather-vla within
44 * gather-array and gather-vla types is not allowed.
46 * This type system is has the least overhead of the 3 type systems.
48 * * Dynamic type system: This type system receives both type
49 * description and actual data onto the stack at runtime. It has more
50 * overhead that the 2 other type systems, but does not require a
51 * prior registration of event field description. This makes it useful
52 * for seldom used types which are not performance critical, but for
53 * which registering each individual events would needlessly grow the
54 * number of events to declare and register.
56 * Another use-case for this type system is for use by dynamically
57 * typed language runtimes, where the field type is only known when
58 * the instrumentation is called.
60 * Those dynamic types can be either used as arguments to a variadic
61 * field list, or as on-stack instrumentation argument for a static
62 * type SIDE_TYPE_DYNAMIC place holder in the stack-copy type system.
64 * The extensibility scheme for the SIDE ABI for type description is as
67 * * Existing field types are never changed nor extended. Field types
68 * can be added to the ABI by reserving a label within
69 * enum side_type_label.
70 * * Each union part of the ABI has an explicit size defined by a
71 * side_padding() member. Each structure and union have a static
72 * assert validating its size.
73 * * Changing the semantic of the existing type fields is a breaking
76 * Handling of unknown types by the tracers:
78 * * A tracer may choose to support only a subset of the types supported
79 * by libside. When encountering an unknown or unsupported type, the
80 * tracer has the option to either disallow the entire event or skip
81 * over the unknown type, both at event registration and when
82 * receiving the side_call arguments.
85 enum side_type_label
{
86 /* Stack-copy basic types */
99 SIDE_TYPE_FLOAT_BINARY16
,
100 SIDE_TYPE_FLOAT_BINARY32
,
101 SIDE_TYPE_FLOAT_BINARY64
,
102 SIDE_TYPE_FLOAT_BINARY128
,
103 SIDE_TYPE_STRING_UTF8
,
104 SIDE_TYPE_STRING_UTF16
,
105 SIDE_TYPE_STRING_UTF32
,
107 /* Stack-copy compound types */
112 SIDE_TYPE_VLA_VISITOR
,
114 /* Stack-copy enumeration types */
116 SIDE_TYPE_ENUM_BITMAP
,
118 /* Stack-copy place holder for dynamic types */
121 /* Gather basic types */
122 SIDE_TYPE_GATHER_BOOL
,
123 SIDE_TYPE_GATHER_INTEGER
,
124 SIDE_TYPE_GATHER_BYTE
,
125 SIDE_TYPE_GATHER_POINTER
,
126 SIDE_TYPE_GATHER_FLOAT
,
127 SIDE_TYPE_GATHER_STRING
,
129 /* Gather compound types */
130 SIDE_TYPE_GATHER_STRUCT
,
131 SIDE_TYPE_GATHER_ARRAY
,
132 SIDE_TYPE_GATHER_VLA
,
134 /* Gather enumeration types */
135 SIDE_TYPE_GATHER_ENUM
,
137 /* Dynamic basic types */
138 SIDE_TYPE_DYNAMIC_NULL
,
139 SIDE_TYPE_DYNAMIC_BOOL
,
140 SIDE_TYPE_DYNAMIC_INTEGER
,
141 SIDE_TYPE_DYNAMIC_BYTE
,
142 SIDE_TYPE_DYNAMIC_POINTER
,
143 SIDE_TYPE_DYNAMIC_FLOAT
,
144 SIDE_TYPE_DYNAMIC_STRING
,
146 /* Dynamic compound types */
147 SIDE_TYPE_DYNAMIC_STRUCT
,
148 SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
,
149 SIDE_TYPE_DYNAMIC_VLA
,
150 SIDE_TYPE_DYNAMIC_VLA_VISITOR
,
152 _NR_SIDE_TYPE_LABEL
, /* Last entry. */
155 enum side_visitor_status
{
156 SIDE_VISITOR_STATUS_OK
= 0,
157 SIDE_VISITOR_STATUS_ERROR
= -1,
160 enum side_type_gather_access_mode
{
161 SIDE_TYPE_GATHER_ACCESS_DIRECT
,
162 SIDE_TYPE_GATHER_ACCESS_POINTER
, /* Pointer dereference */
165 /* Type descriptions */
166 struct side_type_null
{
167 side_ptr_t(const struct side_attr
) attr
;
170 side_check_size(struct side_type_null
, 20);
172 struct side_type_bool
{
173 side_ptr_t(const struct side_attr
) attr
;
175 uint16_t bool_size
; /* bytes */
176 uint16_t len_bits
; /* bits. 0 for (bool_size * CHAR_BITS) */
177 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
179 side_check_size(struct side_type_bool
, 25);
181 struct side_type_byte
{
182 side_ptr_t(const struct side_attr
) attr
;
185 side_check_size(struct side_type_byte
, 20);
187 struct side_type_string
{
188 side_ptr_t(const struct side_attr
) attr
;
190 uint8_t unit_size
; /* 1, 2, or 4 bytes */
191 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
193 side_check_size(struct side_type_string
, 22);
195 struct side_type_integer
{
196 side_ptr_t(const struct side_attr
) attr
;
198 uint16_t integer_size
; /* bytes */
199 uint16_t len_bits
; /* bits. 0 for (integer_size * CHAR_BITS) */
200 uint8_t signedness
; /* true/false */
201 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
203 side_check_size(struct side_type_integer
, 26);
205 struct side_type_float
{
206 side_ptr_t(const struct side_attr
) attr
;
208 uint16_t float_size
; /* bytes */
209 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
211 side_check_size(struct side_type_float
, 23);
213 struct side_enum_mapping
{
216 struct side_type_raw_string label
;
218 side_check_size(struct side_enum_mapping
, 16 + sizeof(struct side_type_raw_string
));
220 struct side_enum_mappings
{
221 side_ptr_t(const struct side_enum_mapping
) mappings
;
222 side_ptr_t(const struct side_attr
) attr
;
223 uint32_t nr_mappings
;
226 side_check_size(struct side_enum_mappings
, 40);
228 struct side_enum_bitmap_mapping
{
229 uint64_t range_begin
;
231 struct side_type_raw_string label
;
233 side_check_size(struct side_enum_bitmap_mapping
, 16 + sizeof(struct side_type_raw_string
));
235 struct side_enum_bitmap_mappings
{
236 side_ptr_t(const struct side_enum_bitmap_mapping
) mappings
;
237 side_ptr_t(const struct side_attr
) attr
;
238 uint32_t nr_mappings
;
241 side_check_size(struct side_enum_bitmap_mappings
, 40);
243 struct side_type_struct
{
244 side_ptr_t(const struct side_event_field
) fields
;
245 side_ptr_t(const struct side_attr
) attr
;
249 side_check_size(struct side_type_struct
, 40);
251 struct side_type_array
{
252 side_ptr_t(const struct side_type
) elem_type
;
253 side_ptr_t(const struct side_attr
) attr
;
257 side_check_size(struct side_type_array
, 40);
259 struct side_type_vla
{
260 side_ptr_t(const struct side_type
) elem_type
;
261 side_ptr_t(const struct side_attr
) attr
;
264 side_check_size(struct side_type_vla
, 36);
266 struct side_type_vla_visitor
{
267 side_ptr_t(const struct side_type
) elem_type
;
268 side_func_ptr_t(side_visitor_func
) visitor
;
269 side_ptr_t(const struct side_attr
) attr
;
272 side_check_size(struct side_type_vla_visitor
, 52);
274 struct side_type_enum
{
275 side_ptr_t(const struct side_enum_mappings
) mappings
;
276 side_ptr_t(const struct side_type
) elem_type
;
278 side_check_size(struct side_type_enum
, 32);
280 struct side_type_enum_bitmap
{
281 side_ptr_t(const struct side_enum_bitmap_mappings
) mappings
;
282 side_ptr_t(const struct side_type
) elem_type
;
284 side_check_size(struct side_type_enum_bitmap
, 32);
286 struct side_type_gather_bool
{
287 uint64_t offset
; /* bytes */
288 uint16_t offset_bits
; /* bits */
289 uint8_t access_mode
; /* enum side_type_gather_access_mode */
290 struct side_type_bool type
;
292 side_check_size(struct side_type_gather_bool
, 11 + sizeof(struct side_type_bool
));
294 struct side_type_gather_byte
{
295 uint64_t offset
; /* bytes */
296 uint8_t access_mode
; /* enum side_type_gather_access_mode */
297 struct side_type_byte type
;
299 side_check_size(struct side_type_gather_byte
, 9 + sizeof(struct side_type_byte
));
301 struct side_type_gather_integer
{
302 uint64_t offset
; /* bytes */
303 uint16_t offset_bits
; /* bits */
304 uint8_t access_mode
; /* enum side_type_gather_access_mode */
305 struct side_type_integer type
;
307 side_check_size(struct side_type_gather_integer
, 11 + sizeof(struct side_type_integer
));
309 struct side_type_gather_float
{
310 uint64_t offset
; /* bytes */
311 uint8_t access_mode
; /* enum side_type_gather_access_mode */
312 struct side_type_float type
;
314 side_check_size(struct side_type_gather_float
, 9 + sizeof(struct side_type_float
));
316 struct side_type_gather_string
{
317 uint64_t offset
; /* bytes */
318 uint8_t access_mode
; /* enum side_type_gather_access_mode */
319 struct side_type_string type
;
321 side_check_size(struct side_type_gather_string
, 9 + sizeof(struct side_type_string
));
323 struct side_type_gather_enum
{
324 side_ptr_t(const struct side_enum_mappings
) mappings
;
325 side_ptr_t(const struct side_type
) elem_type
;
327 side_check_size(struct side_type_gather_enum
, 32);
329 struct side_type_gather_struct
{
330 side_ptr_t(const struct side_type_struct
) type
;
331 uint64_t offset
; /* bytes */
332 uint8_t access_mode
; /* enum side_type_gather_access_mode */
333 uint32_t size
; /* bytes */
335 side_check_size(struct side_type_gather_struct
, 29);
337 struct side_type_gather_array
{
338 uint64_t offset
; /* bytes */
339 uint8_t access_mode
; /* enum side_type_gather_access_mode */
340 struct side_type_array type
;
342 side_check_size(struct side_type_gather_array
, 9 + sizeof(struct side_type_array
));
344 struct side_type_gather_vla
{
345 side_ptr_t(const struct side_type
) length_type
; /* side_length() */
346 uint64_t offset
; /* bytes */
347 uint8_t access_mode
; /* enum side_type_gather_access_mode */
348 struct side_type_vla type
;
350 side_check_size(struct side_type_gather_vla
, 25 + sizeof(struct side_type_vla
));
352 struct side_type_gather
{
354 struct side_type_gather_bool side_bool
;
355 struct side_type_gather_byte side_byte
;
356 struct side_type_gather_integer side_integer
;
357 struct side_type_gather_float side_float
;
358 struct side_type_gather_string side_string
;
359 struct side_type_gather_enum side_enum
;
360 struct side_type_gather_array side_array
;
361 struct side_type_gather_vla side_vla
;
362 struct side_type_gather_struct side_struct
;
366 side_check_size(struct side_type_gather
, 61);
369 side_enum_t(enum side_type_label
, uint16_t) type
;
371 /* Stack-copy basic types */
372 struct side_type_null side_null
;
373 struct side_type_bool side_bool
;
374 struct side_type_byte side_byte
;
375 struct side_type_string side_string
;
376 struct side_type_integer side_integer
;
377 struct side_type_float side_float
;
379 /* Stack-copy compound types */
380 struct side_type_array side_array
;
381 struct side_type_vla side_vla
;
382 struct side_type_vla_visitor side_vla_visitor
;
383 side_ptr_t(const struct side_type_struct
) side_struct
;
384 side_ptr_t(const struct side_type_variant
) side_variant
;
386 /* Stack-copy enumeration types */
387 struct side_type_enum side_enum
;
388 struct side_type_enum_bitmap side_enum_bitmap
;
391 struct side_type_gather side_gather
;
395 side_check_size(struct side_type
, 64);
397 struct side_variant_option
{
400 const struct side_type side_type
;
402 side_check_size(struct side_variant_option
, 16 + sizeof(const struct side_type
));
404 struct side_type_variant
{
405 side_ptr_t(const struct side_variant_option
) options
;
406 side_ptr_t(const struct side_attr
) attr
;
409 const struct side_type selector
;
411 side_check_size(struct side_type_variant
, 40 + sizeof(const struct side_type
));
413 struct side_event_field
{
414 side_ptr_t(const char) field_name
;
415 struct side_type side_type
;
417 side_check_size(struct side_event_field
, 16 + sizeof(struct side_type
));
419 #endif /* SIDE_ABI_TYPE_DESCRIPTION_H */