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 */
101 SIDE_TYPE_FLOAT_BINARY16
,
102 SIDE_TYPE_FLOAT_BINARY32
,
103 SIDE_TYPE_FLOAT_BINARY64
,
104 SIDE_TYPE_FLOAT_BINARY128
,
105 SIDE_TYPE_STRING_UTF8
,
106 SIDE_TYPE_STRING_UTF16
,
107 SIDE_TYPE_STRING_UTF32
,
109 /* Stack-copy compound types */
114 SIDE_TYPE_VLA_VISITOR
,
116 /* Stack-copy enumeration types */
118 SIDE_TYPE_ENUM_BITMAP
,
120 /* Stack-copy place holder for dynamic types */
123 /* Gather basic types */
124 SIDE_TYPE_GATHER_BOOL
,
125 SIDE_TYPE_GATHER_INTEGER
,
126 SIDE_TYPE_GATHER_BYTE
,
127 SIDE_TYPE_GATHER_POINTER
,
128 SIDE_TYPE_GATHER_FLOAT
,
129 SIDE_TYPE_GATHER_STRING
,
131 /* Gather compound types */
132 SIDE_TYPE_GATHER_STRUCT
,
133 SIDE_TYPE_GATHER_ARRAY
,
134 SIDE_TYPE_GATHER_VLA
,
136 /* Gather enumeration types */
137 SIDE_TYPE_GATHER_ENUM
,
139 /* Dynamic basic types */
140 SIDE_TYPE_DYNAMIC_NULL
,
141 SIDE_TYPE_DYNAMIC_BOOL
,
142 SIDE_TYPE_DYNAMIC_INTEGER
,
143 SIDE_TYPE_DYNAMIC_BYTE
,
144 SIDE_TYPE_DYNAMIC_POINTER
,
145 SIDE_TYPE_DYNAMIC_FLOAT
,
146 SIDE_TYPE_DYNAMIC_STRING
,
148 /* Dynamic compound types */
149 SIDE_TYPE_DYNAMIC_STRUCT
,
150 SIDE_TYPE_DYNAMIC_STRUCT_VISITOR
,
151 SIDE_TYPE_DYNAMIC_VLA
,
152 SIDE_TYPE_DYNAMIC_VLA_VISITOR
,
154 _NR_SIDE_TYPE_LABEL
, /* Last entry. */
157 enum side_visitor_status
{
158 SIDE_VISITOR_STATUS_OK
= 0,
159 SIDE_VISITOR_STATUS_ERROR
= -1,
162 enum side_type_gather_access_mode
{
163 SIDE_TYPE_GATHER_ACCESS_DIRECT
,
164 SIDE_TYPE_GATHER_ACCESS_POINTER
, /* Pointer dereference */
167 /* Type descriptions */
168 struct side_type_null
{
169 side_ptr_t(const struct side_attr
) attr
;
172 side_check_size(struct side_type_null
, 20);
174 struct side_type_bool
{
175 side_ptr_t(const struct side_attr
) attr
;
177 uint16_t bool_size
; /* bytes */
178 uint16_t len_bits
; /* bits. 0 for (bool_size * CHAR_BITS) */
179 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
181 side_check_size(struct side_type_bool
, 25);
183 struct side_type_byte
{
184 side_ptr_t(const struct side_attr
) attr
;
187 side_check_size(struct side_type_byte
, 20);
189 struct side_type_string
{
190 side_ptr_t(const struct side_attr
) attr
;
192 uint8_t unit_size
; /* 1, 2, or 4 bytes */
193 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
195 side_check_size(struct side_type_string
, 22);
197 struct side_type_integer
{
198 side_ptr_t(const struct side_attr
) attr
;
200 uint16_t integer_size
; /* bytes */
201 uint16_t len_bits
; /* bits. 0 for (integer_size * CHAR_BITS) */
202 uint8_t signedness
; /* true/false */
203 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
205 side_check_size(struct side_type_integer
, 26);
207 struct side_type_float
{
208 side_ptr_t(const struct side_attr
) attr
;
210 uint16_t float_size
; /* bytes */
211 side_enum_t(enum side_type_label_byte_order
, uint8_t) byte_order
;
213 side_check_size(struct side_type_float
, 23);
215 struct side_enum_mapping
{
218 struct side_type_raw_string label
;
220 side_check_size(struct side_enum_mapping
, 16 + sizeof(struct side_type_raw_string
));
222 struct side_enum_mappings
{
223 side_ptr_t(const struct side_enum_mapping
) mappings
;
224 side_ptr_t(const struct side_attr
) attr
;
225 uint32_t nr_mappings
;
228 side_check_size(struct side_enum_mappings
, 40);
230 struct side_enum_bitmap_mapping
{
231 uint64_t range_begin
;
233 struct side_type_raw_string label
;
235 side_check_size(struct side_enum_bitmap_mapping
, 16 + sizeof(struct side_type_raw_string
));
237 struct side_enum_bitmap_mappings
{
238 side_ptr_t(const struct side_enum_bitmap_mapping
) mappings
;
239 side_ptr_t(const struct side_attr
) attr
;
240 uint32_t nr_mappings
;
243 side_check_size(struct side_enum_bitmap_mappings
, 40);
245 struct side_type_struct
{
246 side_ptr_t(const struct side_event_field
) fields
;
247 side_ptr_t(const struct side_attr
) attr
;
251 side_check_size(struct side_type_struct
, 40);
253 struct side_type_array
{
254 side_ptr_t(const struct side_type
) elem_type
;
255 side_ptr_t(const struct side_attr
) attr
;
259 side_check_size(struct side_type_array
, 40);
261 struct side_type_vla
{
262 side_ptr_t(const struct side_type
) elem_type
;
263 side_ptr_t(const struct side_attr
) attr
;
266 side_check_size(struct side_type_vla
, 36);
268 struct side_type_vla_visitor
{
269 side_ptr_t(const struct side_type
) elem_type
;
270 side_func_ptr_t(side_visitor_func
) visitor
;
271 side_ptr_t(const struct side_attr
) attr
;
274 side_check_size(struct side_type_vla_visitor
, 52);
276 struct side_type_enum
{
277 side_ptr_t(const struct side_enum_mappings
) mappings
;
278 side_ptr_t(const struct side_type
) elem_type
;
280 side_check_size(struct side_type_enum
, 32);
282 struct side_type_enum_bitmap
{
283 side_ptr_t(const struct side_enum_bitmap_mappings
) mappings
;
284 side_ptr_t(const struct side_type
) elem_type
;
286 side_check_size(struct side_type_enum_bitmap
, 32);
288 struct side_type_gather_bool
{
289 uint64_t offset
; /* bytes */
290 uint16_t offset_bits
; /* bits */
291 uint8_t access_mode
; /* enum side_type_gather_access_mode */
292 struct side_type_bool type
;
294 side_check_size(struct side_type_gather_bool
, 11 + sizeof(struct side_type_bool
));
296 struct side_type_gather_byte
{
297 uint64_t offset
; /* bytes */
298 uint8_t access_mode
; /* enum side_type_gather_access_mode */
299 struct side_type_byte type
;
301 side_check_size(struct side_type_gather_byte
, 9 + sizeof(struct side_type_byte
));
303 struct side_type_gather_integer
{
304 uint64_t offset
; /* bytes */
305 uint16_t offset_bits
; /* bits */
306 uint8_t access_mode
; /* enum side_type_gather_access_mode */
307 struct side_type_integer type
;
309 side_check_size(struct side_type_gather_integer
, 11 + sizeof(struct side_type_integer
));
311 struct side_type_gather_float
{
312 uint64_t offset
; /* bytes */
313 uint8_t access_mode
; /* enum side_type_gather_access_mode */
314 struct side_type_float type
;
316 side_check_size(struct side_type_gather_float
, 9 + sizeof(struct side_type_float
));
318 struct side_type_gather_string
{
319 uint64_t offset
; /* bytes */
320 uint8_t access_mode
; /* enum side_type_gather_access_mode */
321 struct side_type_string type
;
323 side_check_size(struct side_type_gather_string
, 9 + sizeof(struct side_type_string
));
325 struct side_type_gather_enum
{
326 side_ptr_t(const struct side_enum_mappings
) mappings
;
327 side_ptr_t(const struct side_type
) elem_type
;
329 side_check_size(struct side_type_gather_enum
, 32);
331 struct side_type_gather_struct
{
332 side_ptr_t(const struct side_type_struct
) type
;
333 uint64_t offset
; /* bytes */
334 uint8_t access_mode
; /* enum side_type_gather_access_mode */
335 uint32_t size
; /* bytes */
337 side_check_size(struct side_type_gather_struct
, 29);
339 struct side_type_gather_array
{
340 uint64_t offset
; /* bytes */
341 uint8_t access_mode
; /* enum side_type_gather_access_mode */
342 struct side_type_array type
;
344 side_check_size(struct side_type_gather_array
, 9 + sizeof(struct side_type_array
));
346 struct side_type_gather_vla
{
347 side_ptr_t(const struct side_type
) length_type
; /* side_length() */
348 uint64_t offset
; /* bytes */
349 uint8_t access_mode
; /* enum side_type_gather_access_mode */
350 struct side_type_vla type
;
352 side_check_size(struct side_type_gather_vla
, 25 + sizeof(struct side_type_vla
));
354 struct side_type_gather
{
356 struct side_type_gather_bool side_bool
;
357 struct side_type_gather_byte side_byte
;
358 struct side_type_gather_integer side_integer
;
359 struct side_type_gather_float side_float
;
360 struct side_type_gather_string side_string
;
361 struct side_type_gather_enum side_enum
;
362 struct side_type_gather_array side_array
;
363 struct side_type_gather_vla side_vla
;
364 struct side_type_gather_struct side_struct
;
368 side_check_size(struct side_type_gather
, 61);
371 side_enum_t(enum side_type_label
, uint16_t) type
;
373 /* Stack-copy basic types */
374 struct side_type_null side_null
;
375 struct side_type_bool side_bool
;
376 struct side_type_byte side_byte
;
377 struct side_type_string side_string
;
378 struct side_type_integer side_integer
;
379 struct side_type_float side_float
;
381 /* Stack-copy compound types */
382 struct side_type_array side_array
;
383 struct side_type_vla side_vla
;
384 struct side_type_vla_visitor side_vla_visitor
;
385 side_ptr_t(const struct side_type_struct
) side_struct
;
386 side_ptr_t(const struct side_type_variant
) side_variant
;
388 /* Stack-copy enumeration types */
389 struct side_type_enum side_enum
;
390 struct side_type_enum_bitmap side_enum_bitmap
;
393 struct side_type_gather side_gather
;
397 side_check_size(struct side_type
, 64);
399 struct side_variant_option
{
402 const struct side_type side_type
;
404 side_check_size(struct side_variant_option
, 16 + sizeof(const struct side_type
));
406 struct side_type_variant
{
407 side_ptr_t(const struct side_variant_option
) options
;
408 side_ptr_t(const struct side_attr
) attr
;
411 const struct side_type selector
;
413 side_check_size(struct side_type_variant
, 40 + sizeof(const struct side_type
));
415 struct side_event_field
{
416 side_ptr_t(const char) field_name
;
417 struct side_type side_type
;
419 side_check_size(struct side_event_field
, 16 + sizeof(struct side_type
));
421 #endif /* SIDE_ABI_TYPE_DESCRIPTION_H */