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