4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; only
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #define MSGPACK_FIXSTR_ID_MASK 0xA0
25 #define MSGPACK_FIXMAP_ID_MASK 0x80
26 #define MSGPACK_FIXARRAY_ID_MASK 0x90
28 #define MSGPACK_NIL_ID 0xC0
29 #define MSGPACK_FALSE_ID 0xC2
30 #define MSGPACK_TRUE_ID 0xC3
31 #define MSGPACK_MAP16_ID 0xDE
32 #define MSGPACK_ARRAY16_ID 0xDC
34 #define MSGPACK_UINT8_ID 0xCC
35 #define MSGPACK_UINT16_ID 0xCD
36 #define MSGPACK_UINT32_ID 0xCE
37 #define MSGPACK_UINT64_ID 0xCF
39 #define MSGPACK_INT8_ID 0xD0
40 #define MSGPACK_INT16_ID 0xD1
41 #define MSGPACK_INT32_ID 0xD2
42 #define MSGPACK_INT64_ID 0xD3
44 #define MSGPACK_FLOAT64_ID 0xCB
45 #define MSGPACK_STR16_ID 0xDA
47 #define MSGPACK_FIXINT_MAX ((1 << 7) - 1)
48 #define MSGPACK_FIXINT_MIN -(1 << 5)
49 #define MSGPACK_FIXMAP_MAX_COUNT 15
50 #define MSGPACK_FIXARRAY_MAX_COUNT 15
51 #define MSGPACK_FIXSTR_MAX_LENGTH 31
54 #include <linux/bug.h>
55 #include <linux/string.h>
56 #include <linux/types.h>
57 #include <asm/byteorder.h>
59 #include <lttng/msgpack.h>
60 #include <lttng/probe-user.h>
62 #define INT8_MIN (-128)
63 #define INT16_MIN (-32767-1)
64 #define INT32_MIN (-2147483647-1)
65 #define INT8_MAX (127)
66 #define INT16_MAX (32767)
67 #define INT32_MAX (2147483647)
68 #define UINT8_MAX (255)
69 #define UINT16_MAX (65535)
70 #define UINT32_MAX (4294967295U)
72 #define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
73 #define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
74 #define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
76 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
78 #else /* __KERNEL__ */
86 #define byteswap_host_to_be16(_tmp) htobe16(_tmp)
87 #define byteswap_host_to_be32(_tmp) htobe32(_tmp)
88 #define byteswap_host_to_be64(_tmp) htobe64(_tmp)
90 #define lttng_msgpack_assert(cond) ({ \
92 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
94 #endif /* __KERNEL__ */
96 static inline int lttng_msgpack_append_buffer(
97 struct lttng_msgpack_writer
*writer
,
103 lttng_msgpack_assert(buf
);
105 /* Ensure we are not trying to write after the end of the buffer. */
106 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
111 memcpy(writer
->write_pos
, buf
, length
);
112 writer
->write_pos
+= length
;
117 static inline int lttng_msgpack_append_user_buffer(
118 struct lttng_msgpack_writer
*writer
,
119 const uint8_t __user
*ubuf
,
124 lttng_msgpack_assert(ubuf
);
126 /* Ensure we are not trying to write after the end of the buffer. */
127 if (writer
->write_pos
+ length
> writer
->end_write_pos
) {
132 if (lttng_copy_from_user_check_nofault(writer
->write_pos
, ubuf
, length
)) {
134 * After a successful strlen user, a page fault on copy is handled by
135 * considering the string as empty, returning a success.
139 writer
->write_pos
+= length
;
144 static inline int lttng_msgpack_append_u8(
145 struct lttng_msgpack_writer
*writer
, uint8_t value
)
147 return lttng_msgpack_append_buffer(writer
, &value
, sizeof(value
));
150 static inline int lttng_msgpack_append_u16(
151 struct lttng_msgpack_writer
*writer
, uint16_t value
)
153 value
= byteswap_host_to_be16(value
);
155 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
158 static inline int lttng_msgpack_append_u32(
159 struct lttng_msgpack_writer
*writer
, uint32_t value
)
161 value
= byteswap_host_to_be32(value
);
163 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
166 static inline int lttng_msgpack_append_u64(
167 struct lttng_msgpack_writer
*writer
, uint64_t value
)
169 value
= byteswap_host_to_be64(value
);
171 return lttng_msgpack_append_buffer(writer
, (uint8_t *) &value
, sizeof(value
));
174 static inline int lttng_msgpack_append_i8(
175 struct lttng_msgpack_writer
*writer
, int8_t value
)
177 return lttng_msgpack_append_u8(writer
, (uint8_t) value
);
180 static inline int lttng_msgpack_append_i16(
181 struct lttng_msgpack_writer
*writer
, int16_t value
)
183 return lttng_msgpack_append_u16(writer
, (uint16_t) value
);
186 static inline int lttng_msgpack_append_i32(
187 struct lttng_msgpack_writer
*writer
, int32_t value
)
189 return lttng_msgpack_append_u32(writer
, (uint32_t) value
);
192 static inline int lttng_msgpack_append_i64(
193 struct lttng_msgpack_writer
*writer
, int64_t value
)
195 return lttng_msgpack_append_u64(writer
, (uint64_t) value
);
198 static inline int lttng_msgpack_encode_fixmap(
199 struct lttng_msgpack_writer
*writer
, uint8_t count
)
203 lttng_msgpack_assert(count
<= MSGPACK_FIXMAP_MAX_COUNT
);
205 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXMAP_ID_MASK
| count
);
213 static inline int lttng_msgpack_encode_map16(
214 struct lttng_msgpack_writer
*writer
, uint16_t count
)
218 lttng_msgpack_assert(count
> MSGPACK_FIXMAP_MAX_COUNT
);
220 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_MAP16_ID
);
224 ret
= lttng_msgpack_append_u16(writer
, count
);
232 static inline int lttng_msgpack_encode_fixarray(
233 struct lttng_msgpack_writer
*writer
, uint8_t count
)
237 lttng_msgpack_assert(count
<= MSGPACK_FIXARRAY_MAX_COUNT
);
239 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXARRAY_ID_MASK
| count
);
247 static inline int lttng_msgpack_encode_array16(
248 struct lttng_msgpack_writer
*writer
, uint16_t count
)
252 lttng_msgpack_assert(count
> MSGPACK_FIXARRAY_MAX_COUNT
);
254 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_ARRAY16_ID
);
258 ret
= lttng_msgpack_append_u16(writer
, count
);
266 static inline int lttng_msgpack_encode_fixstr(
267 struct lttng_msgpack_writer
*writer
,
273 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
275 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
279 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
287 static inline int lttng_msgpack_encode_str16(
288 struct lttng_msgpack_writer
*writer
,
294 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
296 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
300 ret
= lttng_msgpack_append_u16(writer
, len
);
304 ret
= lttng_msgpack_append_buffer(writer
, (uint8_t *) str
, len
);
312 static inline int lttng_msgpack_encode_user_fixstr(
313 struct lttng_msgpack_writer
*writer
,
314 const char __user
*ustr
,
319 lttng_msgpack_assert(len
<= MSGPACK_FIXSTR_MAX_LENGTH
);
321 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_FIXSTR_ID_MASK
| len
);
325 ret
= lttng_msgpack_append_user_buffer(writer
, (uint8_t __user
*) ustr
, len
);
333 static inline int lttng_msgpack_encode_user_str16(
334 struct lttng_msgpack_writer
*writer
,
335 const char __user
*ustr
,
340 lttng_msgpack_assert(len
> MSGPACK_FIXSTR_MAX_LENGTH
);
342 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_STR16_ID
);
346 ret
= lttng_msgpack_append_u16(writer
, len
);
350 ret
= lttng_msgpack_append_user_buffer(writer
, (uint8_t __user
*) ustr
, len
);
359 int lttng_msgpack_begin_map(struct lttng_msgpack_writer
*writer
, size_t count
)
363 if (count
>= (1 << 16)) {
368 if (count
<= MSGPACK_FIXMAP_MAX_COUNT
)
369 ret
= lttng_msgpack_encode_fixmap(writer
, count
);
371 ret
= lttng_msgpack_encode_map16(writer
, count
);
373 writer
->map_nesting
++;
378 int lttng_msgpack_end_map(struct lttng_msgpack_writer
*writer
)
380 lttng_msgpack_assert(writer
->map_nesting
> 0);
381 writer
->map_nesting
--;
385 int lttng_msgpack_begin_array(
386 struct lttng_msgpack_writer
*writer
, size_t count
)
390 if (count
>= (1 << 16)) {
395 if (count
<= MSGPACK_FIXARRAY_MAX_COUNT
)
396 ret
= lttng_msgpack_encode_fixarray(writer
, count
);
398 ret
= lttng_msgpack_encode_array16(writer
, count
);
400 writer
->array_nesting
++;
405 int lttng_msgpack_end_array(struct lttng_msgpack_writer
*writer
)
407 lttng_msgpack_assert(writer
->array_nesting
> 0);
408 writer
->array_nesting
--;
412 int lttng_msgpack_write_str(struct lttng_msgpack_writer
*writer
,
416 size_t length
= strlen(str
);
418 if (length
>= (1 << 16)) {
423 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
424 ret
= lttng_msgpack_encode_fixstr(writer
, str
, length
);
426 ret
= lttng_msgpack_encode_str16(writer
, str
, length
);
433 * Provide the same behavior on lttng_strlen_user_inatomic page fault as the
434 * lttng ring buffer: truncate the last string character.
436 int lttng_msgpack_write_user_str(struct lttng_msgpack_writer
*writer
,
437 const char __user
*ustr
)
440 size_t length
= max_t(size_t, lttng_strlen_user_inatomic(ustr
), 1);
442 if (length
>= (1 << 16)) {
448 * Handle empty string and strlen user page fault as empty string.
451 return lttng_msgpack_write_str(writer
, "");
453 if (length
<= MSGPACK_FIXSTR_MAX_LENGTH
)
454 ret
= lttng_msgpack_encode_user_fixstr(writer
, ustr
, length
);
456 ret
= lttng_msgpack_encode_user_str16(writer
, ustr
, length
);
462 int lttng_msgpack_write_nil(struct lttng_msgpack_writer
*writer
)
464 return lttng_msgpack_append_u8(writer
, MSGPACK_NIL_ID
);
467 int lttng_msgpack_write_true(struct lttng_msgpack_writer
*writer
)
469 return lttng_msgpack_append_u8(writer
, MSGPACK_TRUE_ID
);
472 int lttng_msgpack_write_false(struct lttng_msgpack_writer
*writer
)
474 return lttng_msgpack_append_u8(writer
, MSGPACK_FALSE_ID
);
477 int lttng_msgpack_write_unsigned_integer(
478 struct lttng_msgpack_writer
*writer
, uint64_t value
)
482 if (value
<= MSGPACK_FIXINT_MAX
) {
483 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
486 } else if (value
<= UINT8_MAX
) {
487 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT8_ID
);
491 ret
= lttng_msgpack_append_u8(writer
, (uint8_t) value
);
494 } else if (value
<= UINT16_MAX
) {
495 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT16_ID
);
499 ret
= lttng_msgpack_append_u16(writer
, (uint16_t) value
);
502 } else if (value
<= UINT32_MAX
) {
503 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT32_ID
);
507 ret
= lttng_msgpack_append_u32(writer
, (uint32_t) value
);
511 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_UINT64_ID
);
515 ret
= lttng_msgpack_append_u64(writer
, value
);
524 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer
*writer
, int64_t value
)
528 if (value
>= MSGPACK_FIXINT_MIN
&& value
<= MSGPACK_FIXINT_MAX
){
529 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
532 } else if (value
>= INT8_MIN
&& value
<= INT8_MAX
) {
533 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT8_ID
);
537 ret
= lttng_msgpack_append_i8(writer
, (int8_t) value
);
540 } else if (value
>= INT16_MIN
&& value
<= INT16_MAX
) {
541 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT16_ID
);
545 ret
= lttng_msgpack_append_i16(writer
, (int16_t) value
);
548 } else if (value
>= INT32_MIN
&& value
<= INT32_MAX
) {
549 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT32_ID
);
553 ret
= lttng_msgpack_append_i32(writer
, (int32_t) value
);
557 ret
= lttng_msgpack_append_u8(writer
, MSGPACK_INT64_ID
);
561 ret
= lttng_msgpack_append_i64(writer
, value
);
570 int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer
*writer
, uint8_t **pos
)
572 *pos
= writer
->write_pos
;
576 int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer
*writer
, uint8_t *pos
)
578 writer
->write_pos
= pos
;
582 void lttng_msgpack_writer_init(struct lttng_msgpack_writer
*writer
,
583 uint8_t *buffer
, size_t size
)
585 lttng_msgpack_assert(buffer
);
586 lttng_msgpack_assert(size
>= 0);
588 writer
->buffer
= buffer
;
589 writer
->write_pos
= buffer
;
590 writer
->end_write_pos
= buffer
+ size
;
592 writer
->array_nesting
= 0;
593 writer
->map_nesting
= 0;
596 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer
*writer
)
598 memset(writer
, 0, sizeof(*writer
));