Implement pointer type
[libside.git] / include / side / trace.h
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6 #ifndef _SIDE_TRACE_H
7 #define _SIDE_TRACE_H
8
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <math.h>
14 #include <side/macros.h>
15 #include <side/endian.h>
16
17 /* SIDE stands for "Static Instrumentation Dynamically Enabled" */
18
19 //TODO: as those structures will be ABI, we need to either consider them
20 //fixed forever, or think of a scheme that would allow their binary
21 //representation to be extended if need be.
22
23 struct side_arg_vec;
24 struct side_arg_vec_description;
25 struct side_arg_dynamic_vec;
26 struct side_arg_dynamic_vec_vla;
27 struct side_type_description;
28 struct side_event_field;
29 struct side_tracer_visitor_ctx;
30 struct side_tracer_dynamic_struct_visitor_ctx;
31 struct side_tracer_dynamic_vla_visitor_ctx;
32 struct side_event_description;
33 struct side_arg_dynamic_event_struct;
34 struct side_events_register_handle;
35
36 enum side_type {
37 /* Basic types */
38 SIDE_TYPE_BOOL,
39 SIDE_TYPE_U8,
40 SIDE_TYPE_U16,
41 SIDE_TYPE_U32,
42 SIDE_TYPE_U64,
43 SIDE_TYPE_S8,
44 SIDE_TYPE_S16,
45 SIDE_TYPE_S32,
46 SIDE_TYPE_S64,
47 SIDE_TYPE_BYTE,
48 SIDE_TYPE_POINTER,
49 SIDE_TYPE_FLOAT_BINARY16,
50 SIDE_TYPE_FLOAT_BINARY32,
51 SIDE_TYPE_FLOAT_BINARY64,
52 SIDE_TYPE_FLOAT_BINARY128,
53 SIDE_TYPE_STRING,
54
55 /* Compound types */
56 SIDE_TYPE_STRUCT,
57 SIDE_TYPE_ARRAY,
58 SIDE_TYPE_VLA,
59 SIDE_TYPE_VLA_VISITOR,
60
61 SIDE_TYPE_ARRAY_U8,
62 SIDE_TYPE_ARRAY_U16,
63 SIDE_TYPE_ARRAY_U32,
64 SIDE_TYPE_ARRAY_U64,
65 SIDE_TYPE_ARRAY_S8,
66 SIDE_TYPE_ARRAY_S16,
67 SIDE_TYPE_ARRAY_S32,
68 SIDE_TYPE_ARRAY_S64,
69 SIDE_TYPE_ARRAY_BYTE,
70 SIDE_TYPE_ARRAY_POINTER,
71
72 SIDE_TYPE_VLA_U8,
73 SIDE_TYPE_VLA_U16,
74 SIDE_TYPE_VLA_U32,
75 SIDE_TYPE_VLA_U64,
76 SIDE_TYPE_VLA_S8,
77 SIDE_TYPE_VLA_S16,
78 SIDE_TYPE_VLA_S32,
79 SIDE_TYPE_VLA_S64,
80 SIDE_TYPE_VLA_BYTE,
81 SIDE_TYPE_VLA_POINTER,
82
83 /* Enumeration types */
84 SIDE_TYPE_ENUM,
85 SIDE_TYPE_ENUM_BITMAP,
86
87 /* Dynamic type */
88 SIDE_TYPE_DYNAMIC,
89 };
90
91 enum side_dynamic_type {
92 /* Basic types */
93 SIDE_DYNAMIC_TYPE_NULL,
94 SIDE_DYNAMIC_TYPE_BOOL,
95 SIDE_DYNAMIC_TYPE_U8,
96 SIDE_DYNAMIC_TYPE_U16,
97 SIDE_DYNAMIC_TYPE_U32,
98 SIDE_DYNAMIC_TYPE_U64,
99 SIDE_DYNAMIC_TYPE_S8,
100 SIDE_DYNAMIC_TYPE_S16,
101 SIDE_DYNAMIC_TYPE_S32,
102 SIDE_DYNAMIC_TYPE_S64,
103 SIDE_DYNAMIC_TYPE_BYTE,
104 SIDE_DYNAMIC_TYPE_POINTER,
105 SIDE_DYNAMIC_TYPE_FLOAT_BINARY16,
106 SIDE_DYNAMIC_TYPE_FLOAT_BINARY32,
107 SIDE_DYNAMIC_TYPE_FLOAT_BINARY64,
108 SIDE_DYNAMIC_TYPE_FLOAT_BINARY128,
109 SIDE_DYNAMIC_TYPE_STRING,
110
111 /* Compound types */
112 SIDE_DYNAMIC_TYPE_STRUCT,
113 SIDE_DYNAMIC_TYPE_STRUCT_VISITOR,
114 SIDE_DYNAMIC_TYPE_VLA,
115 SIDE_DYNAMIC_TYPE_VLA_VISITOR,
116 };
117
118 enum side_attr_type {
119 SIDE_ATTR_TYPE_NULL,
120 SIDE_ATTR_TYPE_BOOL,
121 SIDE_ATTR_TYPE_U8,
122 SIDE_ATTR_TYPE_U16,
123 SIDE_ATTR_TYPE_U32,
124 SIDE_ATTR_TYPE_U64,
125 SIDE_ATTR_TYPE_S8,
126 SIDE_ATTR_TYPE_S16,
127 SIDE_ATTR_TYPE_S32,
128 SIDE_ATTR_TYPE_S64,
129 SIDE_ATTR_TYPE_POINTER,
130 SIDE_ATTR_TYPE_FLOAT_BINARY16,
131 SIDE_ATTR_TYPE_FLOAT_BINARY32,
132 SIDE_ATTR_TYPE_FLOAT_BINARY64,
133 SIDE_ATTR_TYPE_FLOAT_BINARY128,
134 SIDE_ATTR_TYPE_STRING,
135 };
136
137 enum side_loglevel {
138 SIDE_LOGLEVEL_EMERG = 0,
139 SIDE_LOGLEVEL_ALERT = 1,
140 SIDE_LOGLEVEL_CRIT = 2,
141 SIDE_LOGLEVEL_ERR = 3,
142 SIDE_LOGLEVEL_WARNING = 4,
143 SIDE_LOGLEVEL_NOTICE = 5,
144 SIDE_LOGLEVEL_INFO = 6,
145 SIDE_LOGLEVEL_DEBUG = 7,
146 };
147
148 enum side_visitor_status {
149 SIDE_VISITOR_STATUS_OK = 0,
150 SIDE_VISITOR_STATUS_ERROR = -1,
151 };
152
153 enum side_error {
154 SIDE_ERROR_OK = 0,
155 SIDE_ERROR_INVAL = 1,
156 SIDE_ERROR_EXIST = 2,
157 SIDE_ERROR_NOMEM = 3,
158 SIDE_ERROR_NOENT = 4,
159 SIDE_ERROR_EXITING = 5,
160 };
161
162 enum side_type_byte_order {
163 SIDE_TYPE_BYTE_ORDER_LE = 0,
164 SIDE_TYPE_BYTE_ORDER_BE = 1,
165 };
166
167 #if (SIDE_BYTE_ORDER == SIDE_LITTLE_ENDIAN)
168 # define SIDE_TYPE_BYTE_ORDER_HOST SIDE_TYPE_BYTE_ORDER_LE
169 #else
170 # define SIDE_TYPE_BYTE_ORDER_HOST SIDE_TYPE_BYTE_ORDER_BE
171 #endif
172
173 #if (SIDE_FLOAT_WORD_ORDER == SIDE_LITTLE_ENDIAN)
174 # define SIDE_TYPE_FLOAT_WORD_ORDER_HOST SIDE_TYPE_BYTE_ORDER_LE
175 #else
176 # define SIDE_TYPE_FLOAT_WORD_ORDER_HOST SIDE_TYPE_BYTE_ORDER_BE
177 #endif
178
179 typedef enum side_visitor_status (*side_visitor)(
180 const struct side_tracer_visitor_ctx *tracer_ctx,
181 void *app_ctx);
182 typedef enum side_visitor_status (*side_dynamic_struct_visitor)(
183 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
184 void *app_ctx);
185 typedef enum side_visitor_status (*side_dynamic_vla_visitor)(
186 const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
187 void *app_ctx);
188
189 struct side_attr_value {
190 uint32_t type; /* enum side_attr_type */
191 union {
192 uint8_t side_bool;
193 uint8_t side_u8;
194 uint16_t side_u16;
195 uint32_t side_u32;
196 uint64_t side_u64;
197 int8_t side_s8;
198 int16_t side_s16;
199 int32_t side_s32;
200 int64_t side_s64;
201 uintptr_t side_pointer;
202 #if __HAVE_FLOAT16
203 _Float16 side_float_binary16;
204 #endif
205 #if __HAVE_FLOAT32
206 _Float32 side_float_binary32;
207 #endif
208 #if __HAVE_FLOAT64
209 _Float64 side_float_binary64;
210 #endif
211 #if __HAVE_FLOAT128
212 _Float128 side_float_binary128;
213 #endif
214 const char *string;
215 } u;
216 };
217
218 /* User attributes. */
219 struct side_attr {
220 const char *key;
221 const struct side_attr_value value;
222 };
223
224 struct side_enum_mapping {
225 int64_t range_begin;
226 int64_t range_end;
227 const char *label;
228 };
229
230 struct side_enum_mappings {
231 const struct side_enum_mapping *mappings;
232 const struct side_attr *attr;
233 uint32_t nr_mappings;
234 uint32_t nr_attr;
235 };
236
237 struct side_enum_bitmap_mapping {
238 uint64_t range_begin;
239 uint64_t range_end;
240 const char *label;
241 };
242
243 struct side_enum_bitmap_mappings {
244 const struct side_enum_bitmap_mapping *mappings;
245 const struct side_attr *attr;
246 uint32_t nr_mappings;
247 uint32_t nr_attr;
248 };
249
250 struct side_type_struct {
251 uint32_t nr_fields;
252 uint32_t nr_attr;
253 const struct side_event_field *fields;
254 const struct side_attr *attr;
255 };
256
257 struct side_type_description {
258 uint32_t type; /* enum side_type */
259 union {
260 /* Basic types */
261 struct {
262 const struct side_attr *attr;
263 uint32_t nr_attr;
264 uint32_t byte_order; /* enum side_type_byte_order */
265 } side_basic;
266
267 /* Compound types */
268 struct {
269 const struct side_type_description *elem_type;
270 const struct side_attr *attr;
271 uint32_t length;
272 uint32_t nr_attr;
273 } side_array;
274 struct {
275 const struct side_type_description *elem_type;
276 const struct side_attr *attr;
277 uint32_t nr_attr;
278 } side_vla;
279 struct {
280 const struct side_type_description *elem_type;
281 side_visitor visitor;
282 const struct side_attr *attr;
283 uint32_t nr_attr;
284 } side_vla_visitor;
285 const struct side_type_struct *side_struct;
286
287 /* Enumeration types */
288 struct {
289 const struct side_enum_mappings *mappings;
290 const struct side_type_description *elem_type;
291 } side_enum;
292 struct {
293 const struct side_enum_bitmap_mappings *mappings;
294 const struct side_type_description *elem_type;
295 } side_enum_bitmap;
296 } u;
297 };
298
299 struct side_event_field {
300 const char *field_name;
301 struct side_type_description side_type;
302 };
303
304 enum side_event_flags {
305 SIDE_EVENT_FLAG_VARIADIC = (1 << 0),
306 };
307
308 struct side_callback {
309 union {
310 void (*call)(const struct side_event_description *desc,
311 const struct side_arg_vec_description *sav_desc,
312 void *priv);
313 void (*call_variadic)(const struct side_event_description *desc,
314 const struct side_arg_vec_description *sav_desc,
315 const struct side_arg_dynamic_event_struct *var_struct,
316 void *priv);
317 } u;
318 void *priv;
319 };
320
321 struct side_event_description {
322 uintptr_t *enabled;
323 const char *provider_name;
324 const char *event_name;
325 const struct side_event_field *fields;
326 const struct side_attr *attr;
327 const struct side_callback *callbacks;
328 uint64_t flags;
329 uint32_t version;
330 uint32_t loglevel; /* enum side_loglevel */
331 uint32_t nr_fields;
332 uint32_t nr_attr;
333 uint32_t nr_callbacks;
334 };
335
336 struct side_arg_dynamic_vec {
337 uint32_t dynamic_type; /* enum side_dynamic_type */
338 union {
339 /* Basic types */
340 struct {
341 const struct side_attr *attr;
342 uint32_t nr_attr;
343 uint32_t byte_order; /* enum side_type_byte_order */
344 union {
345 uint8_t side_bool;
346 uint8_t side_u8;
347 uint16_t side_u16;
348 uint32_t side_u32;
349 uint64_t side_u64;
350 int8_t side_s8;
351 int16_t side_s16;
352 int32_t side_s32;
353 int64_t side_s64;
354 uint8_t side_byte;
355 uintptr_t side_pointer;
356 #if __HAVE_FLOAT16
357 _Float16 side_float_binary16;
358 #endif
359 #if __HAVE_FLOAT32
360 _Float32 side_float_binary32;
361 #endif
362 #if __HAVE_FLOAT64
363 _Float64 side_float_binary64;
364 #endif
365 #if __HAVE_FLOAT128
366 _Float128 side_float_binary128;
367 #endif
368 const char *string;
369 } u;
370 } side_basic;
371
372 /* Compound types */
373 const struct side_arg_dynamic_event_struct *side_dynamic_struct;
374 struct {
375 void *app_ctx;
376 side_dynamic_struct_visitor visitor;
377 const struct side_attr *attr;
378 uint32_t nr_attr;
379 } side_dynamic_struct_visitor;
380 const struct side_arg_dynamic_vec_vla *side_dynamic_vla;
381 struct {
382 void *app_ctx;
383 side_dynamic_vla_visitor visitor;
384 const struct side_attr *attr;
385 uint32_t nr_attr;
386 } side_dynamic_vla_visitor;
387 } u;
388 };
389
390 struct side_arg_dynamic_vec_vla {
391 const struct side_arg_dynamic_vec *sav;
392 const struct side_attr *attr;
393 uint32_t len;
394 uint32_t nr_attr;
395 };
396
397 struct side_arg_dynamic_event_field {
398 const char *field_name;
399 const struct side_arg_dynamic_vec elem;
400 };
401
402 struct side_arg_dynamic_event_struct {
403 const struct side_arg_dynamic_event_field *fields;
404 const struct side_attr *attr;
405 uint32_t len;
406 uint32_t nr_attr;
407 };
408
409 struct side_arg_vec {
410 enum side_type type;
411 union {
412 /* Basic types */
413 uint8_t side_bool;
414 uint8_t side_u8;
415 uint16_t side_u16;
416 uint32_t side_u32;
417 uint64_t side_u64;
418 int8_t side_s8;
419 int16_t side_s16;
420 int32_t side_s32;
421 int64_t side_s64;
422 uint8_t side_byte;
423 uintptr_t side_pointer;
424 #if __HAVE_FLOAT16
425 _Float16 side_float_binary16;
426 #endif
427 #if __HAVE_FLOAT32
428 _Float32 side_float_binary32;
429 #endif
430 #if __HAVE_FLOAT64
431 _Float64 side_float_binary64;
432 #endif
433 #if __HAVE_FLOAT128
434 _Float128 side_float_binary128;
435 #endif
436 const char *string;
437
438 /* Compound types */
439 const struct side_arg_vec_description *side_struct;
440 const struct side_arg_vec_description *side_array;
441 const struct side_arg_vec_description *side_vla;
442 void *side_vla_app_visitor_ctx;
443 void *side_array_fixint;
444 struct {
445 void *p;
446 uint32_t length;
447 } side_vla_fixint;
448
449 /* Dynamic type */
450 struct side_arg_dynamic_vec dynamic;
451 } u;
452 };
453
454 struct side_arg_vec_description {
455 const struct side_arg_vec *sav;
456 uint32_t len;
457 };
458
459 /* The visitor pattern is a double-dispatch visitor. */
460 struct side_tracer_visitor_ctx {
461 enum side_visitor_status (*write_elem)(
462 const struct side_tracer_visitor_ctx *tracer_ctx,
463 const struct side_arg_vec *elem);
464 void *priv; /* Private tracer context. */
465 };
466
467 struct side_tracer_dynamic_struct_visitor_ctx {
468 enum side_visitor_status (*write_field)(
469 const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
470 const struct side_arg_dynamic_event_field *dynamic_field);
471 void *priv; /* Private tracer context. */
472 };
473
474 struct side_tracer_dynamic_vla_visitor_ctx {
475 enum side_visitor_status (*write_elem)(
476 const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
477 const struct side_arg_dynamic_vec *elem);
478 void *priv; /* Private tracer context. */
479 };
480
481 /* Event and type attributes */
482
483 #define side_attr(_key, _value) \
484 { \
485 .key = _key, \
486 .value = SIDE_PARAM(_value), \
487 }
488
489 #define side_attr_list(...) \
490 SIDE_COMPOUND_LITERAL(const struct side_attr, __VA_ARGS__)
491
492 #define side_attr_null(_val) { .type = SIDE_ATTR_TYPE_NULL }
493 #define side_attr_bool(_val) { .type = SIDE_ATTR_TYPE_BOOL, .u = { .side_bool = !!(_val) } }
494 #define side_attr_u8(_val) { .type = SIDE_ATTR_TYPE_U8, .u = { .side_u8 = (_val) } }
495 #define side_attr_u16(_val) { .type = SIDE_ATTR_TYPE_U16, .u = { .side_u16 = (_val) } }
496 #define side_attr_u32(_val) { .type = SIDE_ATTR_TYPE_U32, .u = { .side_u32 = (_val) } }
497 #define side_attr_u64(_val) { .type = SIDE_ATTR_TYPE_U64, .u = { .side_u64 = (_val) } }
498 #define side_attr_s8(_val) { .type = SIDE_ATTR_TYPE_S8, .u = { .side_s8 = (_val) } }
499 #define side_attr_s16(_val) { .type = SIDE_ATTR_TYPE_S16, .u = { .side_s16 = (_val) } }
500 #define side_attr_s32(_val) { .type = SIDE_ATTR_TYPE_S32, .u = { .side_s32 = (_val) } }
501 #define side_attr_s64(_val) { .type = SIDE_ATTR_TYPE_S64, .u = { .side_s64 = (_val) } }
502 #define side_attr_pointer(_val) { .type = SIDE_ATTR_TYPE_POINTER, .u = { .side_pointer = (uintptr_t) (_val) } }
503 #define side_attr_float_binary16(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY16, .u = { .side_float_binary16 = (_val) } }
504 #define side_attr_float_binary32(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY32, .u = { .side_float_binary32 = (_val) } }
505 #define side_attr_float_binary64(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY64, .u = { .side_float_binary64 = (_val) } }
506 #define side_attr_float_binary128(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY128, .u = { .side_float_binary128 = (_val) } }
507 #define side_attr_string(_val) { .type = SIDE_ATTR_TYPE_STRING, .u = { .string = (_val) } }
508
509 /* Static field definition */
510
511 #define _side_type_basic(_type, _byte_order, _attr) \
512 { \
513 .type = _type, \
514 .u = { \
515 .side_basic = { \
516 .attr = _attr, \
517 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
518 .byte_order = _byte_order, \
519 }, \
520 }, \
521 }
522
523 #define _side_field(_name, _type) \
524 { \
525 .field_name = _name, \
526 .side_type = _type, \
527 }
528
529 /* Host endian */
530 #define side_type_bool(_attr) _side_type_basic(SIDE_TYPE_BOOL, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
531 #define side_type_u8(_attr) _side_type_basic(SIDE_TYPE_U8, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
532 #define side_type_u16(_attr) _side_type_basic(SIDE_TYPE_U16, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
533 #define side_type_u32(_attr) _side_type_basic(SIDE_TYPE_U32, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
534 #define side_type_u64(_attr) _side_type_basic(SIDE_TYPE_U64, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
535 #define side_type_s8(_attr) _side_type_basic(SIDE_TYPE_S8, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
536 #define side_type_s16(_attr) _side_type_basic(SIDE_TYPE_S16, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
537 #define side_type_s32(_attr) _side_type_basic(SIDE_TYPE_S32, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
538 #define side_type_s64(_attr) _side_type_basic(SIDE_TYPE_S64, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
539 #define side_type_byte(_attr) _side_type_basic(SIDE_TYPE_BYTE, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
540 #define side_type_pointer(_attr) _side_type_basic(SIDE_TYPE_POINTER, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
541 #define side_type_float_binary16(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY16, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
542 #define side_type_float_binary32(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
543 #define side_type_float_binary64(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
544 #define side_type_float_binary128(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
545 #define side_type_string(_attr) _side_type_basic(SIDE_TYPE_STRING, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
546 #define side_type_dynamic(_attr) _side_type_basic(SIDE_TYPE_DYNAMIC, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
547
548 #define side_field_bool(_name, _attr) _side_field(_name, side_type_bool(SIDE_PARAM(_attr)))
549 #define side_field_u8(_name, _attr) _side_field(_name, side_type_u8(SIDE_PARAM(_attr)))
550 #define side_field_u16(_name, _attr) _side_field(_name, side_type_u16(SIDE_PARAM(_attr)))
551 #define side_field_u32(_name, _attr) _side_field(_name, side_type_u32(SIDE_PARAM(_attr)))
552 #define side_field_u64(_name, _attr) _side_field(_name, side_type_u64(SIDE_PARAM(_attr)))
553 #define side_field_s8(_name, _attr) _side_field(_name, side_type_s8(SIDE_PARAM(_attr)))
554 #define side_field_s16(_name, _attr) _side_field(_name, side_type_s16(SIDE_PARAM(_attr)))
555 #define side_field_s32(_name, _attr) _side_field(_name, side_type_s32(SIDE_PARAM(_attr)))
556 #define side_field_s64(_name, _attr) _side_field(_name, side_type_s64(SIDE_PARAM(_attr)))
557 #define side_field_byte(_name, _attr) _side_field(_name, side_type_byte(SIDE_PARAM(_attr)))
558 #define side_field_pointer(_name, _attr) _side_field(_name, side_type_pointer(SIDE_PARAM(_attr)))
559 #define side_field_float_binary16(_name, _attr) _side_field(_name, side_type_float_binary16(SIDE_PARAM(_attr)))
560 #define side_field_float_binary32(_name, _attr) _side_field(_name, side_type_float_binary32(SIDE_PARAM(_attr)))
561 #define side_field_float_binary64(_name, _attr) _side_field(_name, side_type_float_binary64(SIDE_PARAM(_attr)))
562 #define side_field_float_binary128(_name, _attr) _side_field(_name, side_type_float_binary128(SIDE_PARAM(_attr)))
563 #define side_field_string(_name, _attr) _side_field(_name, side_type_string(SIDE_PARAM(_attr)))
564 #define side_field_dynamic(_name, _attr) _side_field(_name, side_type_dynamic(SIDE_PARAM(_attr)))
565
566 /* Little endian */
567 #define side_type_u16_le(_attr) _side_type_basic(SIDE_TYPE_U16, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
568 #define side_type_u32_le(_attr) _side_type_basic(SIDE_TYPE_U32, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
569 #define side_type_u64_le(_attr) _side_type_basic(SIDE_TYPE_U64, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
570 #define side_type_s16_le(_attr) _side_type_basic(SIDE_TYPE_S16, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
571 #define side_type_s32_le(_attr) _side_type_basic(SIDE_TYPE_S32, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
572 #define side_type_s64_le(_attr) _side_type_basic(SIDE_TYPE_S64, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
573 #define side_type_pointer_le(_attr) _side_type_basic(SIDE_TYPE_POINTER, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
574 #define side_type_float_binary16_le(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY16, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
575 #define side_type_float_binary32_le(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
576 #define side_type_float_binary64_le(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
577 #define side_type_float_binary128_le(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
578
579 #define side_field_u16_le(_name, _attr) _side_field(_name, side_type_u16_le(SIDE_PARAM(_attr)))
580 #define side_field_u32_le(_name, _attr) _side_field(_name, side_type_u32_le(SIDE_PARAM(_attr)))
581 #define side_field_u64_le(_name, _attr) _side_field(_name, side_type_u64_le(SIDE_PARAM(_attr)))
582 #define side_field_s16_le(_name, _attr) _side_field(_name, side_type_s16_le(SIDE_PARAM(_attr)))
583 #define side_field_s32_le(_name, _attr) _side_field(_name, side_type_s32_le(SIDE_PARAM(_attr)))
584 #define side_field_s64_le(_name, _attr) _side_field(_name, side_type_s64_le(SIDE_PARAM(_attr)))
585 #define side_field_pointer_le(_name, _attr) _side_field(_name, side_type_pointer_le(SIDE_PARAM(_attr)))
586 #define side_field_float_binary16_le(_name, _attr) _side_field(_name, side_type_float_binary16_le(SIDE_PARAM(_attr)))
587 #define side_field_float_binary32_le(_name, _attr) _side_field(_name, side_type_float_binary32_le(SIDE_PARAM(_attr)))
588 #define side_field_float_binary64_le(_name, _attr) _side_field(_name, side_type_float_binary64_le(SIDE_PARAM(_attr)))
589 #define side_field_float_binary128_le(_name, _attr) _side_field(_name, side_type_float_binary128_le(SIDE_PARAM(_attr)))
590
591 /* Big endian */
592 #define side_type_u16_be(_attr) _side_type_basic(SIDE_TYPE_U16, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
593 #define side_type_u32_be(_attr) _side_type_basic(SIDE_TYPE_U32, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
594 #define side_type_u64_be(_attr) _side_type_basic(SIDE_TYPE_U64, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
595 #define side_type_s16_be(_attr) _side_type_basic(SIDE_TYPE_S16, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
596 #define side_type_s32_be(_attr) _side_type_basic(SIDE_TYPE_S32, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
597 #define side_type_s64_be(_attr) _side_type_basic(SIDE_TYPE_S64, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
598 #define side_type_pointer_be(_attr) _side_type_basic(SIDE_TYPE_POINTER, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
599 #define side_type_float_binary16_be(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY16, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
600 #define side_type_float_binary32_be(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
601 #define side_type_float_binary64_be(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
602 #define side_type_float_binary128_be(_attr) _side_type_basic(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
603
604 #define side_field_u16_be(_name, _attr) _side_field(_name, side_type_u16_be(SIDE_PARAM(_attr)))
605 #define side_field_u32_be(_name, _attr) _side_field(_name, side_type_u32_be(SIDE_PARAM(_attr)))
606 #define side_field_u64_be(_name, _attr) _side_field(_name, side_type_u64_be(SIDE_PARAM(_attr)))
607 #define side_field_s16_be(_name, _attr) _side_field(_name, side_type_s16_be(SIDE_PARAM(_attr)))
608 #define side_field_s32_be(_name, _attr) _side_field(_name, side_type_s32_be(SIDE_PARAM(_attr)))
609 #define side_field_s64_be(_name, _attr) _side_field(_name, side_type_s64_be(SIDE_PARAM(_attr)))
610 #define side_field_pointer_be(_name, _attr) _side_field(_name, side_type_pointer_be(SIDE_PARAM(_attr)))
611 #define side_field_float_binary16_be(_name, _attr) _side_field(_name, side_type_float_binary16_be(SIDE_PARAM(_attr)))
612 #define side_field_float_binary32_be(_name, _attr) _side_field(_name, side_type_float_binary32_be(SIDE_PARAM(_attr)))
613 #define side_field_float_binary64_be(_name, _attr) _side_field(_name, side_type_float_binary64_be(SIDE_PARAM(_attr)))
614 #define side_field_float_binary128_be(_name, _attr) _side_field(_name, side_type_float_binary128_be(SIDE_PARAM(_attr)))
615
616 #define side_type_enum(_mappings, _elem_type) \
617 { \
618 .type = SIDE_TYPE_ENUM, \
619 .u = { \
620 .side_enum = { \
621 .mappings = _mappings, \
622 .elem_type = _elem_type, \
623 }, \
624 }, \
625 }
626 #define side_field_enum(_name, _mappings, _elem_type) \
627 _side_field(_name, side_type_enum(SIDE_PARAM(_mappings), SIDE_PARAM(_elem_type)))
628
629 #define side_type_enum_bitmap(_mappings, _elem_type) \
630 { \
631 .type = SIDE_TYPE_ENUM_BITMAP, \
632 .u = { \
633 .side_enum_bitmap = { \
634 .mappings = _mappings, \
635 .elem_type = _elem_type, \
636 }, \
637 }, \
638 }
639 #define side_field_enum_bitmap(_name, _mappings, _elem_type) \
640 _side_field(_name, side_type_enum_bitmap(SIDE_PARAM(_mappings), SIDE_PARAM(_elem_type)))
641
642 #define side_type_struct(_struct) \
643 { \
644 .type = SIDE_TYPE_STRUCT, \
645 .u = { \
646 .side_struct = _struct, \
647 }, \
648 }
649 #define side_field_struct(_name, _struct) \
650 _side_field(_name, side_type_struct(SIDE_PARAM(_struct)))
651
652 #define _side_type_struct_define(_fields, _attr) \
653 { \
654 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
655 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
656 .fields = _fields, \
657 .attr = _attr, \
658 }
659
660 #define side_define_struct(_identifier, _fields, _attr) \
661 const struct side_type_struct _identifier = _side_type_struct_define(SIDE_PARAM(_fields), SIDE_PARAM(_attr))
662
663 #define side_struct_literal(_fields, _attr) \
664 SIDE_COMPOUND_LITERAL(const struct side_type_struct, \
665 _side_type_struct_define(SIDE_PARAM(_fields), SIDE_PARAM(_attr)))
666
667 #define side_type_array(_elem_type, _length, _attr) \
668 { \
669 .type = SIDE_TYPE_ARRAY, \
670 .u = { \
671 .side_array = { \
672 .elem_type = _elem_type, \
673 .attr = _attr, \
674 .length = _length, \
675 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
676 }, \
677 }, \
678 }
679 #define side_field_array(_name, _elem_type, _length, _attr) \
680 _side_field(_name, side_type_array(SIDE_PARAM(_elem_type), _length, SIDE_PARAM(_attr)))
681
682 #define side_type_vla(_elem_type, _attr) \
683 { \
684 .type = SIDE_TYPE_VLA, \
685 .u = { \
686 .side_vla = { \
687 .elem_type = _elem_type, \
688 .attr = _attr, \
689 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
690 }, \
691 }, \
692 }
693 #define side_field_vla(_name, _elem_type, _attr) \
694 _side_field(_name, side_type_vla(SIDE_PARAM(_elem_type), SIDE_PARAM(_attr)))
695
696 #define side_type_vla_visitor(_elem_type, _visitor, _attr) \
697 { \
698 .type = SIDE_TYPE_VLA_VISITOR, \
699 .u = { \
700 .side_vla_visitor = { \
701 .elem_type = SIDE_PARAM(_elem_type), \
702 .visitor = _visitor, \
703 .attr = _attr, \
704 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
705 }, \
706 }, \
707 }
708 #define side_field_vla_visitor(_name, _elem_type, _visitor, _attr) \
709 _side_field(_name, side_type_vla_visitor(SIDE_PARAM(_elem_type), _visitor, SIDE_PARAM(_attr)))
710
711 #define side_elem(...) \
712 SIDE_COMPOUND_LITERAL(const struct side_type_description, __VA_ARGS__)
713
714 #define side_field_list(...) \
715 SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
716
717 /* Static field arguments */
718
719 #define side_arg_bool(_val) { .type = SIDE_TYPE_BOOL, .u = { .side_bool = !!(_val) } }
720 #define side_arg_u8(_val) { .type = SIDE_TYPE_U8, .u = { .side_u8 = (_val) } }
721 #define side_arg_u16(_val) { .type = SIDE_TYPE_U16, .u = { .side_u16 = (_val) } }
722 #define side_arg_u32(_val) { .type = SIDE_TYPE_U32, .u = { .side_u32 = (_val) } }
723 #define side_arg_u64(_val) { .type = SIDE_TYPE_U64, .u = { .side_u64 = (_val) } }
724 #define side_arg_s8(_val) { .type = SIDE_TYPE_S8, .u = { .side_s8 = (_val) } }
725 #define side_arg_s16(_val) { .type = SIDE_TYPE_S16, .u = { .side_s16 = (_val) } }
726 #define side_arg_s32(_val) { .type = SIDE_TYPE_S32, .u = { .side_s32 = (_val) } }
727 #define side_arg_s64(_val) { .type = SIDE_TYPE_S64, .u = { .side_s64 = (_val) } }
728 #define side_arg_byte(_val) { .type = SIDE_TYPE_BYTE, .u = { .side_byte = (_val) } }
729 #define side_arg_pointer(_val) { .type = SIDE_TYPE_POINTER, .u = { .side_pointer = (uintptr_t) (_val) } }
730 #define side_arg_enum_bitmap8(_val) { .type = SIDE_TYPE_ENUM_BITMAP8, .u = { .side_u8 = (_val) } }
731 #define side_arg_enum_bitmap16(_val) { .type = SIDE_TYPE_ENUM_BITMAP16, .u = { .side_u16 = (_val) } }
732 #define side_arg_enum_bitmap32(_val) { .type = SIDE_TYPE_ENUM_BITMAP32, .u = { .side_u32 = (_val) } }
733 #define side_arg_enum_bitmap64(_val) { .type = SIDE_TYPE_ENUM_BITMAP64, .u = { .side_u64 = (_val) } }
734 #define side_arg_enum_bitmap_array(_side_type) { .type = SIDE_TYPE_ENUM_BITMAP_ARRAY, .u = { .side_array = (_side_type) } }
735 #define side_arg_enum_bitmap_vla(_side_type) { .type = SIDE_TYPE_ENUM_BITMAP_VLA, .u = { .side_vla = (_side_type) } }
736 #define side_arg_float_binary16(_val) { .type = SIDE_TYPE_FLOAT_BINARY16, .u = { .side_float_binary16 = (_val) } }
737 #define side_arg_float_binary32(_val) { .type = SIDE_TYPE_FLOAT_BINARY32, .u = { .side_float_binary32 = (_val) } }
738 #define side_arg_float_binary64(_val) { .type = SIDE_TYPE_FLOAT_BINARY64, .u = { .side_float_binary64 = (_val) } }
739 #define side_arg_float_binary128(_val) { .type = SIDE_TYPE_FLOAT_BINARY128, .u = { .side_float_binary128 = (_val) } }
740
741 #define side_arg_string(_val) { .type = SIDE_TYPE_STRING, .u = { .string = (_val) } }
742 #define side_arg_struct(_side_type) { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
743 #define side_arg_array(_side_type) { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
744 #define side_arg_vla(_side_type) { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
745 #define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_app_visitor_ctx = (_ctx) } }
746
747 #define side_arg_array_u8(_ptr) { .type = SIDE_TYPE_ARRAY_U8, .u = { .side_array_fixint = (_ptr) } }
748 #define side_arg_array_u16(_ptr) { .type = SIDE_TYPE_ARRAY_U16, .u = { .side_array_fixint = (_ptr) } }
749 #define side_arg_array_u32(_ptr) { .type = SIDE_TYPE_ARRAY_U32, .u = { .side_array_fixint = (_ptr) } }
750 #define side_arg_array_u64(_ptr) { .type = SIDE_TYPE_ARRAY_U64, .u = { .side_array_fixint = (_ptr) } }
751 #define side_arg_array_s8(_ptr) { .type = SIDE_TYPE_ARRAY_S8, .u = { .side_array_fixint = (_ptr) } }
752 #define side_arg_array_s16(_ptr) { .type = SIDE_TYPE_ARRAY_S16, .u = { .side_array_fixint = (_ptr) } }
753 #define side_arg_array_s32(_ptr) { .type = SIDE_TYPE_ARRAY_S32, .u = { .side_array_fixint = (_ptr) } }
754 #define side_arg_array_s64(_ptr) { .type = SIDE_TYPE_ARRAY_S64, .u = { .side_array_fixint = (_ptr) } }
755 #define side_arg_array_byte(_ptr) { .type = SIDE_TYPE_ARRAY_BYTE, .u = { .side_array_fixint = (_ptr) } }
756 #define side_arg_array_pointer(_ptr) { .type = SIDE_TYPE_ARRAY_POINTER, .u = { .side_array_fixint = (_ptr) } }
757
758 #define side_arg_vla_u8(_ptr, _length) { .type = SIDE_TYPE_VLA_U8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } }
759 #define side_arg_vla_u16(_ptr, _length) { .type = SIDE_TYPE_VLA_U16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
760 #define side_arg_vla_u32(_ptr, _length) { .type = SIDE_TYPE_VLA_U32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
761 #define side_arg_vla_u64(_ptr, _length) { .type = SIDE_TYPE_VLA_U64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
762 #define side_arg_vla_s8(_ptr, _length) { .type = SIDE_TYPE_VLA_S8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
763 #define side_arg_vla_s16(_ptr, _length) { .type = SIDE_TYPE_VLA_S16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
764 #define side_arg_vla_s32(_ptr, _length) { .type = SIDE_TYPE_VLA_S32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
765 #define side_arg_vla_s64(_ptr, _length) { .type = SIDE_TYPE_VLA_S64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
766 #define side_arg_vla_byte(_ptr, _length) { .type = SIDE_TYPE_VLA_BYTE, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
767 #define side_arg_vla_pointer(_ptr, _length) { .type = SIDE_TYPE_VLA_POINTER, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
768
769 #define side_arg_dynamic(_dynamic_arg_type) \
770 { \
771 .type = SIDE_TYPE_DYNAMIC, \
772 .u = { \
773 .dynamic = _dynamic_arg_type, \
774 }, \
775 }
776
777 /* Dynamic field arguments */
778
779 #define side_arg_dynamic_null(_attr) \
780 { \
781 .dynamic_type = SIDE_DYNAMIC_TYPE_NULL, \
782 .u = { \
783 .side_basic = { \
784 .attr = _attr, \
785 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
786 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
787 }, \
788 }, \
789 }
790
791 #define side_arg_dynamic_bool(_val, _attr) \
792 { \
793 .dynamic_type = SIDE_DYNAMIC_TYPE_BOOL, \
794 .u = { \
795 .side_basic = { \
796 .attr = _attr, \
797 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
798 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
799 .u = { \
800 .side_bool = !!(_val), \
801 }, \
802 }, \
803 }, \
804 }
805
806 #define side_arg_dynamic_u8(_val, _attr) \
807 { \
808 .dynamic_type = SIDE_DYNAMIC_TYPE_U8, \
809 .u = { \
810 .side_basic = { \
811 .attr = _attr, \
812 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
813 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
814 .u = { \
815 .side_u8 = (_val), \
816 }, \
817 }, \
818 }, \
819 }
820 #define side_arg_dynamic_s8(_val, _attr) \
821 { \
822 .dynamic_type = SIDE_DYNAMIC_TYPE_S8, \
823 .u = { \
824 .side_basic = { \
825 .attr = _attr, \
826 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
827 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
828 .u = { \
829 .side_s8 = (_val), \
830 }, \
831 }, \
832 }, \
833 }
834 #define side_arg_dynamic_byte(_val, _attr) \
835 { \
836 .dynamic_type = SIDE_DYNAMIC_TYPE_BYTE, \
837 .u = { \
838 .side_basic = { \
839 .attr = _attr, \
840 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
841 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
842 .u = { \
843 .side_byte = (_val), \
844 }, \
845 }, \
846 }, \
847 }
848 #define side_arg_dynamic_string(_val, _attr) \
849 { \
850 .dynamic_type = SIDE_DYNAMIC_TYPE_STRING, \
851 .u = { \
852 .side_basic = { \
853 .attr = _attr, \
854 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
855 .byte_order = SIDE_TYPE_BYTE_ORDER_HOST, \
856 .u = { \
857 .string = (_val), \
858 }, \
859 }, \
860 }, \
861 }
862
863 #define _side_arg_dynamic_u16(_val, _byte_order, _attr) \
864 { \
865 .dynamic_type = SIDE_DYNAMIC_TYPE_U16, \
866 .u = { \
867 .side_basic = { \
868 .attr = _attr, \
869 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
870 .byte_order = _byte_order, \
871 .u = { \
872 .side_u16 = (_val), \
873 }, \
874 }, \
875 }, \
876 }
877 #define _side_arg_dynamic_u32(_val, _byte_order, _attr) \
878 { \
879 .dynamic_type = SIDE_DYNAMIC_TYPE_U32, \
880 .u = { \
881 .side_basic = { \
882 .attr = _attr, \
883 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
884 .byte_order = _byte_order, \
885 .u = { \
886 .side_u32 = (_val), \
887 }, \
888 }, \
889 }, \
890 }
891 #define _side_arg_dynamic_u64(_val, _byte_order, _attr) \
892 { \
893 .dynamic_type = SIDE_DYNAMIC_TYPE_U64, \
894 .u = { \
895 .side_basic = { \
896 .attr = _attr, \
897 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
898 .byte_order = _byte_order, \
899 .u = { \
900 .side_u64 = (_val), \
901 }, \
902 }, \
903 }, \
904 }
905
906 #define _side_arg_dynamic_s16(_val, _byte_order, _attr) \
907 { \
908 .dynamic_type = SIDE_DYNAMIC_TYPE_S16, \
909 .u = { \
910 .side_basic = { \
911 .attr = _attr, \
912 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
913 .byte_order = _byte_order, \
914 .u = { \
915 .side_s16 = (_val), \
916 }, \
917 }, \
918 }, \
919 }
920 #define _side_arg_dynamic_s32(_val, _byte_order, _attr) \
921 { \
922 .dynamic_type = SIDE_DYNAMIC_TYPE_S32, \
923 .u = { \
924 .side_basic = { \
925 .attr = _attr, \
926 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
927 .byte_order = _byte_order, \
928 .u = { \
929 .side_s32 = (_val), \
930 }, \
931 }, \
932 }, \
933 }
934 #define _side_arg_dynamic_s64(_val, _byte_order, _attr) \
935 { \
936 .dynamic_type = SIDE_DYNAMIC_TYPE_S64, \
937 .u = { \
938 .side_basic = { \
939 .attr = _attr, \
940 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
941 .byte_order = _byte_order, \
942 .u = { \
943 .side_s64 = (_val), \
944 }, \
945 }, \
946 }, \
947 }
948 #define _side_arg_dynamic_pointer(_val, _byte_order, _attr) \
949 { \
950 .dynamic_type = SIDE_DYNAMIC_TYPE_POINTER, \
951 .u = { \
952 .side_basic = { \
953 .attr = _attr, \
954 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
955 .byte_order = _byte_order, \
956 .u = { \
957 .side_pointer = (uintptr_t) (_val), \
958 }, \
959 }, \
960 }, \
961 }
962 #define _side_arg_dynamic_float_binary16(_val, _byte_order, _attr) \
963 { \
964 .dynamic_type = SIDE_DYNAMIC_TYPE_FLOAT_BINARY16, \
965 .u = { \
966 .side_basic = { \
967 .attr = _attr, \
968 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
969 .byte_order = _byte_order, \
970 .u = { \
971 .side_float_binary16 = (_val), \
972 }, \
973 }, \
974 }, \
975 }
976 #define _side_arg_dynamic_float_binary32(_val, _byte_order, _attr) \
977 { \
978 .dynamic_type = SIDE_DYNAMIC_TYPE_FLOAT_BINARY32, \
979 .u = { \
980 .side_basic = { \
981 .attr = _attr, \
982 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
983 .byte_order = _byte_order, \
984 .u = { \
985 .side_float_binary32 = (_val), \
986 }, \
987 }, \
988 }, \
989 }
990 #define _side_arg_dynamic_float_binary64(_val, _byte_order, _attr) \
991 { \
992 .dynamic_type = SIDE_DYNAMIC_TYPE_FLOAT_BINARY64, \
993 .u = { \
994 .side_basic = { \
995 .attr = _attr, \
996 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
997 .byte_order = _byte_order, \
998 .u = { \
999 .side_float_binary64 = (_val), \
1000 }, \
1001 }, \
1002 }, \
1003 }
1004 #define _side_arg_dynamic_float_binary128(_val, _byte_order, _attr) \
1005 { \
1006 .dynamic_type = SIDE_DYNAMIC_TYPE_FLOAT_BINARY128, \
1007 .u = { \
1008 .side_basic = { \
1009 .attr = _attr, \
1010 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1011 .byte_order = _byte_order, \
1012 .u = { \
1013 .side_float_binary128 = (_val), \
1014 }, \
1015 }, \
1016 }, \
1017 }
1018
1019 /* Host endian */
1020 #define side_arg_dynamic_u16(_val, _attr) _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1021 #define side_arg_dynamic_u32(_val, _attr) _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1022 #define side_arg_dynamic_u64(_val, _attr) _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1023 #define side_arg_dynamic_s16(_val, _attr) _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1024 #define side_arg_dynamic_s32(_val, _attr) _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1025 #define side_arg_dynamic_s64(_val, _attr) _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1026 #define side_arg_dynamic_pointer(_val, _attr) _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_HOST, SIDE_PARAM(_attr))
1027 #define side_arg_dynamic_float_binary16(_val, _attr) _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
1028 #define side_arg_dynamic_float_binary32(_val, _attr) _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
1029 #define side_arg_dynamic_float_binary64(_val, _attr) _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
1030 #define side_arg_dynamic_float_binary128(_val, _attr) _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, SIDE_PARAM(_attr))
1031
1032 /* Little endian */
1033 #define side_arg_dynamic_u16_le(_val, _attr) _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1034 #define side_arg_dynamic_u32_le(_val, _attr) _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1035 #define side_arg_dynamic_u64_le(_val, _attr) _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1036 #define side_arg_dynamic_s16_le(_val, _attr) _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1037 #define side_arg_dynamic_s32_le(_val, _attr) _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1038 #define side_arg_dynamic_s64_le(_val, _attr) _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1039 #define side_arg_dynamic_pointer_le(_val, _attr) _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1040 #define side_arg_dynamic_float_binary16_le(_val, _attr) _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1041 #define side_arg_dynamic_float_binary32_le(_val, _attr) _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1042 #define side_arg_dynamic_float_binary64_le(_val, _attr) _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1043 #define side_arg_dynamic_float_binary128_le(_val, _attr) _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_LE, SIDE_PARAM(_attr))
1044
1045 /* Big endian */
1046 #define side_arg_dynamic_u16_be(_val, _attr) _side_arg_dynamic_u16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1047 #define side_arg_dynamic_u32_be(_val, _attr) _side_arg_dynamic_u32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1048 #define side_arg_dynamic_u64_be(_val, _attr) _side_arg_dynamic_u64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1049 #define side_arg_dynamic_s16_be(_val, _attr) _side_arg_dynamic_s16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1050 #define side_arg_dynamic_s32_be(_val, _attr) _side_arg_dynamic_s32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1051 #define side_arg_dynamic_s64_be(_val, _attr) _side_arg_dynamic_s64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1052 #define side_arg_dynamic_pointer_be(_val, _attr) _side_arg_dynamic_pointer(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1053 #define side_arg_dynamic_float_binary16_be(_val, _attr) _side_arg_dynamic_float_binary16(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1054 #define side_arg_dynamic_float_binary32_be(_val, _attr) _side_arg_dynamic_float_binary32(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1055 #define side_arg_dynamic_float_binary64_be(_val, _attr) _side_arg_dynamic_float_binary64(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1056 #define side_arg_dynamic_float_binary128_be(_val, _attr) _side_arg_dynamic_float_binary128(_val, SIDE_TYPE_BYTE_ORDER_BE, SIDE_PARAM(_attr))
1057
1058 #define side_arg_dynamic_vla(_vla) \
1059 { \
1060 .dynamic_type = SIDE_DYNAMIC_TYPE_VLA, \
1061 .u = { \
1062 .side_dynamic_vla = (_vla), \
1063 }, \
1064 }
1065
1066 #define side_arg_dynamic_vla_visitor(_dynamic_vla_visitor, _ctx, _attr) \
1067 { \
1068 .dynamic_type = SIDE_DYNAMIC_TYPE_VLA_VISITOR, \
1069 .u = { \
1070 .side_dynamic_vla_visitor = { \
1071 .app_ctx = _ctx, \
1072 .visitor = _dynamic_vla_visitor, \
1073 .attr = _attr, \
1074 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1075 }, \
1076 }, \
1077 }
1078
1079 #define side_arg_dynamic_struct(_struct) \
1080 { \
1081 .dynamic_type = SIDE_DYNAMIC_TYPE_STRUCT, \
1082 .u = { \
1083 .side_dynamic_struct = (_struct), \
1084 }, \
1085 }
1086
1087 #define side_arg_dynamic_struct_visitor(_dynamic_struct_visitor, _ctx, _attr) \
1088 { \
1089 .dynamic_type = SIDE_DYNAMIC_TYPE_STRUCT_VISITOR, \
1090 .u = { \
1091 .side_dynamic_struct_visitor = { \
1092 .app_ctx = _ctx, \
1093 .visitor = _dynamic_struct_visitor, \
1094 .attr = _attr, \
1095 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1096 }, \
1097 }, \
1098 }
1099
1100 #define side_arg_dynamic_define_vec(_identifier, _sav, _attr) \
1101 const struct side_arg_dynamic_vec _identifier##_vec[] = { _sav }; \
1102 const struct side_arg_dynamic_vec_vla _identifier = { \
1103 .sav = _identifier##_vec, \
1104 .attr = _attr, \
1105 .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
1106 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1107 }
1108
1109 #define side_arg_dynamic_define_struct(_identifier, _struct_fields, _attr) \
1110 const struct side_arg_dynamic_event_field _identifier##_fields[] = { _struct_fields }; \
1111 const struct side_arg_dynamic_event_struct _identifier = { \
1112 .fields = _identifier##_fields, \
1113 .attr = _attr, \
1114 .len = SIDE_ARRAY_SIZE(_identifier##_fields), \
1115 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1116 }
1117
1118 #define side_arg_define_vec(_identifier, _sav) \
1119 const struct side_arg_vec _identifier##_vec[] = { _sav }; \
1120 const struct side_arg_vec_description _identifier = { \
1121 .sav = _identifier##_vec, \
1122 .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
1123 }
1124
1125 #define side_arg_dynamic_field(_name, _elem) \
1126 { \
1127 .field_name = _name, \
1128 .elem = _elem, \
1129 }
1130
1131 #define side_arg_list(...) __VA_ARGS__
1132
1133 #define side_define_enum(_identifier, _mappings, _attr) \
1134 const struct side_enum_mappings _identifier = { \
1135 .mappings = _mappings, \
1136 .attr = _attr, \
1137 .nr_mappings = SIDE_ARRAY_SIZE(SIDE_PARAM(_mappings)), \
1138 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1139 }
1140
1141 #define side_enum_mapping_list(...) \
1142 SIDE_COMPOUND_LITERAL(const struct side_enum_mapping, __VA_ARGS__)
1143
1144 #define side_enum_mapping_range(_label, _begin, _end) \
1145 { \
1146 .range_begin = _begin, \
1147 .range_end = _end, \
1148 .label = _label, \
1149 }
1150
1151 #define side_enum_mapping_value(_label, _value) \
1152 { \
1153 .range_begin = _value, \
1154 .range_end = _value, \
1155 .label = _label, \
1156 }
1157
1158 #define side_define_enum_bitmap(_identifier, _mappings, _attr) \
1159 const struct side_enum_bitmap_mappings _identifier = { \
1160 .mappings = _mappings, \
1161 .attr = _attr, \
1162 .nr_mappings = SIDE_ARRAY_SIZE(SIDE_PARAM(_mappings)), \
1163 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1164 }
1165
1166 #define side_enum_bitmap_mapping_list(...) \
1167 SIDE_COMPOUND_LITERAL(const struct side_enum_bitmap_mapping, __VA_ARGS__)
1168
1169 #define side_enum_bitmap_mapping_range(_label, _begin, _end) \
1170 { \
1171 .range_begin = _begin, \
1172 .range_end = _end, \
1173 .label = _label, \
1174 }
1175
1176 #define side_enum_bitmap_mapping_value(_label, _value) \
1177 { \
1178 .range_begin = _value, \
1179 .range_end = _value, \
1180 .label = _label, \
1181 }
1182
1183 #define side_event_cond(_identifier) \
1184 if (side_unlikely(__atomic_load_n(&side_event_enable__##_identifier, \
1185 __ATOMIC_RELAXED)))
1186
1187 #define side_event_call(_identifier, _sav) \
1188 { \
1189 const struct side_arg_vec side_sav[] = { _sav }; \
1190 const struct side_arg_vec_description sav_desc = { \
1191 .sav = side_sav, \
1192 .len = SIDE_ARRAY_SIZE(side_sav), \
1193 }; \
1194 side_call(&(_identifier), &sav_desc); \
1195 }
1196
1197 #define side_event(_identifier, _sav) \
1198 side_event_cond(_identifier) \
1199 side_event_call(_identifier, SIDE_PARAM(_sav))
1200
1201 #define side_event_call_variadic(_identifier, _sav, _var_fields, _attr) \
1202 { \
1203 const struct side_arg_vec side_sav[] = { _sav }; \
1204 const struct side_arg_vec_description sav_desc = { \
1205 .sav = side_sav, \
1206 .len = SIDE_ARRAY_SIZE(side_sav), \
1207 }; \
1208 const struct side_arg_dynamic_event_field side_fields[] = { _var_fields }; \
1209 const struct side_arg_dynamic_event_struct var_struct = { \
1210 .fields = side_fields, \
1211 .attr = _attr, \
1212 .len = SIDE_ARRAY_SIZE(side_fields), \
1213 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1214 }; \
1215 side_call_variadic(&(_identifier), &sav_desc, &var_struct); \
1216 }
1217
1218 #define side_event_variadic(_identifier, _sav, _var, _attr) \
1219 side_event_cond(_identifier) \
1220 side_event_call_variadic(_identifier, SIDE_PARAM(_sav), SIDE_PARAM(_var), SIDE_PARAM(_attr))
1221
1222 #define _side_define_event(_linkage, _identifier, _provider, _event, _loglevel, _fields, _attr, _flags) \
1223 _linkage uintptr_t side_event_enable__##_identifier __attribute__((section("side_event_enable"))); \
1224 _linkage struct side_event_description __attribute__((section("side_event_description"))) \
1225 _identifier = { \
1226 .version = 0, \
1227 .enabled = &(side_event_enable__##_identifier), \
1228 .loglevel = _loglevel, \
1229 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
1230 .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
1231 .nr_callbacks = 0, \
1232 .flags = (_flags), \
1233 .provider_name = _provider, \
1234 .event_name = _event, \
1235 .fields = _fields, \
1236 .attr = _attr, \
1237 .callbacks = &side_empty_callback, \
1238 }; \
1239 static const struct side_event_description *side_event_ptr__##_identifier \
1240 __attribute__((section("side_event_description_ptr"), used)) = &(_identifier);
1241
1242 #define side_static_event(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1243 _side_define_event(static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1244 SIDE_PARAM(_attr), 0)
1245
1246 #define side_static_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1247 _side_define_event(static, _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1248 SIDE_PARAM(_attr), SIDE_EVENT_FLAG_VARIADIC)
1249
1250 #define side_hidden_event(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1251 _side_define_event(__attribute__((visibility("hidden"))), _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1252 SIDE_PARAM(_attr), 0)
1253
1254 #define side_hidden_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1255 _side_define_event(__attribute__((visibility("hidden"))), _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1256 SIDE_PARAM(_attr), SIDE_EVENT_FLAG_VARIADIC)
1257
1258 #define side_export_event(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1259 _side_define_event(__attribute__((visibility("default"))), _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1260 SIDE_PARAM(_attr), 0)
1261
1262 #define side_export_event_variadic(_identifier, _provider, _event, _loglevel, _fields, _attr) \
1263 _side_define_event(__attribute__((visibility("default"))), _identifier, _provider, _event, _loglevel, SIDE_PARAM(_fields), \
1264 SIDE_PARAM(_attr), SIDE_EVENT_FLAG_VARIADIC)
1265
1266 #define side_declare_event(_identifier) \
1267 extern uintptr_t side_event_enable_##_identifier; \
1268 extern struct side_event_description _identifier
1269
1270 extern const struct side_callback side_empty_callback;
1271
1272 void side_call(const struct side_event_description *desc,
1273 const struct side_arg_vec_description *sav_desc);
1274 void side_call_variadic(const struct side_event_description *desc,
1275 const struct side_arg_vec_description *sav_desc,
1276 const struct side_arg_dynamic_event_struct *var_struct);
1277
1278 int side_tracer_callback_register(struct side_event_description *desc,
1279 void (*call)(const struct side_event_description *desc,
1280 const struct side_arg_vec_description *sav_desc,
1281 void *priv),
1282 void *priv);
1283 int side_tracer_callback_variadic_register(struct side_event_description *desc,
1284 void (*call_variadic)(const struct side_event_description *desc,
1285 const struct side_arg_vec_description *sav_desc,
1286 const struct side_arg_dynamic_event_struct *var_struct,
1287 void *priv),
1288 void *priv);
1289 int side_tracer_callback_unregister(struct side_event_description *desc,
1290 void (*call)(const struct side_event_description *desc,
1291 const struct side_arg_vec_description *sav_desc,
1292 void *priv),
1293 void *priv);
1294 int side_tracer_callback_variadic_unregister(struct side_event_description *desc,
1295 void (*call_variadic)(const struct side_event_description *desc,
1296 const struct side_arg_vec_description *sav_desc,
1297 const struct side_arg_dynamic_event_struct *var_struct,
1298 void *priv),
1299 void *priv);
1300
1301 struct side_events_register_handle *side_events_register(struct side_event_description **events, uint32_t nr_events);
1302 void side_events_unregister(struct side_events_register_handle *handle);
1303
1304 enum side_tracer_notification {
1305 SIDE_TRACER_NOTIFICATION_INSERT_EVENTS,
1306 SIDE_TRACER_NOTIFICATION_REMOVE_EVENTS,
1307 };
1308
1309 /* Callback is invoked with side library internal lock held. */
1310 struct side_tracer_handle *side_tracer_event_notification_register(
1311 void (*cb)(enum side_tracer_notification notif,
1312 struct side_event_description **events, uint32_t nr_events, void *priv),
1313 void *priv);
1314 void side_tracer_event_notification_unregister(struct side_tracer_handle *handle);
1315
1316 void side_init(void);
1317 void side_exit(void);
1318
1319 /*
1320 * These weak symbols, the constructor, and destructor take care of
1321 * registering only _one_ instance of the side instrumentation per
1322 * shared-ojbect (or for the whole main program).
1323 */
1324 extern struct side_event_description * __start_side_event_description_ptr[]
1325 __attribute__((weak, visibility("hidden")));
1326 extern struct side_event_description * __stop_side_event_description_ptr[]
1327 __attribute__((weak, visibility("hidden")));
1328 int side_event_description_ptr_registered
1329 __attribute__((weak, visibility("hidden")));
1330 struct side_events_register_handle *side_events_handle
1331 __attribute__((weak, visibility("hidden")));
1332
1333 static void
1334 side_event_description_ptr_init(void)
1335 __attribute__((no_instrument_function))
1336 __attribute__((constructor));
1337 static void
1338 side_event_description_ptr_init(void)
1339 {
1340 if (side_event_description_ptr_registered++)
1341 return;
1342 side_events_handle = side_events_register(__start_side_event_description_ptr,
1343 __stop_side_event_description_ptr - __start_side_event_description_ptr);
1344 }
1345
1346 static void
1347 side_event_description_ptr_exit(void)
1348 __attribute__((no_instrument_function))
1349 __attribute__((destructor));
1350 static void
1351 side_event_description_ptr_exit(void)
1352 {
1353 if (--side_event_description_ptr_registered)
1354 return;
1355 side_events_unregister(side_events_handle);
1356 side_events_handle = NULL;
1357 }
1358
1359 #endif /* _SIDE_TRACE_H */
This page took 0.103901 seconds and 4 git commands to generate.