Add u128/s128 integer to ABI
[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_U128,
94 SIDE_TYPE_S8,
95 SIDE_TYPE_S16,
96 SIDE_TYPE_S32,
97 SIDE_TYPE_S64,
98 SIDE_TYPE_S128,
99 SIDE_TYPE_BYTE,
100 SIDE_TYPE_POINTER,
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,
108
109 /* Stack-copy compound types */
110 SIDE_TYPE_STRUCT,
111 SIDE_TYPE_VARIANT,
112 SIDE_TYPE_ARRAY,
113 SIDE_TYPE_VLA,
114 SIDE_TYPE_VLA_VISITOR,
115
116 /* Stack-copy enumeration types */
117 SIDE_TYPE_ENUM,
118 SIDE_TYPE_ENUM_BITMAP,
119
120 /* Stack-copy place holder for dynamic types */
121 SIDE_TYPE_DYNAMIC,
122
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,
130
131 /* Gather compound types */
132 SIDE_TYPE_GATHER_STRUCT,
133 SIDE_TYPE_GATHER_ARRAY,
134 SIDE_TYPE_GATHER_VLA,
135
136 /* Gather enumeration types */
137 SIDE_TYPE_GATHER_ENUM,
138
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,
147
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,
153
154 _NR_SIDE_TYPE_LABEL, /* Last entry. */
155 };
156
157 enum side_visitor_status {
158 SIDE_VISITOR_STATUS_OK = 0,
159 SIDE_VISITOR_STATUS_ERROR = -1,
160 };
161
162 enum side_type_gather_access_mode {
163 SIDE_TYPE_GATHER_ACCESS_DIRECT,
164 SIDE_TYPE_GATHER_ACCESS_POINTER, /* Pointer dereference */
165 };
166
167 /* Type descriptions */
168 struct side_type_null {
169 side_ptr_t(const struct side_attr) attr;
170 uint32_t nr_attr;
171 } SIDE_PACKED;
172 side_check_size(struct side_type_null, 20);
173
174 struct side_type_bool {
175 side_ptr_t(const struct side_attr) attr;
176 uint32_t nr_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;
180 } SIDE_PACKED;
181 side_check_size(struct side_type_bool, 25);
182
183 struct side_type_byte {
184 side_ptr_t(const struct side_attr) attr;
185 uint32_t nr_attr;
186 } SIDE_PACKED;
187 side_check_size(struct side_type_byte, 20);
188
189 struct side_type_string {
190 side_ptr_t(const struct side_attr) attr;
191 uint32_t nr_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;
194 } SIDE_PACKED;
195 side_check_size(struct side_type_string, 22);
196
197 struct side_type_integer {
198 side_ptr_t(const struct side_attr) attr;
199 uint32_t nr_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;
204 } SIDE_PACKED;
205 side_check_size(struct side_type_integer, 26);
206
207 struct side_type_float {
208 side_ptr_t(const struct side_attr) attr;
209 uint32_t nr_attr;
210 uint16_t float_size; /* bytes */
211 side_enum_t(enum side_type_label_byte_order, uint8_t) byte_order;
212 } SIDE_PACKED;
213 side_check_size(struct side_type_float, 23);
214
215 struct side_enum_mapping {
216 int64_t range_begin;
217 int64_t range_end;
218 struct side_type_raw_string label;
219 } SIDE_PACKED;
220 side_check_size(struct side_enum_mapping, 16 + sizeof(struct side_type_raw_string));
221
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;
226 uint32_t nr_attr;
227 } SIDE_PACKED;
228 side_check_size(struct side_enum_mappings, 40);
229
230 struct side_enum_bitmap_mapping {
231 uint64_t range_begin;
232 uint64_t range_end;
233 struct side_type_raw_string label;
234 } SIDE_PACKED;
235 side_check_size(struct side_enum_bitmap_mapping, 16 + sizeof(struct side_type_raw_string));
236
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;
241 uint32_t nr_attr;
242 } SIDE_PACKED;
243 side_check_size(struct side_enum_bitmap_mappings, 40);
244
245 struct side_type_struct {
246 side_ptr_t(const struct side_event_field) fields;
247 side_ptr_t(const struct side_attr) attr;
248 uint32_t nr_fields;
249 uint32_t nr_attr;
250 } SIDE_PACKED;
251 side_check_size(struct side_type_struct, 40);
252
253 struct side_type_array {
254 side_ptr_t(const struct side_type) elem_type;
255 side_ptr_t(const struct side_attr) attr;
256 uint32_t length;
257 uint32_t nr_attr;
258 } SIDE_PACKED;
259 side_check_size(struct side_type_array, 40);
260
261 struct side_type_vla {
262 side_ptr_t(const struct side_type) elem_type;
263 side_ptr_t(const struct side_attr) attr;
264 uint32_t nr_attr;
265 } SIDE_PACKED;
266 side_check_size(struct side_type_vla, 36);
267
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;
272 uint32_t nr_attr;
273 } SIDE_PACKED;
274 side_check_size(struct side_type_vla_visitor, 52);
275
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;
279 } SIDE_PACKED;
280 side_check_size(struct side_type_enum, 32);
281
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;
285 } SIDE_PACKED;
286 side_check_size(struct side_type_enum_bitmap, 32);
287
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;
293 } SIDE_PACKED;
294 side_check_size(struct side_type_gather_bool, 11 + sizeof(struct side_type_bool));
295
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;
300 } SIDE_PACKED;
301 side_check_size(struct side_type_gather_byte, 9 + sizeof(struct side_type_byte));
302
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;
308 } SIDE_PACKED;
309 side_check_size(struct side_type_gather_integer, 11 + sizeof(struct side_type_integer));
310
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;
315 } SIDE_PACKED;
316 side_check_size(struct side_type_gather_float, 9 + sizeof(struct side_type_float));
317
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;
322 } SIDE_PACKED;
323 side_check_size(struct side_type_gather_string, 9 + sizeof(struct side_type_string));
324
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;
328 } SIDE_PACKED;
329 side_check_size(struct side_type_gather_enum, 32);
330
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 */
336 } SIDE_PACKED;
337 side_check_size(struct side_type_gather_struct, 29);
338
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;
343 } SIDE_PACKED;
344 side_check_size(struct side_type_gather_array, 9 + sizeof(struct side_type_array));
345
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;
351 } SIDE_PACKED;
352 side_check_size(struct side_type_gather_vla, 25 + sizeof(struct side_type_vla));
353
354 struct side_type_gather {
355 union {
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;
365 side_padding(61);
366 } SIDE_PACKED u;
367 } SIDE_PACKED;
368 side_check_size(struct side_type_gather, 61);
369
370 struct side_type {
371 side_enum_t(enum side_type_label, uint16_t) type;
372 union {
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;
380
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;
387
388 /* Stack-copy enumeration types */
389 struct side_type_enum side_enum;
390 struct side_type_enum_bitmap side_enum_bitmap;
391
392 /* Gather types */
393 struct side_type_gather side_gather;
394 side_padding(62);
395 } SIDE_PACKED u;
396 } SIDE_PACKED;
397 side_check_size(struct side_type, 64);
398
399 struct side_variant_option {
400 int64_t range_begin;
401 int64_t range_end;
402 const struct side_type side_type;
403 } SIDE_PACKED;
404 side_check_size(struct side_variant_option, 16 + sizeof(const struct side_type));
405
406 struct side_type_variant {
407 side_ptr_t(const struct side_variant_option) options;
408 side_ptr_t(const struct side_attr) attr;
409 uint32_t nr_options;
410 uint32_t nr_attr;
411 const struct side_type selector;
412 } SIDE_PACKED;
413 side_check_size(struct side_type_variant, 40 + sizeof(const struct side_type));
414
415 struct side_event_field {
416 side_ptr_t(const char) field_name;
417 struct side_type side_type;
418 } SIDE_PACKED;
419 side_check_size(struct side_event_field, 16 + sizeof(struct side_type));
420
421 #endif /* SIDE_ABI_TYPE_DESCRIPTION_H */
This page took 0.038036 seconds and 4 git commands to generate.