Add key characteristics to rfc
[libside.git] / include / side / abi / type-description.h
CommitLineData
57553dfd
MD
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2022-2023 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
b8dfb348
MD
6#ifndef SIDE_ABI_TYPE_DESCRIPTION_H
7#define SIDE_ABI_TYPE_DESCRIPTION_H
57553dfd
MD
8
9#include <stdint.h>
10#include <side/macros.h>
11#include <side/endian.h>
12
b8dfb348
MD
13#include <side/abi/type-value.h>
14#include <side/abi/attribute.h>
15#include <side/abi/visitor.h>
57553dfd 16
35e4f870
MD
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
57553dfd
MD
85enum 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,
eae1f40b 93 SIDE_TYPE_U128,
57553dfd
MD
94 SIDE_TYPE_S8,
95 SIDE_TYPE_S16,
96 SIDE_TYPE_S32,
97 SIDE_TYPE_S64,
eae1f40b 98 SIDE_TYPE_S128,
57553dfd
MD
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
157enum side_visitor_status {
158 SIDE_VISITOR_STATUS_OK = 0,
159 SIDE_VISITOR_STATUS_ERROR = -1,
160};
161
162enum side_type_gather_access_mode {
163 SIDE_TYPE_GATHER_ACCESS_DIRECT,
164 SIDE_TYPE_GATHER_ACCESS_POINTER, /* Pointer dereference */
165};
166
167/* Type descriptions */
168struct side_type_null {
169 side_ptr_t(const struct side_attr) attr;
170 uint32_t nr_attr;
171} SIDE_PACKED;
172side_check_size(struct side_type_null, 20);
173
174struct 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;
181side_check_size(struct side_type_bool, 25);
182
183struct side_type_byte {
184 side_ptr_t(const struct side_attr) attr;
185 uint32_t nr_attr;
186} SIDE_PACKED;
187side_check_size(struct side_type_byte, 20);
188
189struct 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;
195side_check_size(struct side_type_string, 22);
196
197struct 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;
205side_check_size(struct side_type_integer, 26);
206
207struct 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;
213side_check_size(struct side_type_float, 23);
214
215struct side_enum_mapping {
216 int64_t range_begin;
217 int64_t range_end;
218 struct side_type_raw_string label;
219} SIDE_PACKED;
220side_check_size(struct side_enum_mapping, 16 + sizeof(struct side_type_raw_string));
221
222struct 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;
228side_check_size(struct side_enum_mappings, 40);
229
230struct side_enum_bitmap_mapping {
231 uint64_t range_begin;
232 uint64_t range_end;
233 struct side_type_raw_string label;
234} SIDE_PACKED;
235side_check_size(struct side_enum_bitmap_mapping, 16 + sizeof(struct side_type_raw_string));
236
237struct 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;
243side_check_size(struct side_enum_bitmap_mappings, 40);
244
245struct 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;
251side_check_size(struct side_type_struct, 40);
252
253struct 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;
259side_check_size(struct side_type_array, 40);
260
261struct side_type_vla {
262 side_ptr_t(const struct side_type) elem_type;
f0619c77 263 side_ptr_t(const struct side_type) length_type;
57553dfd
MD
264 side_ptr_t(const struct side_attr) attr;
265 uint32_t nr_attr;
266} SIDE_PACKED;
f0619c77 267side_check_size(struct side_type_vla, 52);
57553dfd
MD
268
269struct side_type_vla_visitor {
270 side_ptr_t(const struct side_type) elem_type;
f0619c77 271 side_ptr_t(const struct side_type) length_type;
57553dfd
MD
272 side_func_ptr_t(side_visitor_func) visitor;
273 side_ptr_t(const struct side_attr) attr;
274 uint32_t nr_attr;
275} SIDE_PACKED;
f0619c77 276side_check_size(struct side_type_vla_visitor, 68);
57553dfd
MD
277
278struct side_type_enum {
279 side_ptr_t(const struct side_enum_mappings) mappings;
280 side_ptr_t(const struct side_type) elem_type;
281} SIDE_PACKED;
282side_check_size(struct side_type_enum, 32);
283
284struct side_type_enum_bitmap {
285 side_ptr_t(const struct side_enum_bitmap_mappings) mappings;
286 side_ptr_t(const struct side_type) elem_type;
287} SIDE_PACKED;
288side_check_size(struct side_type_enum_bitmap, 32);
289
290struct side_type_gather_bool {
291 uint64_t offset; /* bytes */
292 uint16_t offset_bits; /* bits */
f0619c77 293 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
294 struct side_type_bool type;
295} SIDE_PACKED;
296side_check_size(struct side_type_gather_bool, 11 + sizeof(struct side_type_bool));
297
298struct side_type_gather_byte {
299 uint64_t offset; /* bytes */
f0619c77 300 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
301 struct side_type_byte type;
302} SIDE_PACKED;
303side_check_size(struct side_type_gather_byte, 9 + sizeof(struct side_type_byte));
304
305struct side_type_gather_integer {
306 uint64_t offset; /* bytes */
307 uint16_t offset_bits; /* bits */
f0619c77 308 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
309 struct side_type_integer type;
310} SIDE_PACKED;
311side_check_size(struct side_type_gather_integer, 11 + sizeof(struct side_type_integer));
312
313struct side_type_gather_float {
314 uint64_t offset; /* bytes */
f0619c77 315 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
316 struct side_type_float type;
317} SIDE_PACKED;
318side_check_size(struct side_type_gather_float, 9 + sizeof(struct side_type_float));
319
320struct side_type_gather_string {
321 uint64_t offset; /* bytes */
f0619c77 322 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
323 struct side_type_string type;
324} SIDE_PACKED;
325side_check_size(struct side_type_gather_string, 9 + sizeof(struct side_type_string));
326
327struct side_type_gather_enum {
328 side_ptr_t(const struct side_enum_mappings) mappings;
329 side_ptr_t(const struct side_type) elem_type;
330} SIDE_PACKED;
331side_check_size(struct side_type_gather_enum, 32);
332
333struct side_type_gather_struct {
334 side_ptr_t(const struct side_type_struct) type;
335 uint64_t offset; /* bytes */
f0619c77 336 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
337 uint32_t size; /* bytes */
338} SIDE_PACKED;
339side_check_size(struct side_type_gather_struct, 29);
340
341struct side_type_gather_array {
342 uint64_t offset; /* bytes */
f0619c77 343 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
57553dfd
MD
344 struct side_type_array type;
345} SIDE_PACKED;
346side_check_size(struct side_type_gather_array, 9 + sizeof(struct side_type_array));
347
348struct side_type_gather_vla {
57553dfd 349 uint64_t offset; /* bytes */
f0619c77
MD
350 side_enum_t(enum side_type_gather_access_mode, uint8_t) access_mode;
351 /* Use side_length() for type->length_type. */
57553dfd
MD
352 struct side_type_vla type;
353} SIDE_PACKED;
f0619c77 354side_check_size(struct side_type_gather_vla, 9 + sizeof(struct side_type_vla));
57553dfd
MD
355
356struct side_type_gather {
357 union {
358 struct side_type_gather_bool side_bool;
359 struct side_type_gather_byte side_byte;
360 struct side_type_gather_integer side_integer;
361 struct side_type_gather_float side_float;
362 struct side_type_gather_string side_string;
363 struct side_type_gather_enum side_enum;
364 struct side_type_gather_array side_array;
365 struct side_type_gather_vla side_vla;
366 struct side_type_gather_struct side_struct;
367 side_padding(61);
368 } SIDE_PACKED u;
369} SIDE_PACKED;
370side_check_size(struct side_type_gather, 61);
371
372struct side_type {
373 side_enum_t(enum side_type_label, uint16_t) type;
374 union {
375 /* Stack-copy basic types */
376 struct side_type_null side_null;
377 struct side_type_bool side_bool;
378 struct side_type_byte side_byte;
379 struct side_type_string side_string;
380 struct side_type_integer side_integer;
381 struct side_type_float side_float;
382
383 /* Stack-copy compound types */
384 struct side_type_array side_array;
385 struct side_type_vla side_vla;
f0619c77 386 side_ptr_t(const struct side_type_vla_visitor) side_vla_visitor;
57553dfd
MD
387 side_ptr_t(const struct side_type_struct) side_struct;
388 side_ptr_t(const struct side_type_variant) side_variant;
389
390 /* Stack-copy enumeration types */
391 struct side_type_enum side_enum;
392 struct side_type_enum_bitmap side_enum_bitmap;
393
394 /* Gather types */
395 struct side_type_gather side_gather;
396 side_padding(62);
397 } SIDE_PACKED u;
398} SIDE_PACKED;
399side_check_size(struct side_type, 64);
400
401struct side_variant_option {
402 int64_t range_begin;
403 int64_t range_end;
404 const struct side_type side_type;
405} SIDE_PACKED;
406side_check_size(struct side_variant_option, 16 + sizeof(const struct side_type));
407
408struct side_type_variant {
409 side_ptr_t(const struct side_variant_option) options;
410 side_ptr_t(const struct side_attr) attr;
411 uint32_t nr_options;
412 uint32_t nr_attr;
413 const struct side_type selector;
414} SIDE_PACKED;
415side_check_size(struct side_type_variant, 40 + sizeof(const struct side_type));
416
417struct side_event_field {
418 side_ptr_t(const char) field_name;
419 struct side_type side_type;
420} SIDE_PACKED;
421side_check_size(struct side_event_field, 16 + sizeof(struct side_type));
422
b8dfb348 423#endif /* SIDE_ABI_TYPE_DESCRIPTION_H */
This page took 0.042858 seconds and 5 git commands to generate.