Introduce extension points for trace hit counters
[lttng-modules.git] / src / lib / msgpack / msgpack.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-only
2 * SPDX-FileCopyrightText: 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
3 */
4
5#define _GNU_SOURCE
6#define _LGPL_SOURCE
7
8#define MSGPACK_FIXSTR_ID_MASK 0xA0
9#define MSGPACK_FIXMAP_ID_MASK 0x80
10#define MSGPACK_FIXARRAY_ID_MASK 0x90
11
12#define MSGPACK_NIL_ID 0xC0
13#define MSGPACK_FALSE_ID 0xC2
14#define MSGPACK_TRUE_ID 0xC3
15#define MSGPACK_MAP16_ID 0xDE
16#define MSGPACK_ARRAY16_ID 0xDC
17
18#define MSGPACK_UINT8_ID 0xCC
19#define MSGPACK_UINT16_ID 0xCD
20#define MSGPACK_UINT32_ID 0xCE
21#define MSGPACK_UINT64_ID 0xCF
22
23#define MSGPACK_INT8_ID 0xD0
24#define MSGPACK_INT16_ID 0xD1
25#define MSGPACK_INT32_ID 0xD2
26#define MSGPACK_INT64_ID 0xD3
27
28#define MSGPACK_FLOAT64_ID 0xCB
29#define MSGPACK_STR16_ID 0xDA
30
31#define MSGPACK_FIXINT_MAX ((1 << 7) - 1)
32#define MSGPACK_FIXINT_MIN -(1 << 5)
33#define MSGPACK_FIXMAP_MAX_COUNT 15
34#define MSGPACK_FIXARRAY_MAX_COUNT 15
35#define MSGPACK_FIXSTR_MAX_LENGTH 31
36
37#ifdef __KERNEL__
38#include <linux/bug.h>
39#include <linux/string.h>
40#include <linux/types.h>
41#include <asm/byteorder.h>
42
43#include <lttng/msgpack.h>
44#include <lttng/probe-user.h>
45
46#define INT8_MIN (-128)
47#define INT16_MIN (-32767-1)
48#define INT32_MIN (-2147483647-1)
49#define INT8_MAX (127)
50#define INT16_MAX (32767)
51#define INT32_MAX (2147483647)
52#define UINT8_MAX (255)
53#define UINT16_MAX (65535)
54#define UINT32_MAX (4294967295U)
55
56#define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
57#define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
58#define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
59
60#define lttng_msgpack_assert(cond) WARN_ON(!(cond))
61
62#else /* __KERNEL__ */
63
64#include <endian.h>
65#include <stdio.h>
66#include <string.h>
67
68#include "msgpack.h"
69
70#define byteswap_host_to_be16(_tmp) htobe16(_tmp)
71#define byteswap_host_to_be32(_tmp) htobe32(_tmp)
72#define byteswap_host_to_be64(_tmp) htobe64(_tmp)
73
74#define lttng_msgpack_assert(cond) ({ \
75 if (!(cond)) \
76 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
77 })
78#endif /* __KERNEL__ */
79
80static inline int lttng_msgpack_append_buffer(
81 struct lttng_msgpack_writer *writer,
82 const uint8_t *buf,
83 size_t length)
84{
85 int ret = 0;
86
87 lttng_msgpack_assert(buf);
88
89 /* Ensure we are not trying to write after the end of the buffer. */
90 if (writer->write_pos + length > writer->end_write_pos) {
91 ret = -1;
92 goto end;
93 }
94
95 memcpy(writer->write_pos, buf, length);
96 writer->write_pos += length;
97end:
98 return ret;
99}
100
101static inline int lttng_msgpack_append_user_buffer(
102 struct lttng_msgpack_writer *writer,
103 const uint8_t __user *ubuf,
104 size_t length)
105{
106 int ret = 0;
107
108 lttng_msgpack_assert(ubuf);
109
110 /* Ensure we are not trying to write after the end of the buffer. */
111 if (writer->write_pos + length > writer->end_write_pos) {
112 ret = -1;
113 goto end;
114 }
115
116 if (lttng_copy_from_user_check_nofault(writer->write_pos, ubuf, length)) {
117 ret = -1;
118 goto end;
119 }
120 writer->write_pos += length;
121end:
122 return ret;
123}
124
125static inline int lttng_msgpack_append_u8(
126 struct lttng_msgpack_writer *writer, uint8_t value)
127{
128 return lttng_msgpack_append_buffer(writer, &value, sizeof(value));
129}
130
131static inline int lttng_msgpack_append_u16(
132 struct lttng_msgpack_writer *writer, uint16_t value)
133{
134 value = byteswap_host_to_be16(value);
135
136 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
137}
138
139static inline int lttng_msgpack_append_u32(
140 struct lttng_msgpack_writer *writer, uint32_t value)
141{
142 value = byteswap_host_to_be32(value);
143
144 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
145}
146
147static inline int lttng_msgpack_append_u64(
148 struct lttng_msgpack_writer *writer, uint64_t value)
149{
150 value = byteswap_host_to_be64(value);
151
152 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
153}
154
155static inline int lttng_msgpack_append_i8(
156 struct lttng_msgpack_writer *writer, int8_t value)
157{
158 return lttng_msgpack_append_u8(writer, (uint8_t) value);
159}
160
161static inline int lttng_msgpack_append_i16(
162 struct lttng_msgpack_writer *writer, int16_t value)
163{
164 return lttng_msgpack_append_u16(writer, (uint16_t) value);
165}
166
167static inline int lttng_msgpack_append_i32(
168 struct lttng_msgpack_writer *writer, int32_t value)
169{
170 return lttng_msgpack_append_u32(writer, (uint32_t) value);
171}
172
173static inline int lttng_msgpack_append_i64(
174 struct lttng_msgpack_writer *writer, int64_t value)
175{
176 return lttng_msgpack_append_u64(writer, (uint64_t) value);
177}
178
179static inline int lttng_msgpack_encode_fixmap(
180 struct lttng_msgpack_writer *writer, uint8_t count)
181{
182 int ret = 0;
183
184 lttng_msgpack_assert(count <= MSGPACK_FIXMAP_MAX_COUNT);
185
186 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXMAP_ID_MASK | count);
187 if (ret)
188 goto end;
189
190end:
191 return ret;
192}
193
194static inline int lttng_msgpack_encode_map16(
195 struct lttng_msgpack_writer *writer, uint16_t count)
196{
197 int ret;
198
199 lttng_msgpack_assert(count > MSGPACK_FIXMAP_MAX_COUNT);
200
201 ret = lttng_msgpack_append_u8(writer, MSGPACK_MAP16_ID);
202 if (ret)
203 goto end;
204
205 ret = lttng_msgpack_append_u16(writer, count);
206 if (ret)
207 goto end;
208
209end:
210 return ret;
211}
212
213static inline int lttng_msgpack_encode_fixarray(
214 struct lttng_msgpack_writer *writer, uint8_t count)
215{
216 int ret = 0;
217
218 lttng_msgpack_assert(count <= MSGPACK_FIXARRAY_MAX_COUNT);
219
220 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXARRAY_ID_MASK | count);
221 if (ret)
222 goto end;
223
224end:
225 return ret;
226}
227
228static inline int lttng_msgpack_encode_array16(
229 struct lttng_msgpack_writer *writer, uint16_t count)
230{
231 int ret;
232
233 lttng_msgpack_assert(count > MSGPACK_FIXARRAY_MAX_COUNT);
234
235 ret = lttng_msgpack_append_u8(writer, MSGPACK_ARRAY16_ID);
236 if (ret)
237 goto end;
238
239 ret = lttng_msgpack_append_u16(writer, count);
240 if (ret)
241 goto end;
242
243end:
244 return ret;
245}
246
247static inline int lttng_msgpack_encode_fixstr(
248 struct lttng_msgpack_writer *writer,
249 const char *str,
250 uint8_t len)
251{
252 int ret;
253
254 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
255
256 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
257 if (ret)
258 goto end;
259
260 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
261 if (ret)
262 goto end;
263
264end:
265 return ret;
266}
267
268static inline int lttng_msgpack_encode_str16(
269 struct lttng_msgpack_writer *writer,
270 const char *str,
271 uint16_t len)
272{
273 int ret;
274
275 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
276
277 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
278 if (ret)
279 goto end;
280
281 ret = lttng_msgpack_append_u16(writer, len);
282 if (ret)
283 goto end;
284
285 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
286 if (ret)
287 goto end;
288
289end:
290 return ret;
291}
292
293static inline int lttng_msgpack_encode_user_fixstr(
294 struct lttng_msgpack_writer *writer,
295 const char __user *ustr,
296 uint8_t len)
297{
298 int ret;
299
300 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
301
302 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
303 if (ret)
304 goto end;
305
306 ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
307 if (ret)
308 goto end;
309
310end:
311 return ret;
312}
313
314static inline int lttng_msgpack_encode_user_str16(
315 struct lttng_msgpack_writer *writer,
316 const char __user *ustr,
317 uint16_t len)
318{
319 int ret;
320
321 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
322
323 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
324 if (ret)
325 goto end;
326
327 ret = lttng_msgpack_append_u16(writer, len);
328 if (ret)
329 goto end;
330
331 ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
332 if (ret)
333 goto end;
334
335end:
336 return ret;
337}
338
339
340int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
341{
342 int ret;
343
344 if (count >= (1 << 16)) {
345 ret = -1;
346 goto end;
347 }
348
349 if (count <= MSGPACK_FIXMAP_MAX_COUNT)
350 ret = lttng_msgpack_encode_fixmap(writer, count);
351 else
352 ret = lttng_msgpack_encode_map16(writer, count);
353
354 writer->map_nesting++;
355end:
356 return ret;
357}
358
359int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer)
360{
361 lttng_msgpack_assert(writer->map_nesting > 0);
362 writer->map_nesting--;
363 return 0;
364}
365
366int lttng_msgpack_begin_array(
367 struct lttng_msgpack_writer *writer, size_t count)
368{
369 int ret;
370
371 if (count >= (1 << 16)) {
372 ret = -1;
373 goto end;
374 }
375
376 if (count <= MSGPACK_FIXARRAY_MAX_COUNT)
377 ret = lttng_msgpack_encode_fixarray(writer, count);
378 else
379 ret = lttng_msgpack_encode_array16(writer, count);
380
381 writer->array_nesting++;
382end:
383 return ret;
384}
385
386int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
387{
388 lttng_msgpack_assert(writer->array_nesting > 0);
389 writer->array_nesting--;
390 return 0;
391}
392
393int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
394 const char *str)
395{
396 int ret;
397 size_t length = strlen(str);
398
399 if (length >= (1 << 16)) {
400 ret = -1;
401 goto end;
402 }
403
404 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
405 ret = lttng_msgpack_encode_fixstr(writer, str, length);
406 else
407 ret = lttng_msgpack_encode_str16(writer, str, length);
408
409end:
410 return ret;
411}
412
413/*
414 * Provide the same behavior on lttng_strlen_user_inatomic page fault as the
415 * lttng ring buffer: truncate the last string character.
416 */
417int lttng_msgpack_write_user_str(struct lttng_msgpack_writer *writer,
418 const char __user *ustr)
419{
420 int ret;
421 size_t length = max_t(size_t, lttng_strlen_user_inatomic(ustr), 1);
422
423 if (length >= (1 << 16)) {
424 ret = -1;
425 goto end;
426 }
427
428 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
429 ret = lttng_msgpack_encode_user_fixstr(writer, ustr, length);
430 else
431 ret = lttng_msgpack_encode_user_str16(writer, ustr, length);
432
433end:
434 return ret;
435}
436
437int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
438{
439 return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
440}
441
442int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
443{
444 return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
445}
446
447int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
448{
449 return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
450}
451
452int lttng_msgpack_write_unsigned_integer(
453 struct lttng_msgpack_writer *writer, uint64_t value)
454{
455 int ret = 0;
456
457 if (value <= MSGPACK_FIXINT_MAX) {
458 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
459 if (ret)
460 goto end;
461 } else if (value <= UINT8_MAX) {
462 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT8_ID);
463 if (ret)
464 goto end;
465
466 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
467 if (ret)
468 goto end;
469 } else if (value <= UINT16_MAX) {
470 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT16_ID);
471 if (ret)
472 goto end;
473
474 ret = lttng_msgpack_append_u16(writer, (uint16_t) value);
475 if (ret)
476 goto end;
477 } else if (value <= UINT32_MAX) {
478 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT32_ID);
479 if (ret)
480 goto end;
481
482 ret = lttng_msgpack_append_u32(writer, (uint32_t) value);
483 if (ret)
484 goto end;
485 } else {
486 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT64_ID);
487 if (ret)
488 goto end;
489
490 ret = lttng_msgpack_append_u64(writer, value);
491 if (ret)
492 goto end;
493 }
494
495end:
496 return ret;
497}
498
499int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer *writer, int64_t value)
500{
501 int ret;
502
503 if (value >= MSGPACK_FIXINT_MIN && value <= MSGPACK_FIXINT_MAX){
504 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
505 if (ret)
506 goto end;
507 } else if (value >= INT8_MIN && value <= INT8_MAX) {
508 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT8_ID);
509 if (ret)
510 goto end;
511
512 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
513 if (ret)
514 goto end;
515 } else if (value >= INT16_MIN && value <= INT16_MAX) {
516 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT16_ID);
517 if (ret)
518 goto end;
519
520 ret = lttng_msgpack_append_i16(writer, (int16_t) value);
521 if (ret)
522 goto end;
523 } else if (value >= INT32_MIN && value <= INT32_MAX) {
524 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT32_ID);
525 if (ret)
526 goto end;
527
528 ret = lttng_msgpack_append_i32(writer, (int32_t) value);
529 if (ret)
530 goto end;
531 } else {
532 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT64_ID);
533 if (ret)
534 goto end;
535
536 ret = lttng_msgpack_append_i64(writer, value);
537 if (ret)
538 goto end;
539 }
540
541end:
542 return ret;
543}
544
545int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer *writer, uint8_t **pos)
546{
547 *pos = writer->write_pos;
548 return 0;
549}
550
551int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer *writer, uint8_t *pos)
552{
553 writer->write_pos = pos;
554 return 0;
555}
556
557void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
558 uint8_t *buffer, size_t size)
559{
560 lttng_msgpack_assert(buffer);
561 lttng_msgpack_assert(size >= 0);
562
563 writer->buffer = buffer;
564 writer->write_pos = buffer;
565 writer->end_write_pos = buffer + size;
566
567 writer->array_nesting = 0;
568 writer->map_nesting = 0;
569}
570
571void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
572{
573 memset(writer, 0, sizeof(*writer));
574}
This page took 0.036293 seconds and 5 git commands to generate.