Filter: validate range overflow with end of insn
[lttng-ust.git] / liblttng-ust / lttng-filter.c
CommitLineData
2d78951a
MD
1/*
2 * lttng-filter.c
3 *
4 * LTTng UST filter code.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <errno.h>
24#include <stdio.h>
25#include <helper.h>
26#include <lttng/ust-events.h>
cd54f6d9
MD
27#include <stdint.h>
28#include <errno.h>
29#include <string.h>
30#include <inttypes.h>
31#include <limits.h>
b1caea50 32#include <usterr-signal-safe.h>
cd54f6d9
MD
33#include "filter-bytecode.h"
34
35#define NR_REG 2
36
37#ifndef min_t
38#define min_t(type, a, b) \
39 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
40#endif
41
42#ifndef likely
43#define likely(x) __builtin_expect(!!(x), 1)
44#endif
45
46#ifndef unlikely
47#define unlikely(x) __builtin_expect(!!(x), 0)
48#endif
49
50#ifdef DEBUG
51#define dbg_printf(fmt, args...) printf("[debug bytecode] " fmt, ## args)
52#else
53#define dbg_printf(fmt, args...) \
54do { \
55 /* do nothing but check printf format */ \
56 if (0) \
57 printf("[debug bytecode] " fmt, ## args); \
58} while (0)
59#endif
60
61/* Linked bytecode */
62struct bytecode_runtime {
63 uint16_t len;
64 char data[0];
65};
66
9522a886
MD
67enum reg_type {
68 REG_S64,
69 REG_DOUBLE,
70 REG_STRING,
225b6640 71 REG_TYPE_UNKNOWN,
9522a886
MD
72};
73
74/* Validation registers */
75struct vreg {
76 enum reg_type type;
77 int literal; /* is string literal ? */
78};
79
80/* Execution registers */
cd54f6d9 81struct reg {
9522a886 82 enum reg_type type;
cd54f6d9 83 int64_t v;
da6eed25 84 double d;
cd54f6d9
MD
85
86 const char *str;
87 size_t seq_len;
88 int literal; /* is string literal ? */
89};
90
91static const char *opnames[] = {
92 [ FILTER_OP_UNKNOWN ] = "UNKNOWN",
93
94 [ FILTER_OP_RETURN ] = "RETURN",
95
96 /* binary */
97 [ FILTER_OP_MUL ] = "MUL",
98 [ FILTER_OP_DIV ] = "DIV",
99 [ FILTER_OP_MOD ] = "MOD",
100 [ FILTER_OP_PLUS ] = "PLUS",
101 [ FILTER_OP_MINUS ] = "MINUS",
102 [ FILTER_OP_RSHIFT ] = "RSHIFT",
103 [ FILTER_OP_LSHIFT ] = "LSHIFT",
104 [ FILTER_OP_BIN_AND ] = "BIN_AND",
105 [ FILTER_OP_BIN_OR ] = "BIN_OR",
106 [ FILTER_OP_BIN_XOR ] = "BIN_XOR",
226106c0
MD
107
108 /* binary comparators */
cd54f6d9
MD
109 [ FILTER_OP_EQ ] = "EQ",
110 [ FILTER_OP_NE ] = "NE",
111 [ FILTER_OP_GT ] = "GT",
112 [ FILTER_OP_LT ] = "LT",
113 [ FILTER_OP_GE ] = "GE",
114 [ FILTER_OP_LE ] = "LE",
115
226106c0
MD
116 /* string binary comparators */
117 [ FILTER_OP_EQ_STRING ] = "EQ_STRING",
118 [ FILTER_OP_NE_STRING ] = "NE_STRING",
119 [ FILTER_OP_GT_STRING ] = "GT_STRING",
120 [ FILTER_OP_LT_STRING ] = "LT_STRING",
121 [ FILTER_OP_GE_STRING ] = "GE_STRING",
122 [ FILTER_OP_LE_STRING ] = "LE_STRING",
123
124 /* s64 binary comparators */
125 [ FILTER_OP_EQ_S64 ] = "EQ_S64",
126 [ FILTER_OP_NE_S64 ] = "NE_S64",
127 [ FILTER_OP_GT_S64 ] = "GT_S64",
128 [ FILTER_OP_LT_S64 ] = "LT_S64",
129 [ FILTER_OP_GE_S64 ] = "GE_S64",
130 [ FILTER_OP_LE_S64 ] = "LE_S64",
131
132 /* double binary comparators */
133 [ FILTER_OP_EQ_DOUBLE ] = "EQ_DOUBLE",
134 [ FILTER_OP_NE_DOUBLE ] = "NE_DOUBLE",
135 [ FILTER_OP_GT_DOUBLE ] = "GT_DOUBLE",
136 [ FILTER_OP_LT_DOUBLE ] = "LT_DOUBLE",
137 [ FILTER_OP_GE_DOUBLE ] = "GE_DOUBLE",
138 [ FILTER_OP_LE_DOUBLE ] = "LE_DOUBLE",
139
140
cd54f6d9
MD
141 /* unary */
142 [ FILTER_OP_UNARY_PLUS ] = "UNARY_PLUS",
143 [ FILTER_OP_UNARY_MINUS ] = "UNARY_MINUS",
144 [ FILTER_OP_UNARY_NOT ] = "UNARY_NOT",
226106c0
MD
145 [ FILTER_OP_UNARY_PLUS_S64 ] = "UNARY_PLUS_S64",
146 [ FILTER_OP_UNARY_MINUS_S64 ] = "UNARY_MINUS_S64",
147 [ FILTER_OP_UNARY_NOT_S64 ] = "UNARY_NOT_S64",
148 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = "UNARY_PLUS_DOUBLE",
149 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = "UNARY_MINUS_DOUBLE",
150 [ FILTER_OP_UNARY_NOT_DOUBLE ] = "UNARY_NOT_DOUBLE",
cd54f6d9
MD
151
152 /* logical */
153 [ FILTER_OP_AND ] = "AND",
154 [ FILTER_OP_OR ] = "OR",
155
156 /* load */
157 [ FILTER_OP_LOAD_FIELD_REF ] = "LOAD_FIELD_REF",
2f0145d1
MD
158 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = "LOAD_FIELD_REF_STRING",
159 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = "LOAD_FIELD_REF_SEQUENCE",
160 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = "LOAD_FIELD_REF_S64",
161 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = "LOAD_FIELD_REF_DOUBLE",
162
cd54f6d9
MD
163 [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
164 [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
da6eed25 165 [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
49905038
MD
166
167 /* cast */
168 [ FILTER_OP_CAST_TO_S64 ] = "CAST_TO_S64",
169 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = "CAST_DOUBLE_TO_S64",
170 [ FILTER_OP_CAST_NOP ] = "CAST_NOP",
cd54f6d9
MD
171};
172
173static
174const char *print_op(enum filter_op op)
175{
176 if (op >= NR_FILTER_OPS)
177 return "UNKNOWN";
178 else
179 return opnames[op];
180}
181
182/*
183 * -1: wildcard found.
184 * -2: unknown escape char.
185 * 0: normal char.
186 */
187
188static
189int parse_char(const char **p)
190{
191 switch (**p) {
192 case '\\':
193 (*p)++;
194 switch (**p) {
195 case '\\':
196 case '*':
197 return 0;
198 default:
199 return -2;
200 }
201 case '*':
202 return -1;
203 default:
204 return 0;
205 }
206}
207
208static
209int reg_strcmp(struct reg reg[NR_REG], const char *cmp_type)
210{
211 const char *p = reg[REG_R0].str, *q = reg[REG_R1].str;
212 int ret;
213 int diff;
214
215 for (;;) {
216 int escaped_r0 = 0;
217
218 if (unlikely(p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')) {
219 if (q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')
220 diff = 0;
221 else
222 diff = -1;
223 break;
224 }
225 if (unlikely(q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')) {
226 if (p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')
227 diff = 0;
228 else
229 diff = 1;
230 break;
231 }
232 if (reg[REG_R0].literal) {
233 ret = parse_char(&p);
234 if (ret == -1) {
235 return 0;
236 } else if (ret == -2) {
237 escaped_r0 = 1;
238 }
239 /* else compare both char */
240 }
241 if (reg[REG_R1].literal) {
242 ret = parse_char(&q);
243 if (ret == -1) {
244 return 0;
245 } else if (ret == -2) {
246 if (!escaped_r0)
247 return -1;
248 } else {
249 if (escaped_r0)
250 return 1;
251 }
252 } else {
253 if (escaped_r0)
254 return 1;
255 }
256 diff = *p - *q;
257 if (diff != 0)
258 break;
259 p++;
260 q++;
261 }
262 return diff;
263}
264
265static
266int lttng_filter_false(void *filter_data,
267 const char *filter_stack_data)
268{
269 return 0;
270}
2d78951a 271
064220d4
MD
272#ifdef INTERPRETER_USE_SWITCH
273
86cc3805
MD
274/*
275 * Fallback for compilers that do not support taking address of labels.
276 */
277
064220d4
MD
278#define START_OP \
279 start_pc = &bytecode->data[0]; \
280 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
281 pc = next_pc) { \
282 dbg_printf("Executing op %s (%u)\n", \
283 print_op((unsigned int) *(filter_opcode_t *) pc), \
284 (unsigned int) *(filter_opcode_t *) pc); \
285 switch (*(filter_opcode_t *) pc) {
286
287#define OP(name) case name
288
289#define PO break
290
291#define END_OP } \
292 }
293
294#else
295
86cc3805
MD
296/*
297 * Dispatch-table based interpreter.
298 */
299
300#define START_OP \
301 start_pc = &bytecode->data[0]; \
302 pc = next_pc = start_pc; \
303 if (unlikely(pc - start_pc >= bytecode->len)) \
304 goto end; \
305 goto *dispatch[*(filter_opcode_t *) pc];
306
307#define OP(name) \
308LABEL_##name
309
310#define PO \
311 pc = next_pc; \
312 goto *dispatch[*(filter_opcode_t *) pc];
313
314#define END_OP
064220d4
MD
315
316#endif
317
2d78951a
MD
318static
319int lttng_filter_interpret_bytecode(void *filter_data,
320 const char *filter_stack_data)
321{
cd54f6d9
MD
322 struct bytecode_runtime *bytecode = filter_data;
323 void *pc, *next_pc, *start_pc;
324 int ret = -EINVAL;
325 int retval = 0;
326 struct reg reg[NR_REG];
064220d4
MD
327#ifndef INTERPRETER_USE_SWITCH
328 static void *dispatch[NR_FILTER_OPS] = {
86cc3805 329 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
cd54f6d9 330
064220d4
MD
331 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
332
333 /* binary */
334 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
335 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
336 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
337 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
338 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
339 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
340 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
341 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
342 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
343 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
344
345 /* binary comparators */
346 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
347 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
348 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
349 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
350 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
351 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
352
353 /* string binary comparator */
354 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
355 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
356 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
357 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
358 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
359 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
360
361 /* s64 binary comparator */
362 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
363 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
364 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
365 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
366 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
367 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
368
369 /* double binary comparator */
370 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
371 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
372 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
373 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
374 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
375 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
376
377 /* unary */
378 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
379 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
380 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
381 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
382 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
383 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
384 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
385 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
386 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
387
388 /* logical */
389 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
390 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
391
392 /* load */
393 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
394 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
395 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
396 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
397 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
398
399 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
400 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
401 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
49905038
MD
402
403 /* cast */
404 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
405 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
406 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
064220d4
MD
407 };
408#endif /* #ifndef INTERPRETER_USE_SWITCH */
409
410 START_OP
411
412 OP(FILTER_OP_UNKNOWN):
413 OP(FILTER_OP_LOAD_FIELD_REF):
414#ifdef INTERPRETER_USE_SWITCH
cd54f6d9 415 default:
064220d4 416#endif /* INTERPRETER_USE_SWITCH */
b1caea50 417 ERR("unknown bytecode op %u\n",
cd54f6d9
MD
418 (unsigned int) *(filter_opcode_t *) pc);
419 ret = -EINVAL;
420 goto end;
421
064220d4 422 OP(FILTER_OP_RETURN):
cd54f6d9
MD
423 retval = !!reg[0].v;
424 ret = 0;
425 goto end;
426
427 /* binary */
064220d4
MD
428 OP(FILTER_OP_MUL):
429 OP(FILTER_OP_DIV):
430 OP(FILTER_OP_MOD):
431 OP(FILTER_OP_PLUS):
432 OP(FILTER_OP_MINUS):
433 OP(FILTER_OP_RSHIFT):
434 OP(FILTER_OP_LSHIFT):
435 OP(FILTER_OP_BIN_AND):
436 OP(FILTER_OP_BIN_OR):
437 OP(FILTER_OP_BIN_XOR):
b1caea50 438 ERR("unsupported bytecode op %u\n",
cd54f6d9
MD
439 (unsigned int) *(filter_opcode_t *) pc);
440 ret = -EINVAL;
441 goto end;
442
064220d4
MD
443 OP(FILTER_OP_EQ):
444 OP(FILTER_OP_NE):
445 OP(FILTER_OP_GT):
446 OP(FILTER_OP_LT):
447 OP(FILTER_OP_GE):
448 OP(FILTER_OP_LE):
226106c0
MD
449 ERR("unsupported non-specialized bytecode op %u\n",
450 (unsigned int) *(filter_opcode_t *) pc);
451 ret = -EINVAL;
452 goto end;
cd54f6d9 453
064220d4 454 OP(FILTER_OP_EQ_STRING):
226106c0
MD
455 {
456 reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
cd54f6d9
MD
457 reg[REG_R0].type = REG_S64;
458 next_pc += sizeof(struct binary_op);
064220d4 459 PO;
cd54f6d9 460 }
064220d4 461 OP(FILTER_OP_NE_STRING):
cd54f6d9 462 {
226106c0 463 reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
cd54f6d9
MD
464 reg[REG_R0].type = REG_S64;
465 next_pc += sizeof(struct binary_op);
064220d4 466 PO;
cd54f6d9 467 }
064220d4 468 OP(FILTER_OP_GT_STRING):
cd54f6d9 469 {
226106c0 470 reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
cd54f6d9
MD
471 reg[REG_R0].type = REG_S64;
472 next_pc += sizeof(struct binary_op);
064220d4 473 PO;
cd54f6d9 474 }
064220d4 475 OP(FILTER_OP_LT_STRING):
cd54f6d9 476 {
226106c0 477 reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
cd54f6d9
MD
478 reg[REG_R0].type = REG_S64;
479 next_pc += sizeof(struct binary_op);
064220d4 480 PO;
cd54f6d9 481 }
064220d4 482 OP(FILTER_OP_GE_STRING):
cd54f6d9 483 {
226106c0
MD
484 reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
485 reg[REG_R0].type = REG_S64;
486 next_pc += sizeof(struct binary_op);
064220d4 487 PO;
226106c0 488 }
064220d4 489 OP(FILTER_OP_LE_STRING):
226106c0
MD
490 {
491 reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
492 reg[REG_R0].type = REG_S64;
493 next_pc += sizeof(struct binary_op);
064220d4 494 PO;
226106c0 495 }
cd54f6d9 496
064220d4 497 OP(FILTER_OP_EQ_S64):
226106c0
MD
498 {
499 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
cd54f6d9
MD
500 reg[REG_R0].type = REG_S64;
501 next_pc += sizeof(struct binary_op);
064220d4 502 PO;
cd54f6d9 503 }
064220d4 504 OP(FILTER_OP_NE_S64):
cd54f6d9 505 {
226106c0
MD
506 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
507 reg[REG_R0].type = REG_S64;
508 next_pc += sizeof(struct binary_op);
064220d4 509 PO;
226106c0 510 }
064220d4 511 OP(FILTER_OP_GT_S64):
226106c0
MD
512 {
513 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
514 reg[REG_R0].type = REG_S64;
515 next_pc += sizeof(struct binary_op);
064220d4 516 PO;
226106c0 517 }
064220d4 518 OP(FILTER_OP_LT_S64):
226106c0
MD
519 {
520 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
521 reg[REG_R0].type = REG_S64;
522 next_pc += sizeof(struct binary_op);
064220d4 523 PO;
226106c0 524 }
064220d4 525 OP(FILTER_OP_GE_S64):
226106c0
MD
526 {
527 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
528 reg[REG_R0].type = REG_S64;
529 next_pc += sizeof(struct binary_op);
064220d4 530 PO;
226106c0 531 }
064220d4 532 OP(FILTER_OP_LE_S64):
226106c0
MD
533 {
534 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
535 reg[REG_R0].type = REG_S64;
536 next_pc += sizeof(struct binary_op);
064220d4 537 PO;
226106c0 538 }
cd54f6d9 539
064220d4 540 OP(FILTER_OP_EQ_DOUBLE):
226106c0
MD
541 {
542 if (unlikely(reg[REG_R0].type == REG_S64))
543 reg[REG_R0].d = (double) reg[REG_R0].v;
544 else if (unlikely(reg[REG_R1].type == REG_S64))
545 reg[REG_R1].d = (double) reg[REG_R1].v;
546 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
547 reg[REG_R0].type = REG_S64;
548 next_pc += sizeof(struct binary_op);
064220d4 549 PO;
226106c0 550 }
064220d4 551 OP(FILTER_OP_NE_DOUBLE):
226106c0
MD
552 {
553 if (unlikely(reg[REG_R0].type == REG_S64))
554 reg[REG_R0].d = (double) reg[REG_R0].v;
555 else if (unlikely(reg[REG_R1].type == REG_S64))
556 reg[REG_R1].d = (double) reg[REG_R1].v;
557 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
558 reg[REG_R0].type = REG_S64;
559 next_pc += sizeof(struct binary_op);
064220d4 560 PO;
226106c0 561 }
064220d4 562 OP(FILTER_OP_GT_DOUBLE):
226106c0
MD
563 {
564 if (unlikely(reg[REG_R0].type == REG_S64))
565 reg[REG_R0].d = (double) reg[REG_R0].v;
566 else if (unlikely(reg[REG_R1].type == REG_S64))
567 reg[REG_R1].d = (double) reg[REG_R1].v;
568 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
569 reg[REG_R0].type = REG_S64;
570 next_pc += sizeof(struct binary_op);
064220d4 571 PO;
226106c0 572 }
064220d4 573 OP(FILTER_OP_LT_DOUBLE):
226106c0
MD
574 {
575 if (unlikely(reg[REG_R0].type == REG_S64))
576 reg[REG_R0].d = (double) reg[REG_R0].v;
577 else if (unlikely(reg[REG_R1].type == REG_S64))
578 reg[REG_R1].d = (double) reg[REG_R1].v;
579 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
580 reg[REG_R0].type = REG_S64;
581 next_pc += sizeof(struct binary_op);
064220d4 582 PO;
226106c0 583 }
064220d4 584 OP(FILTER_OP_GE_DOUBLE):
226106c0
MD
585 {
586 if (unlikely(reg[REG_R0].type == REG_S64))
587 reg[REG_R0].d = (double) reg[REG_R0].v;
588 else if (unlikely(reg[REG_R1].type == REG_S64))
589 reg[REG_R1].d = (double) reg[REG_R1].v;
590 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
591 reg[REG_R0].type = REG_S64;
592 next_pc += sizeof(struct binary_op);
064220d4 593 PO;
226106c0 594 }
064220d4 595 OP(FILTER_OP_LE_DOUBLE):
226106c0
MD
596 {
597 if (unlikely(reg[REG_R0].type == REG_S64))
598 reg[REG_R0].d = (double) reg[REG_R0].v;
599 else if (unlikely(reg[REG_R1].type == REG_S64))
600 reg[REG_R1].d = (double) reg[REG_R1].v;
601 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].d);
cd54f6d9
MD
602 reg[REG_R0].type = REG_S64;
603 next_pc += sizeof(struct binary_op);
064220d4 604 PO;
cd54f6d9
MD
605 }
606
607 /* unary */
064220d4 608 OP(FILTER_OP_UNARY_PLUS):
6f992ca3
MD
609 OP(FILTER_OP_UNARY_MINUS):
610 OP(FILTER_OP_UNARY_NOT):
611 ERR("unsupported non-specialized bytecode op %u\n",
612 (unsigned int) *(filter_opcode_t *) pc);
613 ret = -EINVAL;
614 goto end;
615
616
617 OP(FILTER_OP_UNARY_PLUS_S64):
618 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
cd54f6d9 619 {
cd54f6d9 620 next_pc += sizeof(struct unary_op);
064220d4 621 PO;
cd54f6d9 622 }
6f992ca3 623 OP(FILTER_OP_UNARY_MINUS_S64):
cd54f6d9
MD
624 {
625 struct unary_op *insn = (struct unary_op *) pc;
626
6f992ca3 627 reg[insn->reg].v = -reg[insn->reg].v;
cd54f6d9 628 next_pc += sizeof(struct unary_op);
064220d4 629 PO;
cd54f6d9 630 }
6f992ca3 631 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
cd54f6d9
MD
632 {
633 struct unary_op *insn = (struct unary_op *) pc;
634
6f992ca3
MD
635 reg[insn->reg].d = -reg[insn->reg].d;
636 next_pc += sizeof(struct unary_op);
637 PO;
638 }
639 OP(FILTER_OP_UNARY_NOT_S64):
640 {
641 struct unary_op *insn = (struct unary_op *) pc;
da6eed25 642
cd54f6d9
MD
643 reg[insn->reg].v = !reg[insn->reg].v;
644 next_pc += sizeof(struct unary_op);
064220d4 645 PO;
cd54f6d9 646 }
6f992ca3
MD
647 OP(FILTER_OP_UNARY_NOT_DOUBLE):
648 {
649 struct unary_op *insn = (struct unary_op *) pc;
650
651 reg[insn->reg].d = !reg[insn->reg].d;
652 next_pc += sizeof(struct unary_op);
653 PO;
654 }
655
cd54f6d9 656 /* logical */
064220d4 657 OP(FILTER_OP_AND):
cd54f6d9
MD
658 {
659 struct logical_op *insn = (struct logical_op *) pc;
660
cd54f6d9 661 /* If REG_R0 is 0, skip and evaluate to 0 */
96c9d846 662 if (unlikely(reg[REG_R0].v == 0)) {
cd54f6d9
MD
663 dbg_printf("Jumping to bytecode offset %u\n",
664 (unsigned int) insn->skip_offset);
665 next_pc = start_pc + insn->skip_offset;
cd54f6d9
MD
666 } else {
667 next_pc += sizeof(struct logical_op);
668 }
064220d4 669 PO;
cd54f6d9 670 }
49905038 671 OP(FILTER_OP_OR):
cd54f6d9
MD
672 {
673 struct logical_op *insn = (struct logical_op *) pc;
674
cd54f6d9 675 /* If REG_R0 is nonzero, skip and evaluate to 1 */
da6eed25 676
96c9d846 677 if (unlikely(reg[REG_R0].v != 0)) {
cd54f6d9
MD
678 reg[REG_R0].v = 1;
679 dbg_printf("Jumping to bytecode offset %u\n",
680 (unsigned int) insn->skip_offset);
681 next_pc = start_pc + insn->skip_offset;
cd54f6d9
MD
682 } else {
683 next_pc += sizeof(struct logical_op);
684 }
064220d4 685 PO;
cd54f6d9
MD
686 }
687
96c9d846 688
cd54f6d9 689 /* load */
064220d4 690 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
cd54f6d9
MD
691 {
692 struct load_op *insn = (struct load_op *) pc;
693 struct field_ref *ref = (struct field_ref *) insn->data;
694
2f0145d1
MD
695 dbg_printf("load field ref offset %u type string\n",
696 ref->offset);
697 reg[insn->reg].str =
698 *(const char * const *) &filter_stack_data[ref->offset];
33fb658e
MD
699 if (unlikely(!reg[insn->reg].str)) {
700 dbg_printf("Filter warning: loading a NULL string.\n");
701 ret = -EINVAL;
702 goto end;
703 }
2f0145d1
MD
704 reg[insn->reg].type = REG_STRING;
705 reg[insn->reg].seq_len = UINT_MAX;
706 reg[insn->reg].literal = 0;
707 dbg_printf("ref load string %s\n", reg[insn->reg].str);
708 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 709 PO;
2f0145d1 710 }
cd54f6d9 711
064220d4 712 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
2f0145d1
MD
713 {
714 struct load_op *insn = (struct load_op *) pc;
715 struct field_ref *ref = (struct field_ref *) insn->data;
cd54f6d9 716
2f0145d1
MD
717 dbg_printf("load field ref offset %u type sequence\n",
718 ref->offset);
719 reg[insn->reg].seq_len =
720 *(unsigned long *) &filter_stack_data[ref->offset];
721 reg[insn->reg].str =
722 *(const char **) (&filter_stack_data[ref->offset
723 + sizeof(unsigned long)]);
33fb658e
MD
724 if (unlikely(!reg[insn->reg].str)) {
725 dbg_printf("Filter warning: loading a NULL sequence.\n");
726 ret = -EINVAL;
727 goto end;
728 }
2f0145d1
MD
729 reg[insn->reg].type = REG_STRING;
730 reg[insn->reg].literal = 0;
731 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 732 PO;
2f0145d1
MD
733 }
734
064220d4 735 OP(FILTER_OP_LOAD_FIELD_REF_S64):
2f0145d1
MD
736 {
737 struct load_op *insn = (struct load_op *) pc;
738 struct field_ref *ref = (struct field_ref *) insn->data;
739
740 dbg_printf("load field ref offset %u type s64\n",
741 ref->offset);
742 memcpy(&reg[insn->reg].v, &filter_stack_data[ref->offset],
743 sizeof(struct literal_numeric));
744 reg[insn->reg].type = REG_S64;
2f0145d1
MD
745 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
746 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 747 PO;
2f0145d1
MD
748 }
749
064220d4 750 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
2f0145d1
MD
751 {
752 struct load_op *insn = (struct load_op *) pc;
753 struct field_ref *ref = (struct field_ref *) insn->data;
754
755 dbg_printf("load field ref offset %u type double\n",
756 ref->offset);
757 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
758 sizeof(struct literal_double));
759 reg[insn->reg].type = REG_DOUBLE;
2f0145d1 760 dbg_printf("ref load double %g\n", reg[insn->reg].d);
cd54f6d9 761 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 762 PO;
cd54f6d9
MD
763 }
764
064220d4 765 OP(FILTER_OP_LOAD_STRING):
cd54f6d9
MD
766 {
767 struct load_op *insn = (struct load_op *) pc;
768
cd54f6d9
MD
769 dbg_printf("load string %s\n", insn->data);
770 reg[insn->reg].str = insn->data;
771 reg[insn->reg].type = REG_STRING;
772 reg[insn->reg].seq_len = UINT_MAX;
773 reg[insn->reg].literal = 1;
774 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
064220d4 775 PO;
cd54f6d9
MD
776 }
777
064220d4 778 OP(FILTER_OP_LOAD_S64):
cd54f6d9
MD
779 {
780 struct load_op *insn = (struct load_op *) pc;
781
cd54f6d9
MD
782 memcpy(&reg[insn->reg].v, insn->data,
783 sizeof(struct literal_numeric));
784 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
785 reg[insn->reg].type = REG_S64;
786 next_pc += sizeof(struct load_op)
787 + sizeof(struct literal_numeric);
064220d4 788 PO;
cd54f6d9 789 }
da6eed25 790
064220d4 791 OP(FILTER_OP_LOAD_DOUBLE):
da6eed25
MD
792 {
793 struct load_op *insn = (struct load_op *) pc;
794
da6eed25
MD
795 memcpy(&reg[insn->reg].d, insn->data,
796 sizeof(struct literal_double));
797 dbg_printf("load s64 %g\n", reg[insn->reg].d);
798 reg[insn->reg].type = REG_DOUBLE;
799 next_pc += sizeof(struct load_op)
800 + sizeof(struct literal_double);
064220d4 801 PO;
da6eed25 802 }
064220d4 803
49905038
MD
804 /* cast */
805 OP(FILTER_OP_CAST_TO_S64):
806 ERR("unsupported non-specialized bytecode op %u\n",
807 (unsigned int) *(filter_opcode_t *) pc);
808 ret = -EINVAL;
809 goto end;
810
811 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
812 {
813 struct cast_op *insn = (struct cast_op *) pc;
814
815 reg[insn->reg].v = (int64_t) reg[insn->reg].d;
816 reg[insn->reg].type = REG_S64;
817 next_pc += sizeof(struct cast_op);
818 PO;
819 }
820
821 OP(FILTER_OP_CAST_NOP):
822 {
823 next_pc += sizeof(struct cast_op);
824 PO;
825 }
826
064220d4 827 END_OP
cd54f6d9
MD
828end:
829 /* return 0 (discard) on error */
830 if (ret)
831 return 0;
832 return retval;
833}
834
86cc3805
MD
835#undef START_OP
836#undef OP
837#undef PO
838#undef END_OP
839
9522a886
MD
840static
841int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
842{
843 switch (reg[REG_R0].type) {
844 default:
845 goto error_unknown;
846
847 case REG_STRING:
848 switch (reg[REG_R1].type) {
849 default:
850 goto error_unknown;
851
852 case REG_STRING:
853 break;
854 case REG_S64:
855 case REG_DOUBLE:
856 goto error_mismatch;
857 }
858 break;
859 case REG_S64:
860 case REG_DOUBLE:
861 switch (reg[REG_R1].type) {
862 default:
863 goto error_unknown;
864
865 case REG_STRING:
866 goto error_mismatch;
867
868 case REG_S64:
869 case REG_DOUBLE:
870 break;
871 }
872 break;
873 }
874 return 0;
875
876error_unknown:
877
878 return -EINVAL;
879error_mismatch:
880 ERR("type mismatch for '%s' binary operator\n", str);
881 return -EINVAL;
882}
883
bbe775b2
MD
884/*
885 * Validate bytecode range overflow within the validation pass.
886 * Called for each instruction encountered.
887 */
888static
889int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
890 void *start_pc, void *pc)
891{
892 int ret = 0;
893
894 switch (*(filter_opcode_t *) pc) {
895 case FILTER_OP_UNKNOWN:
896 default:
897 {
898 ERR("unknown bytecode op %u\n",
899 (unsigned int) *(filter_opcode_t *) pc);
900 ret = -EINVAL;
901 break;
902 }
903
904 case FILTER_OP_RETURN:
905 {
906 if (unlikely(pc + sizeof(struct return_op)
907 > start_pc + bytecode->len)) {
908 ret = -EINVAL;
909 }
910 break;
911 }
912
913 /* binary */
914 case FILTER_OP_MUL:
915 case FILTER_OP_DIV:
916 case FILTER_OP_MOD:
917 case FILTER_OP_PLUS:
918 case FILTER_OP_MINUS:
919 case FILTER_OP_RSHIFT:
920 case FILTER_OP_LSHIFT:
921 case FILTER_OP_BIN_AND:
922 case FILTER_OP_BIN_OR:
923 case FILTER_OP_BIN_XOR:
924 {
925 ERR("unsupported bytecode op %u\n",
926 (unsigned int) *(filter_opcode_t *) pc);
927 ret = -EINVAL;
928 break;
929 }
930
931 case FILTER_OP_EQ:
932 case FILTER_OP_NE:
933 case FILTER_OP_GT:
934 case FILTER_OP_LT:
935 case FILTER_OP_GE:
936 case FILTER_OP_LE:
937 case FILTER_OP_EQ_STRING:
938 case FILTER_OP_NE_STRING:
939 case FILTER_OP_GT_STRING:
940 case FILTER_OP_LT_STRING:
941 case FILTER_OP_GE_STRING:
942 case FILTER_OP_LE_STRING:
943 case FILTER_OP_EQ_S64:
944 case FILTER_OP_NE_S64:
945 case FILTER_OP_GT_S64:
946 case FILTER_OP_LT_S64:
947 case FILTER_OP_GE_S64:
948 case FILTER_OP_LE_S64:
949 case FILTER_OP_EQ_DOUBLE:
950 case FILTER_OP_NE_DOUBLE:
951 case FILTER_OP_GT_DOUBLE:
952 case FILTER_OP_LT_DOUBLE:
953 case FILTER_OP_GE_DOUBLE:
954 case FILTER_OP_LE_DOUBLE:
955 {
956 if (unlikely(pc + sizeof(struct binary_op)
957 > start_pc + bytecode->len)) {
958 ret = -EINVAL;
959 }
960 break;
961 }
962
963 /* unary */
964 case FILTER_OP_UNARY_PLUS:
965 case FILTER_OP_UNARY_MINUS:
966 case FILTER_OP_UNARY_NOT:
967 case FILTER_OP_UNARY_PLUS_S64:
968 case FILTER_OP_UNARY_MINUS_S64:
969 case FILTER_OP_UNARY_NOT_S64:
970 case FILTER_OP_UNARY_PLUS_DOUBLE:
971 case FILTER_OP_UNARY_MINUS_DOUBLE:
972 case FILTER_OP_UNARY_NOT_DOUBLE:
973 {
974 if (unlikely(pc + sizeof(struct unary_op)
975 > start_pc + bytecode->len)) {
976 ret = -EINVAL;
977 }
978 break;
979 }
980
981 /* logical */
982 case FILTER_OP_AND:
983 case FILTER_OP_OR:
984 {
985 if (unlikely(pc + sizeof(struct logical_op)
986 > start_pc + bytecode->len)) {
987 ret = -EINVAL;
988 }
989 break;
990 }
991
992 /* load */
993 case FILTER_OP_LOAD_FIELD_REF:
994 {
995 ERR("Unknown field ref type\n");
996 ret = -EINVAL;
997 break;
998 }
999 case FILTER_OP_LOAD_FIELD_REF_STRING:
1000 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1001 case FILTER_OP_LOAD_FIELD_REF_S64:
1002 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1003 {
1004 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
1005 > start_pc + bytecode->len)) {
1006 ret = -EINVAL;
1007 }
1008 break;
1009 }
1010
1011 case FILTER_OP_LOAD_STRING:
1012 {
1013 struct load_op *insn = (struct load_op *) pc;
1014 uint32_t str_len, maxlen;
1015
1016 if (unlikely(pc + sizeof(struct load_op)
1017 > start_pc + bytecode->len)) {
1018 ret = -EINVAL;
1019 break;
1020 }
1021
1022 maxlen = start_pc + bytecode->len - pc - sizeof(struct load_op);
1023 str_len = strnlen(insn->data, maxlen);
1024 if (unlikely(str_len >= maxlen)) {
1025 /* Final '\0' not found within range */
1026 ret = -EINVAL;
1027 }
1028 break;
1029 }
1030
1031 case FILTER_OP_LOAD_S64:
1032 {
1033 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
1034 > start_pc + bytecode->len)) {
1035 ret = -EINVAL;
1036 }
1037 break;
1038 }
1039
1040 case FILTER_OP_LOAD_DOUBLE:
1041 {
1042 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_double)
1043 > start_pc + bytecode->len)) {
1044 ret = -EINVAL;
1045 }
1046 break;
1047 }
1048
1049 case FILTER_OP_CAST_TO_S64:
1050 case FILTER_OP_CAST_DOUBLE_TO_S64:
1051 case FILTER_OP_CAST_NOP:
1052 {
1053 if (unlikely(pc + sizeof(struct cast_op)
1054 > start_pc + bytecode->len)) {
1055 ret = -EINVAL;
1056 }
1057 break;
1058 }
1059 }
1060
1061 return ret;
1062}
1063
9522a886
MD
1064static
1065int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
1066{
1067 void *pc, *next_pc, *start_pc;
1068 int ret = -EINVAL;
1069 struct vreg reg[NR_REG];
1070 int i;
1071
1072 for (i = 0; i < NR_REG; i++) {
225b6640 1073 reg[i].type = REG_TYPE_UNKNOWN;
9522a886
MD
1074 reg[i].literal = 0;
1075 }
1076
1077 start_pc = &bytecode->data[0];
1078 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1079 pc = next_pc) {
bbe775b2 1080 if (bytecode_validate_overflow(bytecode, start_pc, pc) != 0) {
9522a886
MD
1081 ERR("filter bytecode overflow\n");
1082 ret = -EINVAL;
1083 goto end;
1084 }
1085 dbg_printf("Validating op %s (%u)\n",
1086 print_op((unsigned int) *(filter_opcode_t *) pc),
1087 (unsigned int) *(filter_opcode_t *) pc);
1088 switch (*(filter_opcode_t *) pc) {
1089 case FILTER_OP_UNKNOWN:
1090 default:
1091 ERR("unknown bytecode op %u\n",
1092 (unsigned int) *(filter_opcode_t *) pc);
1093 ret = -EINVAL;
1094 goto end;
1095
1096 case FILTER_OP_RETURN:
1097 ret = 0;
1098 goto end;
1099
1100 /* binary */
1101 case FILTER_OP_MUL:
1102 case FILTER_OP_DIV:
1103 case FILTER_OP_MOD:
1104 case FILTER_OP_PLUS:
1105 case FILTER_OP_MINUS:
1106 case FILTER_OP_RSHIFT:
1107 case FILTER_OP_LSHIFT:
1108 case FILTER_OP_BIN_AND:
1109 case FILTER_OP_BIN_OR:
1110 case FILTER_OP_BIN_XOR:
1111 ERR("unsupported bytecode op %u\n",
1112 (unsigned int) *(filter_opcode_t *) pc);
1113 ret = -EINVAL;
1114 goto end;
1115
1116 case FILTER_OP_EQ:
1117 {
1118 ret = bin_op_compare_check(reg, "==");
1119 if (ret)
1120 goto end;
1121 reg[REG_R0].type = REG_S64;
1122 next_pc += sizeof(struct binary_op);
1123 break;
1124 }
1125 case FILTER_OP_NE:
1126 {
1127 ret = bin_op_compare_check(reg, "!=");
1128 if (ret)
1129 goto end;
1130 reg[REG_R0].type = REG_S64;
1131 next_pc += sizeof(struct binary_op);
1132 break;
1133 }
1134 case FILTER_OP_GT:
1135 {
1136 ret = bin_op_compare_check(reg, ">");
1137 if (ret)
1138 goto end;
1139 reg[REG_R0].type = REG_S64;
1140 next_pc += sizeof(struct binary_op);
1141 break;
1142 }
1143 case FILTER_OP_LT:
1144 {
1145 ret = bin_op_compare_check(reg, "<");
1146 if (ret)
1147 goto end;
1148 reg[REG_R0].type = REG_S64;
1149 next_pc += sizeof(struct binary_op);
1150 break;
1151 }
1152 case FILTER_OP_GE:
1153 {
1154 ret = bin_op_compare_check(reg, ">=");
1155 if (ret)
1156 goto end;
1157 reg[REG_R0].type = REG_S64;
1158 next_pc += sizeof(struct binary_op);
1159 break;
1160 }
1161 case FILTER_OP_LE:
1162 {
1163 ret = bin_op_compare_check(reg, "<=");
1164 if (ret)
1165 goto end;
1166 reg[REG_R0].type = REG_S64;
1167 next_pc += sizeof(struct binary_op);
1168 break;
1169 }
1170
226106c0
MD
1171 case FILTER_OP_EQ_STRING:
1172 case FILTER_OP_NE_STRING:
1173 case FILTER_OP_GT_STRING:
1174 case FILTER_OP_LT_STRING:
1175 case FILTER_OP_GE_STRING:
1176 case FILTER_OP_LE_STRING:
1177 {
1178 if (reg[REG_R0].type != REG_STRING
1179 || reg[REG_R1].type != REG_STRING) {
1180 ERR("Unexpected register type for string comparator\n");
1181 ret = -EINVAL;
1182 goto end;
1183 }
1184 reg[REG_R0].type = REG_S64;
1185 next_pc += sizeof(struct binary_op);
1186 break;
1187 }
1188
1189 case FILTER_OP_EQ_S64:
1190 case FILTER_OP_NE_S64:
1191 case FILTER_OP_GT_S64:
1192 case FILTER_OP_LT_S64:
1193 case FILTER_OP_GE_S64:
1194 case FILTER_OP_LE_S64:
1195 {
1196 if (reg[REG_R0].type != REG_S64
1197 || reg[REG_R1].type != REG_S64) {
1198 ERR("Unexpected register type for s64 comparator\n");
1199 ret = -EINVAL;
1200 goto end;
1201 }
1202 reg[REG_R0].type = REG_S64;
1203 next_pc += sizeof(struct binary_op);
1204 break;
1205 }
1206
1207 case FILTER_OP_EQ_DOUBLE:
1208 case FILTER_OP_NE_DOUBLE:
1209 case FILTER_OP_GT_DOUBLE:
1210 case FILTER_OP_LT_DOUBLE:
1211 case FILTER_OP_GE_DOUBLE:
1212 case FILTER_OP_LE_DOUBLE:
1213 {
1214 if ((reg[REG_R0].type != REG_DOUBLE && reg[REG_R0].type != REG_S64)
1215 || (reg[REG_R1].type != REG_DOUBLE && reg[REG_R1].type != REG_S64)) {
1216 ERR("Unexpected register type for double comparator\n");
1217 ret = -EINVAL;
1218 goto end;
1219 }
96c9d846
MD
1220 if (reg[REG_R0].type != REG_DOUBLE && reg[REG_R1].type != REG_DOUBLE) {
1221 ERR("Double operator should have at least one double register\n");
1222 ret = -EINVAL;
1223 goto end;
1224 }
226106c0
MD
1225 reg[REG_R0].type = REG_DOUBLE;
1226 next_pc += sizeof(struct binary_op);
1227 break;
1228 }
1229
9522a886
MD
1230 /* unary */
1231 case FILTER_OP_UNARY_PLUS:
1232 case FILTER_OP_UNARY_MINUS:
1233 case FILTER_OP_UNARY_NOT:
1234 {
1235 struct unary_op *insn = (struct unary_op *) pc;
1236
1237 if (unlikely(insn->reg >= REG_ERROR)) {
1238 ERR("invalid register %u\n",
1239 (unsigned int) insn->reg);
1240 ret = -EINVAL;
1241 goto end;
1242 }
1243 switch (reg[insn->reg].type) {
1244 default:
1245 ERR("unknown register type\n");
1246 ret = -EINVAL;
1247 goto end;
1248
1249 case REG_STRING:
1250 ERR("Unary op can only be applied to numeric or floating point registers\n");
1251 ret = -EINVAL;
1252 goto end;
1253 case REG_S64:
1254 break;
1255 case REG_DOUBLE:
1256 break;
1257 }
1258 next_pc += sizeof(struct unary_op);
1259 break;
1260 }
08c84b15
MD
1261
1262 case FILTER_OP_UNARY_PLUS_S64:
1263 case FILTER_OP_UNARY_MINUS_S64:
1264 case FILTER_OP_UNARY_NOT_S64:
1265 {
1266 struct unary_op *insn = (struct unary_op *) pc;
1267
1268 if (unlikely(insn->reg >= REG_ERROR)) {
1269 ERR("invalid register %u\n",
1270 (unsigned int) insn->reg);
1271 ret = -EINVAL;
1272 goto end;
1273 }
1274 if (reg[insn->reg].type != REG_S64) {
1275 ERR("Invalid register type\n");
1276 ret = -EINVAL;
1277 goto end;
1278 }
1279 next_pc += sizeof(struct unary_op);
1280 break;
1281 }
1282
1283 case FILTER_OP_UNARY_PLUS_DOUBLE:
1284 case FILTER_OP_UNARY_MINUS_DOUBLE:
1285 case FILTER_OP_UNARY_NOT_DOUBLE:
1286 {
1287 struct unary_op *insn = (struct unary_op *) pc;
1288
1289 if (unlikely(insn->reg >= REG_ERROR)) {
1290 ERR("invalid register %u\n",
1291 (unsigned int) insn->reg);
1292 ret = -EINVAL;
1293 goto end;
1294 }
1295 if (reg[insn->reg].type != REG_DOUBLE) {
1296 ERR("Invalid register type\n");
1297 ret = -EINVAL;
1298 goto end;
1299 }
1300 next_pc += sizeof(struct unary_op);
1301 break;
1302 }
1303
9522a886
MD
1304 /* logical */
1305 case FILTER_OP_AND:
1306 case FILTER_OP_OR:
1307 {
1308 struct logical_op *insn = (struct logical_op *) pc;
1309
49905038
MD
1310 if (reg[REG_R0].type != REG_S64) {
1311 ERR("Logical comparator expects S64 register\n");
9522a886
MD
1312 ret = -EINVAL;
1313 goto end;
1314 }
1315
1316 dbg_printf("Validate jumping to bytecode offset %u\n",
1317 (unsigned int) insn->skip_offset);
1318 if (unlikely(start_pc + insn->skip_offset <= pc)) {
1319 ERR("Loops are not allowed in bytecode\n");
1320 ret = -EINVAL;
1321 goto end;
1322 }
1323 next_pc += sizeof(struct logical_op);
1324 break;
1325 }
1326
1327 /* load */
1328 case FILTER_OP_LOAD_FIELD_REF:
2f0145d1
MD
1329 {
1330 ERR("Unknown field ref type\n");
1331 ret = -EINVAL;
1332 goto end;
1333 }
1334 case FILTER_OP_LOAD_FIELD_REF_STRING:
1335 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
9522a886
MD
1336 {
1337 struct load_op *insn = (struct load_op *) pc;
1338 struct field_ref *ref = (struct field_ref *) insn->data;
1339
1340 if (unlikely(insn->reg >= REG_ERROR)) {
1341 ERR("invalid register %u\n",
1342 (unsigned int) insn->reg);
1343 ret = -EINVAL;
1344 goto end;
1345 }
2f0145d1
MD
1346 dbg_printf("Validate load field ref offset %u type string\n",
1347 ref->offset);
1348 reg[insn->reg].type = REG_STRING;
1349 reg[insn->reg].literal = 0;
1350 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1351 break;
1352 }
1353 case FILTER_OP_LOAD_FIELD_REF_S64:
1354 {
1355 struct load_op *insn = (struct load_op *) pc;
1356 struct field_ref *ref = (struct field_ref *) insn->data;
1357
1358 if (unlikely(insn->reg >= REG_ERROR)) {
1359 ERR("invalid register %u\n",
1360 (unsigned int) insn->reg);
9522a886
MD
1361 ret = -EINVAL;
1362 goto end;
9522a886 1363 }
2f0145d1
MD
1364 dbg_printf("Validate load field ref offset %u type s64\n",
1365 ref->offset);
1366 reg[insn->reg].type = REG_S64;
1367 reg[insn->reg].literal = 0;
1368 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1369 break;
1370 }
1371 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1372 {
1373 struct load_op *insn = (struct load_op *) pc;
1374 struct field_ref *ref = (struct field_ref *) insn->data;
9522a886 1375
2f0145d1
MD
1376 if (unlikely(insn->reg >= REG_ERROR)) {
1377 ERR("invalid register %u\n",
1378 (unsigned int) insn->reg);
1379 ret = -EINVAL;
1380 goto end;
1381 }
1382 dbg_printf("Validate load field ref offset %u type double\n",
1383 ref->offset);
1384 reg[insn->reg].type = REG_DOUBLE;
1385 reg[insn->reg].literal = 0;
9522a886
MD
1386 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1387 break;
1388 }
1389
1390 case FILTER_OP_LOAD_STRING:
1391 {
1392 struct load_op *insn = (struct load_op *) pc;
1393
1394 if (unlikely(insn->reg >= REG_ERROR)) {
1395 ERR("invalid register %u\n",
1396 (unsigned int) insn->reg);
1397 ret = -EINVAL;
1398 goto end;
1399 }
1400 reg[insn->reg].type = REG_STRING;
1401 reg[insn->reg].literal = 1;
1402 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1403 break;
1404 }
1405
1406 case FILTER_OP_LOAD_S64:
1407 {
1408 struct load_op *insn = (struct load_op *) pc;
1409
1410 if (unlikely(insn->reg >= REG_ERROR)) {
1411 ERR("invalid register %u\n",
1412 (unsigned int) insn->reg);
1413 ret = -EINVAL;
1414 goto end;
1415 }
1416 reg[insn->reg].type = REG_S64;
08c84b15 1417 reg[insn->reg].literal = 1;
9522a886
MD
1418 next_pc += sizeof(struct load_op)
1419 + sizeof(struct literal_numeric);
1420 break;
1421 }
1422
1423 case FILTER_OP_LOAD_DOUBLE:
1424 {
1425 struct load_op *insn = (struct load_op *) pc;
1426
1427 if (unlikely(insn->reg >= REG_ERROR)) {
1428 ERR("invalid register %u\n",
1429 (unsigned int) insn->reg);
1430 ret = -EINVAL;
1431 goto end;
1432 }
1433 reg[insn->reg].type = REG_DOUBLE;
08c84b15 1434 reg[insn->reg].literal = 1;
9522a886
MD
1435 next_pc += sizeof(struct load_op)
1436 + sizeof(struct literal_double);
1437 break;
1438 }
49905038
MD
1439
1440 case FILTER_OP_CAST_TO_S64:
1441 case FILTER_OP_CAST_DOUBLE_TO_S64:
1442 {
1443 struct cast_op *insn = (struct cast_op *) pc;
1444
1445 if (unlikely(insn->reg >= REG_ERROR)) {
1446 ERR("invalid register %u\n",
1447 (unsigned int) insn->reg);
1448 ret = -EINVAL;
1449 goto end;
1450 }
1451 switch (reg[insn->reg].type) {
1452 default:
1453 ERR("unknown register type\n");
1454 ret = -EINVAL;
1455 goto end;
1456
1457 case REG_STRING:
1458 ERR("Cast op can only be applied to numeric or floating point registers\n");
1459 ret = -EINVAL;
1460 goto end;
1461 case REG_S64:
1462 break;
1463 case REG_DOUBLE:
1464 break;
1465 }
1466 if (insn->op == FILTER_OP_CAST_DOUBLE_TO_S64) {
1467 if (reg[insn->reg].type != REG_DOUBLE) {
1468 ERR("Cast expects double\n");
1469 ret = -EINVAL;
1470 goto end;
1471 }
1472 }
1473 reg[insn->reg].type = REG_S64;
1474 next_pc += sizeof(struct cast_op);
1475 break;
1476 }
1477 case FILTER_OP_CAST_NOP:
1478 {
1479 next_pc += sizeof(struct cast_op);
1480 break;
1481 }
1482
9522a886
MD
1483 }
1484 }
1485end:
1486 return ret;
1487}
1488
08c84b15
MD
1489static
1490int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
1491{
1492 void *pc, *next_pc, *start_pc;
1493 int ret = -EINVAL;
1494 struct vreg reg[NR_REG];
1495 int i;
1496
1497 for (i = 0; i < NR_REG; i++) {
1498 reg[i].type = REG_TYPE_UNKNOWN;
1499 reg[i].literal = 0;
1500 }
1501
1502 start_pc = &bytecode->data[0];
1503 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1504 pc = next_pc) {
1505 switch (*(filter_opcode_t *) pc) {
1506 case FILTER_OP_UNKNOWN:
1507 default:
1508 ERR("unknown bytecode op %u\n",
1509 (unsigned int) *(filter_opcode_t *) pc);
1510 ret = -EINVAL;
1511 goto end;
1512
1513 case FILTER_OP_RETURN:
1514 ret = 0;
1515 goto end;
1516
1517 /* binary */
1518 case FILTER_OP_MUL:
1519 case FILTER_OP_DIV:
1520 case FILTER_OP_MOD:
1521 case FILTER_OP_PLUS:
1522 case FILTER_OP_MINUS:
1523 case FILTER_OP_RSHIFT:
1524 case FILTER_OP_LSHIFT:
1525 case FILTER_OP_BIN_AND:
1526 case FILTER_OP_BIN_OR:
1527 case FILTER_OP_BIN_XOR:
1528 ERR("unsupported bytecode op %u\n",
1529 (unsigned int) *(filter_opcode_t *) pc);
1530 ret = -EINVAL;
1531 goto end;
1532
1533 case FILTER_OP_EQ:
226106c0
MD
1534 {
1535 struct binary_op *insn = (struct binary_op *) pc;
1536
1537 switch(reg[REG_R0].type) {
1538 default:
1539 ERR("unknown register type\n");
1540 ret = -EINVAL;
1541 goto end;
1542
1543 case REG_STRING:
1544 insn->op = FILTER_OP_EQ_STRING;
1545 break;
1546 case REG_S64:
1547 if (reg[REG_R1].type == REG_S64)
1548 insn->op = FILTER_OP_EQ_S64;
1549 else
1550 insn->op = FILTER_OP_EQ_DOUBLE;
1551 break;
1552 case REG_DOUBLE:
1553 insn->op = FILTER_OP_EQ_DOUBLE;
1554 break;
1555 }
1556 reg[REG_R0].type = REG_S64;
1557 next_pc += sizeof(struct binary_op);
1558 break;
1559 }
1560
08c84b15 1561 case FILTER_OP_NE:
226106c0
MD
1562 {
1563 struct binary_op *insn = (struct binary_op *) pc;
1564
1565 switch(reg[REG_R0].type) {
1566 default:
1567 ERR("unknown register type\n");
1568 ret = -EINVAL;
1569 goto end;
1570
1571 case REG_STRING:
1572 insn->op = FILTER_OP_NE_STRING;
1573 break;
1574 case REG_S64:
1575 if (reg[REG_R1].type == REG_S64)
1576 insn->op = FILTER_OP_NE_S64;
1577 else
1578 insn->op = FILTER_OP_NE_DOUBLE;
1579 break;
1580 case REG_DOUBLE:
1581 insn->op = FILTER_OP_NE_DOUBLE;
1582 break;
1583 }
1584 reg[REG_R0].type = REG_S64;
1585 next_pc += sizeof(struct binary_op);
1586 break;
1587 }
1588
08c84b15 1589 case FILTER_OP_GT:
226106c0
MD
1590 {
1591 struct binary_op *insn = (struct binary_op *) pc;
1592
1593 switch(reg[REG_R0].type) {
1594 default:
1595 ERR("unknown register type\n");
1596 ret = -EINVAL;
1597 goto end;
1598
1599 case REG_STRING:
1600 insn->op = FILTER_OP_GT_STRING;
1601 break;
1602 case REG_S64:
1603 if (reg[REG_R1].type == REG_S64)
1604 insn->op = FILTER_OP_GT_S64;
1605 else
1606 insn->op = FILTER_OP_GT_DOUBLE;
1607 break;
1608 case REG_DOUBLE:
1609 insn->op = FILTER_OP_GT_DOUBLE;
1610 break;
1611 }
1612 reg[REG_R0].type = REG_S64;
1613 next_pc += sizeof(struct binary_op);
1614 break;
1615 }
1616
08c84b15 1617 case FILTER_OP_LT:
226106c0
MD
1618 {
1619 struct binary_op *insn = (struct binary_op *) pc;
1620
1621 switch(reg[REG_R0].type) {
1622 default:
1623 ERR("unknown register type\n");
1624 ret = -EINVAL;
1625 goto end;
1626
1627 case REG_STRING:
1628 insn->op = FILTER_OP_LT_STRING;
1629 break;
1630 case REG_S64:
1631 if (reg[REG_R1].type == REG_S64)
1632 insn->op = FILTER_OP_LT_S64;
1633 else
1634 insn->op = FILTER_OP_LT_DOUBLE;
1635 break;
1636 case REG_DOUBLE:
1637 insn->op = FILTER_OP_LT_DOUBLE;
1638 break;
1639 }
1640 reg[REG_R0].type = REG_S64;
1641 next_pc += sizeof(struct binary_op);
1642 break;
1643 }
1644
08c84b15 1645 case FILTER_OP_GE:
226106c0
MD
1646 {
1647 struct binary_op *insn = (struct binary_op *) pc;
1648
1649 switch(reg[REG_R0].type) {
1650 default:
1651 ERR("unknown register type\n");
1652 ret = -EINVAL;
1653 goto end;
1654
1655 case REG_STRING:
1656 insn->op = FILTER_OP_GE_STRING;
1657 break;
1658 case REG_S64:
1659 if (reg[REG_R1].type == REG_S64)
1660 insn->op = FILTER_OP_GE_S64;
1661 else
1662 insn->op = FILTER_OP_GE_DOUBLE;
1663 break;
1664 case REG_DOUBLE:
1665 insn->op = FILTER_OP_GE_DOUBLE;
1666 break;
1667 }
1668 reg[REG_R0].type = REG_S64;
1669 next_pc += sizeof(struct binary_op);
1670 break;
1671 }
08c84b15 1672 case FILTER_OP_LE:
226106c0
MD
1673 {
1674 struct binary_op *insn = (struct binary_op *) pc;
1675
1676 switch(reg[REG_R0].type) {
1677 default:
1678 ERR("unknown register type\n");
1679 ret = -EINVAL;
1680 goto end;
1681
1682 case REG_STRING:
1683 insn->op = FILTER_OP_LE_STRING;
1684 break;
1685 case REG_S64:
1686 if (reg[REG_R1].type == REG_S64)
1687 insn->op = FILTER_OP_LE_S64;
1688 else
1689 insn->op = FILTER_OP_LE_DOUBLE;
1690 break;
1691 case REG_DOUBLE:
1692 insn->op = FILTER_OP_LE_DOUBLE;
1693 break;
1694 }
1695 reg[REG_R0].type = REG_S64;
1696 next_pc += sizeof(struct binary_op);
1697 break;
1698 }
1699
1700 case FILTER_OP_EQ_STRING:
1701 case FILTER_OP_NE_STRING:
1702 case FILTER_OP_GT_STRING:
1703 case FILTER_OP_LT_STRING:
1704 case FILTER_OP_GE_STRING:
1705 case FILTER_OP_LE_STRING:
1706 case FILTER_OP_EQ_S64:
1707 case FILTER_OP_NE_S64:
1708 case FILTER_OP_GT_S64:
1709 case FILTER_OP_LT_S64:
1710 case FILTER_OP_GE_S64:
1711 case FILTER_OP_LE_S64:
1712 case FILTER_OP_EQ_DOUBLE:
1713 case FILTER_OP_NE_DOUBLE:
1714 case FILTER_OP_GT_DOUBLE:
1715 case FILTER_OP_LT_DOUBLE:
1716 case FILTER_OP_GE_DOUBLE:
1717 case FILTER_OP_LE_DOUBLE:
08c84b15
MD
1718 {
1719 reg[REG_R0].type = REG_S64;
1720 next_pc += sizeof(struct binary_op);
1721 break;
1722 }
1723
1724 /* unary */
1725 case FILTER_OP_UNARY_PLUS:
1726 {
1727 struct unary_op *insn = (struct unary_op *) pc;
1728
1729 switch(reg[insn->reg].type) {
1730 default:
1731 ERR("unknown register type\n");
1732 ret = -EINVAL;
1733 goto end;
1734
1735 case REG_S64:
1736 insn->op = FILTER_OP_UNARY_PLUS_S64;
1737 break;
1738 case REG_DOUBLE:
1739 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1740 break;
1741 }
96c9d846 1742 next_pc += sizeof(struct unary_op);
08c84b15
MD
1743 break;
1744 }
1745
1746 case FILTER_OP_UNARY_MINUS:
1747 {
1748 struct unary_op *insn = (struct unary_op *) pc;
1749
1750 switch(reg[insn->reg].type) {
1751 default:
1752 ERR("unknown register type\n");
1753 ret = -EINVAL;
1754 goto end;
1755
1756 case REG_S64:
1757 insn->op = FILTER_OP_UNARY_MINUS_S64;
1758 break;
1759 case REG_DOUBLE:
1760 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1761 break;
1762 }
96c9d846 1763 next_pc += sizeof(struct unary_op);
08c84b15
MD
1764 break;
1765 }
1766
1767 case FILTER_OP_UNARY_NOT:
1768 {
1769 struct unary_op *insn = (struct unary_op *) pc;
1770
1771 switch(reg[insn->reg].type) {
1772 default:
1773 ERR("unknown register type\n");
1774 ret = -EINVAL;
1775 goto end;
1776
1777 case REG_S64:
1778 insn->op = FILTER_OP_UNARY_NOT_S64;
1779 break;
1780 case REG_DOUBLE:
1781 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1782 break;
1783 }
96c9d846 1784 next_pc += sizeof(struct unary_op);
08c84b15
MD
1785 break;
1786 }
1787
1788 case FILTER_OP_UNARY_PLUS_S64:
1789 case FILTER_OP_UNARY_MINUS_S64:
1790 case FILTER_OP_UNARY_NOT_S64:
1791 case FILTER_OP_UNARY_PLUS_DOUBLE:
1792 case FILTER_OP_UNARY_MINUS_DOUBLE:
1793 case FILTER_OP_UNARY_NOT_DOUBLE:
1794 {
1795 next_pc += sizeof(struct unary_op);
1796 break;
1797 }
1798
1799 /* logical */
1800 case FILTER_OP_AND:
1801 case FILTER_OP_OR:
1802 {
1803 next_pc += sizeof(struct logical_op);
1804 break;
1805 }
1806
1807 /* load */
1808 case FILTER_OP_LOAD_FIELD_REF:
1809 {
1810 ERR("Unknown field ref type\n");
1811 ret = -EINVAL;
1812 goto end;
1813 }
1814 case FILTER_OP_LOAD_FIELD_REF_STRING:
1815 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1816 {
1817 struct load_op *insn = (struct load_op *) pc;
1818
1819 reg[insn->reg].type = REG_STRING;
1820 reg[insn->reg].literal = 0;
1821 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1822 break;
1823 }
1824 case FILTER_OP_LOAD_FIELD_REF_S64:
1825 {
1826 struct load_op *insn = (struct load_op *) pc;
1827
1828 reg[insn->reg].type = REG_S64;
1829 reg[insn->reg].literal = 0;
1830 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1831 break;
1832 }
1833 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1834 {
1835 struct load_op *insn = (struct load_op *) pc;
1836
1837 reg[insn->reg].type = REG_DOUBLE;
1838 reg[insn->reg].literal = 0;
1839 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1840 break;
1841 }
1842
1843 case FILTER_OP_LOAD_STRING:
1844 {
1845 struct load_op *insn = (struct load_op *) pc;
1846
1847 reg[insn->reg].type = REG_STRING;
1848 reg[insn->reg].literal = 1;
1849 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1850 break;
1851 }
1852
1853 case FILTER_OP_LOAD_S64:
1854 {
1855 struct load_op *insn = (struct load_op *) pc;
1856
1857 reg[insn->reg].type = REG_S64;
1858 reg[insn->reg].literal = 1;
1859 next_pc += sizeof(struct load_op)
1860 + sizeof(struct literal_numeric);
1861 break;
1862 }
1863
1864 case FILTER_OP_LOAD_DOUBLE:
1865 {
1866 struct load_op *insn = (struct load_op *) pc;
1867
1868 reg[insn->reg].type = REG_DOUBLE;
1869 reg[insn->reg].literal = 1;
1870 next_pc += sizeof(struct load_op)
1871 + sizeof(struct literal_double);
1872 break;
1873 }
49905038
MD
1874
1875 /* cast */
1876 case FILTER_OP_CAST_TO_S64:
1877 {
1878 struct cast_op *insn = (struct cast_op *) pc;
1879
1880 switch (reg[insn->reg].type) {
1881 default:
1882 ERR("unknown register type\n");
1883 ret = -EINVAL;
1884 goto end;
1885
1886 case REG_STRING:
1887 ERR("Cast op can only be applied to numeric or floating point registers\n");
1888 ret = -EINVAL;
1889 goto end;
1890 case REG_S64:
1891 insn->op = FILTER_OP_CAST_NOP;
1892 break;
1893 case REG_DOUBLE:
1894 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
1895 break;
1896 }
1897 reg[insn->reg].type = REG_S64;
1898 next_pc += sizeof(struct cast_op);
1899 break;
1900 }
1901 case FILTER_OP_CAST_DOUBLE_TO_S64:
1902 {
1903 struct cast_op *insn = (struct cast_op *) pc;
1904
1905 reg[insn->reg].type = REG_S64;
1906 next_pc += sizeof(struct cast_op);
1907 break;
1908 }
1909 case FILTER_OP_CAST_NOP:
1910 {
1911 next_pc += sizeof(struct cast_op);
1912 break;
1913 }
1914
1915
08c84b15
MD
1916 }
1917 }
1918end:
1919 return ret;
1920}
1921
cd54f6d9
MD
1922static
1923int apply_field_reloc(struct ltt_event *event,
1924 struct bytecode_runtime *runtime,
1925 uint32_t runtime_len,
1926 uint32_t reloc_offset,
1927 const char *field_name)
1928{
1929 const struct lttng_event_desc *desc;
1930 const struct lttng_event_field *fields, *field = NULL;
1931 unsigned int nr_fields, i;
1932 struct field_ref *field_ref;
2f0145d1 1933 struct load_op *op;
cd54f6d9
MD
1934 uint32_t field_offset = 0;
1935
a8c27c7c 1936 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
cd54f6d9
MD
1937
1938 /* Ensure that the reloc is within the code */
1939 if (runtime_len - reloc_offset < sizeof(uint16_t))
1940 return -EINVAL;
1941
1942 /* Lookup event by name */
1943 desc = event->desc;
1944 if (!desc)
1945 return -EINVAL;
1946 fields = desc->fields;
1947 if (!fields)
1948 return -EINVAL;
1949 nr_fields = desc->nr_fields;
1950 for (i = 0; i < nr_fields; i++) {
1951 if (!strcmp(fields[i].name, field_name)) {
1952 field = &fields[i];
1953 break;
1954 }
1955 /* compute field offset */
1956 switch (fields[i].type.atype) {
1957 case atype_integer:
1958 case atype_enum:
1959 field_offset += sizeof(int64_t);
1960 break;
1961 case atype_array:
1962 case atype_sequence:
1963 field_offset += sizeof(unsigned long);
1964 field_offset += sizeof(void *);
1965 break;
1966 case atype_string:
1967 field_offset += sizeof(void *);
1968 break;
1969 case atype_float:
1970 field_offset += sizeof(double);
da6eed25 1971 break;
cd54f6d9
MD
1972 default:
1973 return -EINVAL;
1974 }
1975 }
1976 if (!field)
1977 return -EINVAL;
1978
1979 /* Check if field offset is too large for 16-bit offset */
1980 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1981 return -EINVAL;
1982
1983 /* set type */
2f0145d1
MD
1984 op = (struct load_op *) &runtime->data[reloc_offset];
1985 field_ref = (struct field_ref *) op->data;
cd54f6d9
MD
1986 switch (field->type.atype) {
1987 case atype_integer:
1988 case atype_enum:
2f0145d1 1989 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
cd54f6d9
MD
1990 break;
1991 case atype_array:
1992 case atype_sequence:
2f0145d1 1993 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
cd54f6d9
MD
1994 break;
1995 case atype_string:
2f0145d1 1996 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
cd54f6d9
MD
1997 break;
1998 case atype_float:
2f0145d1 1999 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
da6eed25 2000 break;
cd54f6d9
MD
2001 default:
2002 return -EINVAL;
2003 }
2004 /* set offset */
2005 field_ref->offset = (uint16_t) field_offset;
2d78951a
MD
2006 return 0;
2007}
2008
cd54f6d9
MD
2009/*
2010 * Take a bytecode with reloc table and link it to an event to create a
2011 * bytecode runtime.
2012 */
2d78951a
MD
2013static
2014int _lttng_filter_event_link_bytecode(struct ltt_event *event,
2015 struct lttng_ust_filter_bytecode *filter_bytecode)
2016{
cd54f6d9
MD
2017 int ret, offset, next_offset;
2018 struct bytecode_runtime *runtime = NULL;
2019 size_t runtime_alloc_len;
2020
2d78951a
MD
2021 if (!filter_bytecode)
2022 return 0;
cd54f6d9
MD
2023 /* Even is not connected to any description */
2024 if (!event->desc)
2025 return 0;
2026 /* Bytecode already linked */
2027 if (event->filter || event->filter_data)
2028 return 0;
2d78951a 2029
a8c27c7c 2030 dbg_printf("Linking\n");
cd54f6d9
MD
2031
2032 /* We don't need the reloc table in the runtime */
2033 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
2034 runtime = zmalloc(runtime_alloc_len);
2035 if (!runtime) {
2036 ret = -ENOMEM;
2037 goto link_error;
2038 }
2039 runtime->len = filter_bytecode->reloc_offset;
2040 /* copy original bytecode */
2041 memcpy(runtime->data, filter_bytecode->data, runtime->len);
2042 /*
2043 * apply relocs. Those are a uint16_t (offset in bytecode)
2044 * followed by a string (field name).
2045 */
cd54f6d9
MD
2046 for (offset = filter_bytecode->reloc_offset;
2047 offset < filter_bytecode->len;
2048 offset = next_offset) {
2049 uint16_t reloc_offset =
2050 *(uint16_t *) &filter_bytecode->data[offset];
2051 const char *field_name =
2052 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
2053
2054 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
2055 if (ret) {
2056 goto link_error;
2057 }
2058 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
2059 }
9522a886
MD
2060 /* Validate bytecode */
2061 ret = lttng_filter_validate_bytecode(runtime);
2062 if (ret) {
2063 goto link_error;
2064 }
08c84b15
MD
2065 /* Specialize bytecode */
2066 ret = lttng_filter_specialize_bytecode(runtime);
2067 if (ret) {
2068 goto link_error;
2069 }
cd54f6d9 2070 event->filter_data = runtime;
2d78951a 2071 event->filter = lttng_filter_interpret_bytecode;
2d78951a 2072 return 0;
cd54f6d9
MD
2073
2074link_error:
2075 event->filter = lttng_filter_false;
2076 free(runtime);
2077 return ret;
2d78951a
MD
2078}
2079
2080void lttng_filter_event_link_bytecode(struct ltt_event *event,
2081 struct lttng_ust_filter_bytecode *filter_bytecode)
2082{
2083 int ret;
2084
cd54f6d9 2085 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
2d78951a
MD
2086 if (ret) {
2087 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
2088 }
2089}
2090
2091/*
2092 * Link bytecode to all events for a wildcard. Skips events that already
2093 * have a bytecode linked.
2094 * We do not set each event's filter_bytecode field, because they do not
2095 * own the filter_bytecode: the wildcard owns it.
2096 */
2097void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
2098{
2099 struct ltt_event *event;
2100 int ret;
2101
2102 if (!wildcard->filter_bytecode)
2103 return;
2104
2105 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
2106 if (event->filter)
2107 continue;
2108 ret = _lttng_filter_event_link_bytecode(event,
2109 wildcard->filter_bytecode);
2110 if (ret) {
2111 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
2112 }
2113
2114 }
2115 return;
2116}
2117
2118/*
2119 * Need to attach filter to an event before starting tracing for the
cd54f6d9 2120 * session. We own the filter_bytecode if we return success.
2d78951a
MD
2121 */
2122int lttng_filter_event_attach_bytecode(struct ltt_event *event,
2123 struct lttng_ust_filter_bytecode *filter_bytecode)
2124{
2d78951a
MD
2125 if (event->chan->session->been_active)
2126 return -EPERM;
2127 if (event->filter_bytecode)
2128 return -EEXIST;
cd54f6d9 2129 event->filter_bytecode = filter_bytecode;
2d78951a
MD
2130 return 0;
2131}
2132
2133/*
2134 * Need to attach filter to a wildcard before starting tracing for the
cd54f6d9 2135 * session. We own the filter_bytecode if we return success.
2d78951a
MD
2136 */
2137int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
2138 struct lttng_ust_filter_bytecode *filter_bytecode)
2139{
2d78951a
MD
2140 if (wildcard->chan->session->been_active)
2141 return -EPERM;
2142 if (wildcard->filter_bytecode)
2143 return -EEXIST;
cd54f6d9 2144 wildcard->filter_bytecode = filter_bytecode;
2d78951a
MD
2145 return 0;
2146}
This page took 0.113914 seconds and 4 git commands to generate.