e76fbe2b36c3269bbabbc0398113d681b0fc42b9
[libside.git] / include / side / abi / type-description.h
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2022-2023 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6 #ifndef SIDE_ABI_TYPE_DESCRIPTION_H
7 #define SIDE_ABI_TYPE_DESCRIPTION_H
8
9 #include <stdint.h>
10 #include <side/macros.h>
11 #include <side/endian.h>
12
13 #include <side/abi/type-value.h>
14 #include <side/abi/attribute.h>
15 #include <side/abi/visitor.h>
16
17 /*
18 * SIDE ABI for type description.
19 *
20 * This instrumentation ABI exposes 3 type systems:
21 *
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.
30 *
31 * This is the most expressive of the 3 type systems, althrough not the
32 * fastest due to the extra copy of the arguments.
33 *
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.
41 *
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.
45 *
46 * This type system is has the least overhead of the 3 type systems.
47 *
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.
55 *
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.
59 *
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.
63 *
64 * The extensibility scheme for the SIDE ABI for type description is as
65 * follows:
66 *
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
74 * ABI change.
75 *
76 * Handling of unknown types by the tracers:
77 *
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.
83 */
84
85 enum side_type_label {
86 /* Stack-copy basic types */
87 SIDE_TYPE_NULL,
88 SIDE_TYPE_BOOL,
89 SIDE_TYPE_U8,
90 SIDE_TYPE_U16,
91 SIDE_TYPE_U32,
92 SIDE_TYPE_U64,
93 SIDE_TYPE_S8,
94 SIDE_TYPE_S16,
95 SIDE_TYPE_S32,
96 SIDE_TYPE_S64,
97 SIDE_TYPE_BYTE,
98 SIDE_TYPE_POINTER,
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,
106
107 /* Stack-copy compound types */
108 SIDE_TYPE_STRUCT,
109 SIDE_TYPE_VARIANT,
110 SIDE_TYPE_ARRAY,
111 SIDE_TYPE_VLA,
112 SIDE_TYPE_VLA_VISITOR,
113
114 /* Stack-copy enumeration types */
115 SIDE_TYPE_ENUM,
116 SIDE_TYPE_ENUM_BITMAP,
117
118 /* Stack-copy place holder for dynamic types */
119 SIDE_TYPE_DYNAMIC,
120
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,
128
129 /* Gather compound types */
130 SIDE_TYPE_GATHER_STRUCT,
131 SIDE_TYPE_GATHER_ARRAY,
132 SIDE_TYPE_GATHER_VLA,
133
134 /* Gather enumeration types */
135 SIDE_TYPE_GATHER_ENUM,
136
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,
145
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,
151
152 _NR_SIDE_TYPE_LABEL, /* Last entry. */
153 };
154
155 enum side_visitor_status {
156 SIDE_VISITOR_STATUS_OK = 0,
157 SIDE_VISITOR_STATUS_ERROR = -1,
158 };
159
160 enum side_type_gather_access_mode {
161 SIDE_TYPE_GATHER_ACCESS_DIRECT,
162 SIDE_TYPE_GATHER_ACCESS_POINTER, /* Pointer dereference */
163 };
164
165 /* Type descriptions */
166 struct side_type_null {
167 side_ptr_t(const struct side_attr) attr;
168 uint32_t nr_attr;
169 } SIDE_PACKED;
170 side_check_size(struct side_type_null, 20);
171
172 struct side_type_bool {
173 side_ptr_t(const struct side_attr) attr;
174 uint32_t nr_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;
178 } SIDE_PACKED;
179 side_check_size(struct side_type_bool, 25);
180
181 struct side_type_byte {
182 side_ptr_t(const struct side_attr) attr;
183 uint32_t nr_attr;
184 } SIDE_PACKED;
185 side_check_size(struct side_type_byte, 20);
186
187 struct side_type_string {
188 side_ptr_t(const struct side_attr) attr;
189 uint32_t nr_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;
192 } SIDE_PACKED;
193 side_check_size(struct side_type_string, 22);
194
195 struct side_type_integer {
196 side_ptr_t(const struct side_attr) attr;
197 uint32_t nr_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;
202 } SIDE_PACKED;
203 side_check_size(struct side_type_integer, 26);
204
205 struct side_type_float {
206 side_ptr_t(const struct side_attr) attr;
207 uint32_t nr_attr;
208 uint16_t float_size; /* bytes */
209 side_enum_t(enum side_type_label_byte_order, uint8_t) byte_order;
210 } SIDE_PACKED;
211 side_check_size(struct side_type_float, 23);
212
213 struct side_enum_mapping {
214 int64_t range_begin;
215 int64_t range_end;
216 struct side_type_raw_string label;
217 } SIDE_PACKED;
218 side_check_size(struct side_enum_mapping, 16 + sizeof(struct side_type_raw_string));
219
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;
224 uint32_t nr_attr;
225 } SIDE_PACKED;
226 side_check_size(struct side_enum_mappings, 40);
227
228 struct side_enum_bitmap_mapping {
229 uint64_t range_begin;
230 uint64_t range_end;
231 struct side_type_raw_string label;
232 } SIDE_PACKED;
233 side_check_size(struct side_enum_bitmap_mapping, 16 + sizeof(struct side_type_raw_string));
234
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;
239 uint32_t nr_attr;
240 } SIDE_PACKED;
241 side_check_size(struct side_enum_bitmap_mappings, 40);
242
243 struct side_type_struct {
244 side_ptr_t(const struct side_event_field) fields;
245 side_ptr_t(const struct side_attr) attr;
246 uint32_t nr_fields;
247 uint32_t nr_attr;
248 } SIDE_PACKED;
249 side_check_size(struct side_type_struct, 40);
250
251 struct side_type_array {
252 side_ptr_t(const struct side_type) elem_type;
253 side_ptr_t(const struct side_attr) attr;
254 uint32_t length;
255 uint32_t nr_attr;
256 } SIDE_PACKED;
257 side_check_size(struct side_type_array, 40);
258
259 struct side_type_vla {
260 side_ptr_t(const struct side_type) elem_type;
261 side_ptr_t(const struct side_attr) attr;
262 uint32_t nr_attr;
263 } SIDE_PACKED;
264 side_check_size(struct side_type_vla, 36);
265
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;
270 uint32_t nr_attr;
271 } SIDE_PACKED;
272 side_check_size(struct side_type_vla_visitor, 52);
273
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;
277 } SIDE_PACKED;
278 side_check_size(struct side_type_enum, 32);
279
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;
283 } SIDE_PACKED;
284 side_check_size(struct side_type_enum_bitmap, 32);
285
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;
291 } SIDE_PACKED;
292 side_check_size(struct side_type_gather_bool, 11 + sizeof(struct side_type_bool));
293
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;
298 } SIDE_PACKED;
299 side_check_size(struct side_type_gather_byte, 9 + sizeof(struct side_type_byte));
300
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;
306 } SIDE_PACKED;
307 side_check_size(struct side_type_gather_integer, 11 + sizeof(struct side_type_integer));
308
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;
313 } SIDE_PACKED;
314 side_check_size(struct side_type_gather_float, 9 + sizeof(struct side_type_float));
315
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;
320 } SIDE_PACKED;
321 side_check_size(struct side_type_gather_string, 9 + sizeof(struct side_type_string));
322
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;
326 } SIDE_PACKED;
327 side_check_size(struct side_type_gather_enum, 32);
328
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 */
334 } SIDE_PACKED;
335 side_check_size(struct side_type_gather_struct, 29);
336
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;
341 } SIDE_PACKED;
342 side_check_size(struct side_type_gather_array, 9 + sizeof(struct side_type_array));
343
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;
349 } SIDE_PACKED;
350 side_check_size(struct side_type_gather_vla, 25 + sizeof(struct side_type_vla));
351
352 struct side_type_gather {
353 union {
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;
363 side_padding(61);
364 } SIDE_PACKED u;
365 } SIDE_PACKED;
366 side_check_size(struct side_type_gather, 61);
367
368 struct side_type {
369 side_enum_t(enum side_type_label, uint16_t) type;
370 union {
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;
378
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;
385
386 /* Stack-copy enumeration types */
387 struct side_type_enum side_enum;
388 struct side_type_enum_bitmap side_enum_bitmap;
389
390 /* Gather types */
391 struct side_type_gather side_gather;
392 side_padding(62);
393 } SIDE_PACKED u;
394 } SIDE_PACKED;
395 side_check_size(struct side_type, 64);
396
397 struct side_variant_option {
398 int64_t range_begin;
399 int64_t range_end;
400 const struct side_type side_type;
401 } SIDE_PACKED;
402 side_check_size(struct side_variant_option, 16 + sizeof(const struct side_type));
403
404 struct side_type_variant {
405 side_ptr_t(const struct side_variant_option) options;
406 side_ptr_t(const struct side_attr) attr;
407 uint32_t nr_options;
408 uint32_t nr_attr;
409 const struct side_type selector;
410 } SIDE_PACKED;
411 side_check_size(struct side_type_variant, 40 + sizeof(const struct side_type));
412
413 struct side_event_field {
414 side_ptr_t(const char) field_name;
415 struct side_type side_type;
416 } SIDE_PACKED;
417 side_check_size(struct side_event_field, 16 + sizeof(struct side_type));
418
419 #endif /* SIDE_ABI_TYPE_DESCRIPTION_H */
This page took 0.03674 seconds and 3 git commands to generate.