1 /* SPDX-License-Identifier: LGPL-2.1-only
2 * SPDX-FileCopyrightText: 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
8 #define MSGPACK_FIXSTR_ID_MASK 0xA0
9 #define MSGPACK_FIXMAP_ID_MASK 0x80
10 #define MSGPACK_FIXARRAY_ID_MASK 0x90
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
18 #define MSGPACK_UINT8_ID 0xCC
19 #define MSGPACK_UINT16_ID 0xCD
20 #define MSGPACK_UINT32_ID 0xCE
21 #define MSGPACK_UINT64_ID 0xCF
23 #define MSGPACK_INT8_ID 0xD0
24 #define MSGPACK_INT16_ID 0xD1
25 #define MSGPACK_INT32_ID 0xD2
26 #define MSGPACK_INT64_ID 0xD3
28 #define MSGPACK_FLOAT64_ID 0xCB
29 #define MSGPACK_STR16_ID 0xDA
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
38 #include <linux/bug.h>
39 #include <linux/string.h>
40 #include <linux/types.h>
41 #include <asm/byteorder.h>
43 #include <lttng/msgpack.h>
44 #include <lttng/probe-user.h>
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)
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)
60 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
62 #else /* __KERNEL__ */
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)
74 #define lttng_msgpack_assert(cond) ({ \
76 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
78 #endif /* __KERNEL__ */
80 static inline int lttng_msgpack_append_buffer(
81 struct lttng_msgpack_writer
*writer
,
87 lttng_msgpack_assert(buf
);
89 /* Ensure we are not trying to write after the end of the buffer. */
90 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
95 memcpy(writer
->write_pos
, buf
, length
);
96 writer
->write_pos
+= length
;
101 static inline int lttng_msgpack_append_user_buffer(
102 struct lttng_msgpack_writer
*writer
,
103 const uint8_t __user
*ubuf
,
108 lttng_msgpack_assert(ubuf
);
110 /* Ensure we are not trying to write after the end of the buffer. */
111 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
116 if (lttng_copy_from_user_check_nofault(writer
->write_pos
, ubuf
, length
)) {
120 writer
->write_pos
+= length
;
125 static inline int lttng_msgpack_append_u8(
126 struct lttng_msgpack_writer
*writer
, uint8_t value
)
128 return lttng_msgpack_append_buffer(writer
, &value
, sizeof(value
));
131 static inline int lttng_msgpack_append_u16(
132 struct lttng_msgpack_writer
*writer
, uint16_t value
)
134 value
= byteswap_host_to_be16(value
);
136 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
139 static inline int lttng_msgpack_append_u32(
140 struct lttng_msgpack_writer
*writer
, uint32_t value
)
142 value
= byteswap_host_to_be32(value
);
144 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
147 static inline int lttng_msgpack_append_u64(
148 struct lttng_msgpack_writer
*writer
, uint64_t value
)
150 value
= byteswap_host_to_be64(value
);
152 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
155 static inline int lttng_msgpack_append_i8(
156 struct lttng_msgpack_writer
*writer
, int8_t value
)
158 return lttng_msgpack_append_u8(writer
, (uint8_t) value
);
161 static inline int lttng_msgpack_append_i16(
162 struct lttng_msgpack_writer
*writer
, int16_t value
)
164 return lttng_msgpack_append_u16(writer
, (uint16_t) value
);
167 static inline int lttng_msgpack_append_i32(
168 struct lttng_msgpack_writer
*writer
, int32_t value
)
170 return lttng_msgpack_append_u32(writer
, (uint32_t) value
);
173 static inline int lttng_msgpack_append_i64(
174 struct lttng_msgpack_writer
*writer
, int64_t value
)
176 return lttng_msgpack_append_u64(writer
, (uint64_t) value
);
179 static inline int lttng_msgpack_encode_fixmap(
180 struct lttng_msgpack_writer
*writer
, uint8_t count
)
184 lttng_msgpack_assert(count
<= MSGPACK_FIXMAP_MAX_COUNT
);
186 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXMAP_ID_MASK
| count
);
194 static inline int lttng_msgpack_encode_map16(
195 struct lttng_msgpack_writer
*writer
, uint16_t count
)
199 lttng_msgpack_assert(count
> MSGPACK_FIXMAP_MAX_COUNT
);
201 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_MAP16_ID
);
205 ret
= lttng_msgpack_append_u16(writer
, count
);
213 static inline int lttng_msgpack_encode_fixarray(
214 struct lttng_msgpack_writer
*writer
, uint8_t count
)
218 lttng_msgpack_assert(count
<= MSGPACK_FIXARRAY_MAX_COUNT
);
220 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXARRAY_ID_MASK
| count
);
228 static inline int lttng_msgpack_encode_array16(
229 struct lttng_msgpack_writer
*writer
, uint16_t count
)
233 lttng_msgpack_assert(count
> MSGPACK_FIXARRAY_MAX_COUNT
);
235 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_ARRAY16_ID
);
239 ret
= lttng_msgpack_append_u16(writer
, count
);
247 static inline int lttng_msgpack_encode_fixstr(
248 struct lttng_msgpack_writer
*writer
,
254 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
256 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
260 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
268 static inline int lttng_msgpack_encode_str16(
269 struct lttng_msgpack_writer
*writer
,
275 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
277 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
281 ret
= lttng_msgpack_append_u16(writer
, len
);
285 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
293 static inline int lttng_msgpack_encode_user_fixstr(
294 struct lttng_msgpack_writer
*writer
,
295 const char __user
*ustr
,
300 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
302 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
306 ret
= lttng_msgpack_append_user_buffer(writer
, (uint8_t __user
*) ustr
, len
);
314 static inline int lttng_msgpack_encode_user_str16(
315 struct lttng_msgpack_writer
*writer
,
316 const char __user
*ustr
,
321 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
323 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
327 ret
= lttng_msgpack_append_u16(writer
, len
);
331 ret
= lttng_msgpack_append_user_buffer(writer
, (uint8_t __user
*) ustr
, len
);
340 int lttng_msgpack_begin_map(struct lttng_msgpack_writer
*writer
, size_t count
)
344 if (count
>= (1 << 16)) {
349 if (count
<= MSGPACK_FIXMAP_MAX_COUNT
)
350 ret
= lttng_msgpack_encode_fixmap(writer
, count
);
352 ret
= lttng_msgpack_encode_map16(writer
, count
);
354 writer
->map_nesting
++;
359 int lttng_msgpack_end_map(struct lttng_msgpack_writer
*writer
)
361 lttng_msgpack_assert(writer
->map_nesting
> 0);
362 writer
->map_nesting
--;
366 int lttng_msgpack_begin_array(
367 struct lttng_msgpack_writer
*writer
, size_t count
)
371 if (count
>= (1 << 16)) {
376 if (count
<= MSGPACK_FIXARRAY_MAX_COUNT
)
377 ret
= lttng_msgpack_encode_fixarray(writer
, count
);
379 ret
= lttng_msgpack_encode_array16(writer
, count
);
381 writer
->array_nesting
++;
386 int lttng_msgpack_end_array(struct lttng_msgpack_writer
*writer
)
388 lttng_msgpack_assert(writer
->array_nesting
> 0);
389 writer
->array_nesting
--;
393 int lttng_msgpack_write_str(struct lttng_msgpack_writer
*writer
,
397 size_t length
= strlen(str
);
399 if (length
>= (1 << 16)) {
404 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
405 ret
= lttng_msgpack_encode_fixstr(writer
, str
, length
);
407 ret
= lttng_msgpack_encode_str16(writer
, str
, length
);
414 * Provide the same behavior on lttng_strlen_user_inatomic page fault as the
415 * lttng ring buffer: truncate the last string character.
417 int lttng_msgpack_write_user_str(struct lttng_msgpack_writer
*writer
,
418 const char __user
*ustr
)
421 size_t length
= max_t(size_t, lttng_strlen_user_inatomic(ustr
), 1);
423 if (length
>= (1 << 16)) {
428 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
429 ret
= lttng_msgpack_encode_user_fixstr(writer
, ustr
, length
);
431 ret
= lttng_msgpack_encode_user_str16(writer
, ustr
, length
);
437 int lttng_msgpack_write_nil(struct lttng_msgpack_writer
*writer
)
439 return lttng_msgpack_append_u8(writer
, MSGPACK_NIL_ID
);
442 int lttng_msgpack_write_true(struct lttng_msgpack_writer
*writer
)
444 return lttng_msgpack_append_u8(writer
, MSGPACK_TRUE_ID
);
447 int lttng_msgpack_write_false(struct lttng_msgpack_writer
*writer
)
449 return lttng_msgpack_append_u8(writer
, MSGPACK_FALSE_ID
);
452 int lttng_msgpack_write_unsigned_integer(
453 struct lttng_msgpack_writer
*writer
, uint64_t value
)
457 if (value
<= MSGPACK_FIXINT_MAX
) {
458 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
461 } else if (value
<= UINT8_MAX
) {
462 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT8_ID
);
466 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
469 } else if (value
<= UINT16_MAX
) {
470 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT16_ID
);
474 ret
= lttng_msgpack_append_u16(writer
, (uint16_t) value
);
477 } else if (value
<= UINT32_MAX
) {
478 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT32_ID
);
482 ret
= lttng_msgpack_append_u32(writer
, (uint32_t) value
);
486 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT64_ID
);
490 ret
= lttng_msgpack_append_u64(writer
, value
);
499 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer
*writer
, int64_t value
)
503 if (value
>= MSGPACK_FIXINT_MIN
&& value
<= MSGPACK_FIXINT_MAX
){
504 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
507 } else if (value
>= INT8_MIN
&& value
<= INT8_MAX
) {
508 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT8_ID
);
512 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
515 } else if (value
>= INT16_MIN
&& value
<= INT16_MAX
) {
516 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT16_ID
);
520 ret
= lttng_msgpack_append_i16(writer
, (int16_t) value
);
523 } else if (value
>= INT32_MIN
&& value
<= INT32_MAX
) {
524 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT32_ID
);
528 ret
= lttng_msgpack_append_i32(writer
, (int32_t) value
);
532 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT64_ID
);
536 ret
= lttng_msgpack_append_i64(writer
, value
);
545 int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer
*writer
, uint8_t **pos
)
547 *pos
= writer
->write_pos
;
551 int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer
*writer
, uint8_t *pos
)
553 writer
->write_pos
= pos
;
557 void lttng_msgpack_writer_init(struct lttng_msgpack_writer
*writer
,
558 uint8_t *buffer
, size_t size
)
560 lttng_msgpack_assert(buffer
);
561 lttng_msgpack_assert(size
>= 0);
563 writer
->buffer
= buffer
;
564 writer
->write_pos
= buffer
;
565 writer
->end_write_pos
= buffer
+ size
;
567 writer
->array_nesting
= 0;
568 writer
->map_nesting
= 0;
571 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer
*writer
)
573 memset(writer
, 0, sizeof(*writer
));