Filter: Specialize unary operators
[lttng-ust.git] / liblttng-ust / lttng-filter.c
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>
27 #include <stdint.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <inttypes.h>
31 #include <limits.h>
32 #include <usterr-signal-safe.h>
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...) \
54 do { \
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 */
62 struct bytecode_runtime {
63 uint16_t len;
64 char data[0];
65 };
66
67 enum reg_type {
68 REG_S64,
69 REG_DOUBLE,
70 REG_STRING,
71 REG_TYPE_UNKNOWN,
72 };
73
74 /* Validation registers */
75 struct vreg {
76 enum reg_type type;
77 int literal; /* is string literal ? */
78 };
79
80 /* Execution registers */
81 struct reg {
82 enum reg_type type;
83 int64_t v;
84 double d;
85
86 const char *str;
87 size_t seq_len;
88 int literal; /* is string literal ? */
89 };
90
91 static 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",
107
108 /* binary comparators */
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
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
141 /* unary */
142 [ FILTER_OP_UNARY_PLUS ] = "UNARY_PLUS",
143 [ FILTER_OP_UNARY_MINUS ] = "UNARY_MINUS",
144 [ FILTER_OP_UNARY_NOT ] = "UNARY_NOT",
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",
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",
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
163 [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
164 [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
165 [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
166 };
167
168 static
169 const char *print_op(enum filter_op op)
170 {
171 if (op >= NR_FILTER_OPS)
172 return "UNKNOWN";
173 else
174 return opnames[op];
175 }
176
177 /*
178 * -1: wildcard found.
179 * -2: unknown escape char.
180 * 0: normal char.
181 */
182
183 static
184 int parse_char(const char **p)
185 {
186 switch (**p) {
187 case '\\':
188 (*p)++;
189 switch (**p) {
190 case '\\':
191 case '*':
192 return 0;
193 default:
194 return -2;
195 }
196 case '*':
197 return -1;
198 default:
199 return 0;
200 }
201 }
202
203 static
204 int reg_strcmp(struct reg reg[NR_REG], const char *cmp_type)
205 {
206 const char *p = reg[REG_R0].str, *q = reg[REG_R1].str;
207 int ret;
208 int diff;
209
210 for (;;) {
211 int escaped_r0 = 0;
212
213 if (unlikely(p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')) {
214 if (q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')
215 diff = 0;
216 else
217 diff = -1;
218 break;
219 }
220 if (unlikely(q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')) {
221 if (p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')
222 diff = 0;
223 else
224 diff = 1;
225 break;
226 }
227 if (reg[REG_R0].literal) {
228 ret = parse_char(&p);
229 if (ret == -1) {
230 return 0;
231 } else if (ret == -2) {
232 escaped_r0 = 1;
233 }
234 /* else compare both char */
235 }
236 if (reg[REG_R1].literal) {
237 ret = parse_char(&q);
238 if (ret == -1) {
239 return 0;
240 } else if (ret == -2) {
241 if (!escaped_r0)
242 return -1;
243 } else {
244 if (escaped_r0)
245 return 1;
246 }
247 } else {
248 if (escaped_r0)
249 return 1;
250 }
251 diff = *p - *q;
252 if (diff != 0)
253 break;
254 p++;
255 q++;
256 }
257 return diff;
258 }
259
260 static
261 int lttng_filter_false(void *filter_data,
262 const char *filter_stack_data)
263 {
264 return 0;
265 }
266
267 #define INTERPRETER_USE_SWITCH
268
269 #ifdef INTERPRETER_USE_SWITCH
270
271 #define START_OP \
272 start_pc = &bytecode->data[0]; \
273 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
274 pc = next_pc) { \
275 dbg_printf("Executing op %s (%u)\n", \
276 print_op((unsigned int) *(filter_opcode_t *) pc), \
277 (unsigned int) *(filter_opcode_t *) pc); \
278 switch (*(filter_opcode_t *) pc) {
279
280 #define OP(name) case name
281
282 #define PO break
283
284 #define END_OP } \
285 }
286
287 #else
288
289 #define OP(name)
290
291 #endif
292
293 static
294 int lttng_filter_interpret_bytecode(void *filter_data,
295 const char *filter_stack_data)
296 {
297 struct bytecode_runtime *bytecode = filter_data;
298 void *pc, *next_pc, *start_pc;
299 int ret = -EINVAL;
300 int retval = 0;
301 struct reg reg[NR_REG];
302 #ifndef INTERPRETER_USE_SWITCH
303 static void *dispatch[NR_FILTER_OPS] = {
304 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN = 0,
305
306 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
307
308 /* binary */
309 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
310 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
311 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
312 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
313 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
314 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
315 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
316 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
317 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
318 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
319
320 /* binary comparators */
321 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
322 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
323 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
324 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
325 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
326 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
327
328 /* string binary comparator */
329 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
330 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
331 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
332 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
333 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
334 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
335
336 /* s64 binary comparator */
337 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
338 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
339 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
340 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
341 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
342 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
343
344 /* double binary comparator */
345 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
346 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
347 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
348 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
349 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
350 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
351
352 /* unary */
353 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
354 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
355 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
356 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
357 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
358 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
359 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
360 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
361 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
362
363 /* logical */
364 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
365 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
366
367 /* load */
368 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
369 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
370 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
371 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
372 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
373
374 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
375 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
376 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
377 };
378 #endif /* #ifndef INTERPRETER_USE_SWITCH */
379
380 START_OP
381
382 OP(FILTER_OP_UNKNOWN):
383 OP(FILTER_OP_LOAD_FIELD_REF):
384 #ifdef INTERPRETER_USE_SWITCH
385 default:
386 #endif /* INTERPRETER_USE_SWITCH */
387 ERR("unknown bytecode op %u\n",
388 (unsigned int) *(filter_opcode_t *) pc);
389 ret = -EINVAL;
390 goto end;
391
392 OP(FILTER_OP_RETURN):
393 retval = !!reg[0].v;
394 ret = 0;
395 goto end;
396
397 /* binary */
398 OP(FILTER_OP_MUL):
399 OP(FILTER_OP_DIV):
400 OP(FILTER_OP_MOD):
401 OP(FILTER_OP_PLUS):
402 OP(FILTER_OP_MINUS):
403 OP(FILTER_OP_RSHIFT):
404 OP(FILTER_OP_LSHIFT):
405 OP(FILTER_OP_BIN_AND):
406 OP(FILTER_OP_BIN_OR):
407 OP(FILTER_OP_BIN_XOR):
408 ERR("unsupported bytecode op %u\n",
409 (unsigned int) *(filter_opcode_t *) pc);
410 ret = -EINVAL;
411 goto end;
412
413 OP(FILTER_OP_EQ):
414 OP(FILTER_OP_NE):
415 OP(FILTER_OP_GT):
416 OP(FILTER_OP_LT):
417 OP(FILTER_OP_GE):
418 OP(FILTER_OP_LE):
419 ERR("unsupported non-specialized bytecode op %u\n",
420 (unsigned int) *(filter_opcode_t *) pc);
421 ret = -EINVAL;
422 goto end;
423
424 OP(FILTER_OP_EQ_STRING):
425 {
426 reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
427 reg[REG_R0].type = REG_S64;
428 next_pc += sizeof(struct binary_op);
429 PO;
430 }
431 OP(FILTER_OP_NE_STRING):
432 {
433 reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
434 reg[REG_R0].type = REG_S64;
435 next_pc += sizeof(struct binary_op);
436 PO;
437 }
438 OP(FILTER_OP_GT_STRING):
439 {
440 reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
441 reg[REG_R0].type = REG_S64;
442 next_pc += sizeof(struct binary_op);
443 PO;
444 }
445 OP(FILTER_OP_LT_STRING):
446 {
447 reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
448 reg[REG_R0].type = REG_S64;
449 next_pc += sizeof(struct binary_op);
450 PO;
451 }
452 OP(FILTER_OP_GE_STRING):
453 {
454 reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
455 reg[REG_R0].type = REG_S64;
456 next_pc += sizeof(struct binary_op);
457 PO;
458 }
459 OP(FILTER_OP_LE_STRING):
460 {
461 reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
462 reg[REG_R0].type = REG_S64;
463 next_pc += sizeof(struct binary_op);
464 PO;
465 }
466
467 OP(FILTER_OP_EQ_S64):
468 {
469 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
470 reg[REG_R0].type = REG_S64;
471 next_pc += sizeof(struct binary_op);
472 PO;
473 }
474 OP(FILTER_OP_NE_S64):
475 {
476 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
477 reg[REG_R0].type = REG_S64;
478 next_pc += sizeof(struct binary_op);
479 PO;
480 }
481 OP(FILTER_OP_GT_S64):
482 {
483 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
484 reg[REG_R0].type = REG_S64;
485 next_pc += sizeof(struct binary_op);
486 PO;
487 }
488 OP(FILTER_OP_LT_S64):
489 {
490 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
491 reg[REG_R0].type = REG_S64;
492 next_pc += sizeof(struct binary_op);
493 PO;
494 }
495 OP(FILTER_OP_GE_S64):
496 {
497 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
498 reg[REG_R0].type = REG_S64;
499 next_pc += sizeof(struct binary_op);
500 PO;
501 }
502 OP(FILTER_OP_LE_S64):
503 {
504 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
505 reg[REG_R0].type = REG_S64;
506 next_pc += sizeof(struct binary_op);
507 PO;
508 }
509
510 OP(FILTER_OP_EQ_DOUBLE):
511 {
512 if (unlikely(reg[REG_R0].type == REG_S64))
513 reg[REG_R0].d = (double) reg[REG_R0].v;
514 else if (unlikely(reg[REG_R1].type == REG_S64))
515 reg[REG_R1].d = (double) reg[REG_R1].v;
516 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
517 reg[REG_R0].type = REG_S64;
518 next_pc += sizeof(struct binary_op);
519 PO;
520 }
521 OP(FILTER_OP_NE_DOUBLE):
522 {
523 if (unlikely(reg[REG_R0].type == REG_S64))
524 reg[REG_R0].d = (double) reg[REG_R0].v;
525 else if (unlikely(reg[REG_R1].type == REG_S64))
526 reg[REG_R1].d = (double) reg[REG_R1].v;
527 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
528 reg[REG_R0].type = REG_S64;
529 next_pc += sizeof(struct binary_op);
530 PO;
531 }
532 OP(FILTER_OP_GT_DOUBLE):
533 {
534 if (unlikely(reg[REG_R0].type == REG_S64))
535 reg[REG_R0].d = (double) reg[REG_R0].v;
536 else if (unlikely(reg[REG_R1].type == REG_S64))
537 reg[REG_R1].d = (double) reg[REG_R1].v;
538 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
539 reg[REG_R0].type = REG_S64;
540 next_pc += sizeof(struct binary_op);
541 PO;
542 }
543 OP(FILTER_OP_LT_DOUBLE):
544 {
545 if (unlikely(reg[REG_R0].type == REG_S64))
546 reg[REG_R0].d = (double) reg[REG_R0].v;
547 else if (unlikely(reg[REG_R1].type == REG_S64))
548 reg[REG_R1].d = (double) reg[REG_R1].v;
549 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
550 reg[REG_R0].type = REG_S64;
551 next_pc += sizeof(struct binary_op);
552 PO;
553 }
554 OP(FILTER_OP_GE_DOUBLE):
555 {
556 if (unlikely(reg[REG_R0].type == REG_S64))
557 reg[REG_R0].d = (double) reg[REG_R0].v;
558 else if (unlikely(reg[REG_R1].type == REG_S64))
559 reg[REG_R1].d = (double) reg[REG_R1].v;
560 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
561 reg[REG_R0].type = REG_S64;
562 next_pc += sizeof(struct binary_op);
563 PO;
564 }
565 OP(FILTER_OP_LE_DOUBLE):
566 {
567 if (unlikely(reg[REG_R0].type == REG_S64))
568 reg[REG_R0].d = (double) reg[REG_R0].v;
569 else if (unlikely(reg[REG_R1].type == REG_S64))
570 reg[REG_R1].d = (double) reg[REG_R1].v;
571 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].d);
572 reg[REG_R0].type = REG_S64;
573 next_pc += sizeof(struct binary_op);
574 PO;
575 }
576
577 /* unary */
578 OP(FILTER_OP_UNARY_PLUS):
579 OP(FILTER_OP_UNARY_MINUS):
580 OP(FILTER_OP_UNARY_NOT):
581 ERR("unsupported non-specialized bytecode op %u\n",
582 (unsigned int) *(filter_opcode_t *) pc);
583 ret = -EINVAL;
584 goto end;
585
586
587 OP(FILTER_OP_UNARY_PLUS_S64):
588 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
589 {
590 next_pc += sizeof(struct unary_op);
591 PO;
592 }
593 OP(FILTER_OP_UNARY_MINUS_S64):
594 {
595 struct unary_op *insn = (struct unary_op *) pc;
596
597 reg[insn->reg].v = -reg[insn->reg].v;
598 next_pc += sizeof(struct unary_op);
599 PO;
600 }
601 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
602 {
603 struct unary_op *insn = (struct unary_op *) pc;
604
605 reg[insn->reg].d = -reg[insn->reg].d;
606 next_pc += sizeof(struct unary_op);
607 PO;
608 }
609 OP(FILTER_OP_UNARY_NOT_S64):
610 {
611 struct unary_op *insn = (struct unary_op *) pc;
612
613 reg[insn->reg].v = !reg[insn->reg].v;
614 next_pc += sizeof(struct unary_op);
615 PO;
616 }
617 OP(FILTER_OP_UNARY_NOT_DOUBLE):
618 {
619 struct unary_op *insn = (struct unary_op *) pc;
620
621 reg[insn->reg].d = !reg[insn->reg].d;
622 next_pc += sizeof(struct unary_op);
623 PO;
624 }
625
626 /* logical */
627 OP(FILTER_OP_AND):
628 {
629 struct logical_op *insn = (struct logical_op *) pc;
630
631 /* If REG_R0 is 0, skip and evaluate to 0 */
632 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v == 0)
633 || unlikely(reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d == 0.0)) {
634 dbg_printf("Jumping to bytecode offset %u\n",
635 (unsigned int) insn->skip_offset);
636 next_pc = start_pc + insn->skip_offset;
637 } else {
638 next_pc += sizeof(struct logical_op);
639 }
640 PO;
641 }
642 OP(FILTER_OP_OR):
643 {
644 struct logical_op *insn = (struct logical_op *) pc;
645
646 /* If REG_R0 is nonzero, skip and evaluate to 1 */
647
648 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v != 0)
649 || unlikely(reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d != 0.0)) {
650 reg[REG_R0].v = 1;
651 dbg_printf("Jumping to bytecode offset %u\n",
652 (unsigned int) insn->skip_offset);
653 next_pc = start_pc + insn->skip_offset;
654 } else {
655 next_pc += sizeof(struct logical_op);
656 }
657 PO;
658 }
659
660 /* load */
661 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
662 {
663 struct load_op *insn = (struct load_op *) pc;
664 struct field_ref *ref = (struct field_ref *) insn->data;
665
666 dbg_printf("load field ref offset %u type string\n",
667 ref->offset);
668 reg[insn->reg].str =
669 *(const char * const *) &filter_stack_data[ref->offset];
670 reg[insn->reg].type = REG_STRING;
671 reg[insn->reg].seq_len = UINT_MAX;
672 reg[insn->reg].literal = 0;
673 dbg_printf("ref load string %s\n", reg[insn->reg].str);
674 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
675 PO;
676 }
677
678 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
679 {
680 struct load_op *insn = (struct load_op *) pc;
681 struct field_ref *ref = (struct field_ref *) insn->data;
682
683 dbg_printf("load field ref offset %u type sequence\n",
684 ref->offset);
685 reg[insn->reg].seq_len =
686 *(unsigned long *) &filter_stack_data[ref->offset];
687 reg[insn->reg].str =
688 *(const char **) (&filter_stack_data[ref->offset
689 + sizeof(unsigned long)]);
690 reg[insn->reg].type = REG_STRING;
691 reg[insn->reg].literal = 0;
692 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
693 PO;
694 }
695
696 OP(FILTER_OP_LOAD_FIELD_REF_S64):
697 {
698 struct load_op *insn = (struct load_op *) pc;
699 struct field_ref *ref = (struct field_ref *) insn->data;
700
701 dbg_printf("load field ref offset %u type s64\n",
702 ref->offset);
703 memcpy(&reg[insn->reg].v, &filter_stack_data[ref->offset],
704 sizeof(struct literal_numeric));
705 reg[insn->reg].type = REG_S64;
706 reg[insn->reg].literal = 0;
707 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
708 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
709 PO;
710 }
711
712 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
713 {
714 struct load_op *insn = (struct load_op *) pc;
715 struct field_ref *ref = (struct field_ref *) insn->data;
716
717 dbg_printf("load field ref offset %u type double\n",
718 ref->offset);
719 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
720 sizeof(struct literal_double));
721 reg[insn->reg].type = REG_DOUBLE;
722 reg[insn->reg].literal = 0;
723 dbg_printf("ref load double %g\n", reg[insn->reg].d);
724 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
725 PO;
726 }
727
728 OP(FILTER_OP_LOAD_STRING):
729 {
730 struct load_op *insn = (struct load_op *) pc;
731
732 dbg_printf("load string %s\n", insn->data);
733 reg[insn->reg].str = insn->data;
734 reg[insn->reg].type = REG_STRING;
735 reg[insn->reg].seq_len = UINT_MAX;
736 reg[insn->reg].literal = 1;
737 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
738 PO;
739 }
740
741 OP(FILTER_OP_LOAD_S64):
742 {
743 struct load_op *insn = (struct load_op *) pc;
744
745 memcpy(&reg[insn->reg].v, insn->data,
746 sizeof(struct literal_numeric));
747 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
748 reg[insn->reg].type = REG_S64;
749 reg[insn->reg].literal = 1;
750 next_pc += sizeof(struct load_op)
751 + sizeof(struct literal_numeric);
752 PO;
753 }
754
755 OP(FILTER_OP_LOAD_DOUBLE):
756 {
757 struct load_op *insn = (struct load_op *) pc;
758
759 memcpy(&reg[insn->reg].d, insn->data,
760 sizeof(struct literal_double));
761 dbg_printf("load s64 %g\n", reg[insn->reg].d);
762 reg[insn->reg].type = REG_DOUBLE;
763 reg[insn->reg].literal = 1;
764 next_pc += sizeof(struct load_op)
765 + sizeof(struct literal_double);
766 PO;
767 }
768
769 END_OP
770 end:
771 /* return 0 (discard) on error */
772 if (ret)
773 return 0;
774 return retval;
775 }
776
777 static
778 int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
779 {
780 switch (reg[REG_R0].type) {
781 default:
782 goto error_unknown;
783
784 case REG_STRING:
785 switch (reg[REG_R1].type) {
786 default:
787 goto error_unknown;
788
789 case REG_STRING:
790 break;
791 case REG_S64:
792 case REG_DOUBLE:
793 goto error_mismatch;
794 }
795 break;
796 case REG_S64:
797 case REG_DOUBLE:
798 switch (reg[REG_R1].type) {
799 default:
800 goto error_unknown;
801
802 case REG_STRING:
803 goto error_mismatch;
804
805 case REG_S64:
806 case REG_DOUBLE:
807 break;
808 }
809 break;
810 }
811 return 0;
812
813 error_unknown:
814
815 return -EINVAL;
816 error_mismatch:
817 ERR("type mismatch for '%s' binary operator\n", str);
818 return -EINVAL;
819 }
820
821 static
822 int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
823 {
824 void *pc, *next_pc, *start_pc;
825 int ret = -EINVAL;
826 struct vreg reg[NR_REG];
827 int i;
828
829 for (i = 0; i < NR_REG; i++) {
830 reg[i].type = REG_TYPE_UNKNOWN;
831 reg[i].literal = 0;
832 }
833
834 start_pc = &bytecode->data[0];
835 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
836 pc = next_pc) {
837 if (unlikely(pc >= start_pc + bytecode->len)) {
838 ERR("filter bytecode overflow\n");
839 ret = -EINVAL;
840 goto end;
841 }
842 dbg_printf("Validating op %s (%u)\n",
843 print_op((unsigned int) *(filter_opcode_t *) pc),
844 (unsigned int) *(filter_opcode_t *) pc);
845 switch (*(filter_opcode_t *) pc) {
846 case FILTER_OP_UNKNOWN:
847 default:
848 ERR("unknown bytecode op %u\n",
849 (unsigned int) *(filter_opcode_t *) pc);
850 ret = -EINVAL;
851 goto end;
852
853 case FILTER_OP_RETURN:
854 ret = 0;
855 goto end;
856
857 /* binary */
858 case FILTER_OP_MUL:
859 case FILTER_OP_DIV:
860 case FILTER_OP_MOD:
861 case FILTER_OP_PLUS:
862 case FILTER_OP_MINUS:
863 case FILTER_OP_RSHIFT:
864 case FILTER_OP_LSHIFT:
865 case FILTER_OP_BIN_AND:
866 case FILTER_OP_BIN_OR:
867 case FILTER_OP_BIN_XOR:
868 ERR("unsupported bytecode op %u\n",
869 (unsigned int) *(filter_opcode_t *) pc);
870 ret = -EINVAL;
871 goto end;
872
873 case FILTER_OP_EQ:
874 {
875 ret = bin_op_compare_check(reg, "==");
876 if (ret)
877 goto end;
878 reg[REG_R0].type = REG_S64;
879 next_pc += sizeof(struct binary_op);
880 break;
881 }
882 case FILTER_OP_NE:
883 {
884 ret = bin_op_compare_check(reg, "!=");
885 if (ret)
886 goto end;
887 reg[REG_R0].type = REG_S64;
888 next_pc += sizeof(struct binary_op);
889 break;
890 }
891 case FILTER_OP_GT:
892 {
893 ret = bin_op_compare_check(reg, ">");
894 if (ret)
895 goto end;
896 reg[REG_R0].type = REG_S64;
897 next_pc += sizeof(struct binary_op);
898 break;
899 }
900 case FILTER_OP_LT:
901 {
902 ret = bin_op_compare_check(reg, "<");
903 if (ret)
904 goto end;
905 reg[REG_R0].type = REG_S64;
906 next_pc += sizeof(struct binary_op);
907 break;
908 }
909 case FILTER_OP_GE:
910 {
911 ret = bin_op_compare_check(reg, ">=");
912 if (ret)
913 goto end;
914 reg[REG_R0].type = REG_S64;
915 next_pc += sizeof(struct binary_op);
916 break;
917 }
918 case FILTER_OP_LE:
919 {
920 ret = bin_op_compare_check(reg, "<=");
921 if (ret)
922 goto end;
923 reg[REG_R0].type = REG_S64;
924 next_pc += sizeof(struct binary_op);
925 break;
926 }
927
928 case FILTER_OP_EQ_STRING:
929 case FILTER_OP_NE_STRING:
930 case FILTER_OP_GT_STRING:
931 case FILTER_OP_LT_STRING:
932 case FILTER_OP_GE_STRING:
933 case FILTER_OP_LE_STRING:
934 {
935 if (reg[REG_R0].type != REG_STRING
936 || reg[REG_R1].type != REG_STRING) {
937 ERR("Unexpected register type for string comparator\n");
938 ret = -EINVAL;
939 goto end;
940 }
941 reg[REG_R0].type = REG_S64;
942 next_pc += sizeof(struct binary_op);
943 break;
944 }
945
946 case FILTER_OP_EQ_S64:
947 case FILTER_OP_NE_S64:
948 case FILTER_OP_GT_S64:
949 case FILTER_OP_LT_S64:
950 case FILTER_OP_GE_S64:
951 case FILTER_OP_LE_S64:
952 {
953 if (reg[REG_R0].type != REG_S64
954 || reg[REG_R1].type != REG_S64) {
955 ERR("Unexpected register type for s64 comparator\n");
956 ret = -EINVAL;
957 goto end;
958 }
959 reg[REG_R0].type = REG_S64;
960 next_pc += sizeof(struct binary_op);
961 break;
962 }
963
964 case FILTER_OP_EQ_DOUBLE:
965 case FILTER_OP_NE_DOUBLE:
966 case FILTER_OP_GT_DOUBLE:
967 case FILTER_OP_LT_DOUBLE:
968 case FILTER_OP_GE_DOUBLE:
969 case FILTER_OP_LE_DOUBLE:
970 {
971 if ((reg[REG_R0].type != REG_DOUBLE && reg[REG_R0].type != REG_S64)
972 || (reg[REG_R1].type != REG_DOUBLE && reg[REG_R1].type != REG_S64)) {
973 ERR("Unexpected register type for double comparator\n");
974 ret = -EINVAL;
975 goto end;
976 }
977 reg[REG_R0].type = REG_DOUBLE;
978 next_pc += sizeof(struct binary_op);
979 break;
980 }
981
982 /* unary */
983 case FILTER_OP_UNARY_PLUS:
984 case FILTER_OP_UNARY_MINUS:
985 case FILTER_OP_UNARY_NOT:
986 {
987 struct unary_op *insn = (struct unary_op *) pc;
988
989 if (unlikely(insn->reg >= REG_ERROR)) {
990 ERR("invalid register %u\n",
991 (unsigned int) insn->reg);
992 ret = -EINVAL;
993 goto end;
994 }
995 switch (reg[insn->reg].type) {
996 default:
997 ERR("unknown register type\n");
998 ret = -EINVAL;
999 goto end;
1000
1001 case REG_STRING:
1002 ERR("Unary op can only be applied to numeric or floating point registers\n");
1003 ret = -EINVAL;
1004 goto end;
1005 case REG_S64:
1006 break;
1007 case REG_DOUBLE:
1008 break;
1009 }
1010 next_pc += sizeof(struct unary_op);
1011 break;
1012 }
1013
1014 case FILTER_OP_UNARY_PLUS_S64:
1015 case FILTER_OP_UNARY_MINUS_S64:
1016 case FILTER_OP_UNARY_NOT_S64:
1017 {
1018 struct unary_op *insn = (struct unary_op *) pc;
1019
1020 if (unlikely(insn->reg >= REG_ERROR)) {
1021 ERR("invalid register %u\n",
1022 (unsigned int) insn->reg);
1023 ret = -EINVAL;
1024 goto end;
1025 }
1026 if (reg[insn->reg].type != REG_S64) {
1027 ERR("Invalid register type\n");
1028 ret = -EINVAL;
1029 goto end;
1030 }
1031 next_pc += sizeof(struct unary_op);
1032 break;
1033 }
1034
1035 case FILTER_OP_UNARY_PLUS_DOUBLE:
1036 case FILTER_OP_UNARY_MINUS_DOUBLE:
1037 case FILTER_OP_UNARY_NOT_DOUBLE:
1038 {
1039 struct unary_op *insn = (struct unary_op *) pc;
1040
1041 if (unlikely(insn->reg >= REG_ERROR)) {
1042 ERR("invalid register %u\n",
1043 (unsigned int) insn->reg);
1044 ret = -EINVAL;
1045 goto end;
1046 }
1047 if (reg[insn->reg].type != REG_DOUBLE) {
1048 ERR("Invalid register type\n");
1049 ret = -EINVAL;
1050 goto end;
1051 }
1052 next_pc += sizeof(struct unary_op);
1053 break;
1054 }
1055
1056 /* logical */
1057 case FILTER_OP_AND:
1058 case FILTER_OP_OR:
1059 {
1060 struct logical_op *insn = (struct logical_op *) pc;
1061
1062 if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
1063 || reg[REG_R1].type == REG_TYPE_UNKNOWN
1064 || reg[REG_R0].type == REG_STRING
1065 || reg[REG_R1].type == REG_STRING)) {
1066 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
1067 ret = -EINVAL;
1068 goto end;
1069 }
1070
1071 dbg_printf("Validate jumping to bytecode offset %u\n",
1072 (unsigned int) insn->skip_offset);
1073 if (unlikely(start_pc + insn->skip_offset <= pc)) {
1074 ERR("Loops are not allowed in bytecode\n");
1075 ret = -EINVAL;
1076 goto end;
1077 }
1078 next_pc += sizeof(struct logical_op);
1079 break;
1080 }
1081
1082 /* load */
1083 case FILTER_OP_LOAD_FIELD_REF:
1084 {
1085 ERR("Unknown field ref type\n");
1086 ret = -EINVAL;
1087 goto end;
1088 }
1089 case FILTER_OP_LOAD_FIELD_REF_STRING:
1090 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1091 {
1092 struct load_op *insn = (struct load_op *) pc;
1093 struct field_ref *ref = (struct field_ref *) insn->data;
1094
1095 if (unlikely(insn->reg >= REG_ERROR)) {
1096 ERR("invalid register %u\n",
1097 (unsigned int) insn->reg);
1098 ret = -EINVAL;
1099 goto end;
1100 }
1101 dbg_printf("Validate load field ref offset %u type string\n",
1102 ref->offset);
1103 reg[insn->reg].type = REG_STRING;
1104 reg[insn->reg].literal = 0;
1105 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1106 break;
1107 }
1108 case FILTER_OP_LOAD_FIELD_REF_S64:
1109 {
1110 struct load_op *insn = (struct load_op *) pc;
1111 struct field_ref *ref = (struct field_ref *) insn->data;
1112
1113 if (unlikely(insn->reg >= REG_ERROR)) {
1114 ERR("invalid register %u\n",
1115 (unsigned int) insn->reg);
1116 ret = -EINVAL;
1117 goto end;
1118 }
1119 dbg_printf("Validate load field ref offset %u type s64\n",
1120 ref->offset);
1121 reg[insn->reg].type = REG_S64;
1122 reg[insn->reg].literal = 0;
1123 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1124 break;
1125 }
1126 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1127 {
1128 struct load_op *insn = (struct load_op *) pc;
1129 struct field_ref *ref = (struct field_ref *) insn->data;
1130
1131 if (unlikely(insn->reg >= REG_ERROR)) {
1132 ERR("invalid register %u\n",
1133 (unsigned int) insn->reg);
1134 ret = -EINVAL;
1135 goto end;
1136 }
1137 dbg_printf("Validate load field ref offset %u type double\n",
1138 ref->offset);
1139 reg[insn->reg].type = REG_DOUBLE;
1140 reg[insn->reg].literal = 0;
1141 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1142 break;
1143 }
1144
1145 case FILTER_OP_LOAD_STRING:
1146 {
1147 struct load_op *insn = (struct load_op *) pc;
1148
1149 if (unlikely(insn->reg >= REG_ERROR)) {
1150 ERR("invalid register %u\n",
1151 (unsigned int) insn->reg);
1152 ret = -EINVAL;
1153 goto end;
1154 }
1155 reg[insn->reg].type = REG_STRING;
1156 reg[insn->reg].literal = 1;
1157 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1158 break;
1159 }
1160
1161 case FILTER_OP_LOAD_S64:
1162 {
1163 struct load_op *insn = (struct load_op *) pc;
1164
1165 if (unlikely(insn->reg >= REG_ERROR)) {
1166 ERR("invalid register %u\n",
1167 (unsigned int) insn->reg);
1168 ret = -EINVAL;
1169 goto end;
1170 }
1171 reg[insn->reg].type = REG_S64;
1172 reg[insn->reg].literal = 1;
1173 next_pc += sizeof(struct load_op)
1174 + sizeof(struct literal_numeric);
1175 break;
1176 }
1177
1178 case FILTER_OP_LOAD_DOUBLE:
1179 {
1180 struct load_op *insn = (struct load_op *) pc;
1181
1182 if (unlikely(insn->reg >= REG_ERROR)) {
1183 ERR("invalid register %u\n",
1184 (unsigned int) insn->reg);
1185 ret = -EINVAL;
1186 goto end;
1187 }
1188 reg[insn->reg].type = REG_DOUBLE;
1189 reg[insn->reg].literal = 1;
1190 next_pc += sizeof(struct load_op)
1191 + sizeof(struct literal_double);
1192 break;
1193 }
1194 }
1195 }
1196 end:
1197 return ret;
1198 }
1199
1200 static
1201 int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
1202 {
1203 void *pc, *next_pc, *start_pc;
1204 int ret = -EINVAL;
1205 struct vreg reg[NR_REG];
1206 int i;
1207
1208 for (i = 0; i < NR_REG; i++) {
1209 reg[i].type = REG_TYPE_UNKNOWN;
1210 reg[i].literal = 0;
1211 }
1212
1213 start_pc = &bytecode->data[0];
1214 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1215 pc = next_pc) {
1216 switch (*(filter_opcode_t *) pc) {
1217 case FILTER_OP_UNKNOWN:
1218 default:
1219 ERR("unknown bytecode op %u\n",
1220 (unsigned int) *(filter_opcode_t *) pc);
1221 ret = -EINVAL;
1222 goto end;
1223
1224 case FILTER_OP_RETURN:
1225 ret = 0;
1226 goto end;
1227
1228 /* binary */
1229 case FILTER_OP_MUL:
1230 case FILTER_OP_DIV:
1231 case FILTER_OP_MOD:
1232 case FILTER_OP_PLUS:
1233 case FILTER_OP_MINUS:
1234 case FILTER_OP_RSHIFT:
1235 case FILTER_OP_LSHIFT:
1236 case FILTER_OP_BIN_AND:
1237 case FILTER_OP_BIN_OR:
1238 case FILTER_OP_BIN_XOR:
1239 ERR("unsupported bytecode op %u\n",
1240 (unsigned int) *(filter_opcode_t *) pc);
1241 ret = -EINVAL;
1242 goto end;
1243
1244 case FILTER_OP_EQ:
1245 {
1246 struct binary_op *insn = (struct binary_op *) pc;
1247
1248 switch(reg[REG_R0].type) {
1249 default:
1250 ERR("unknown register type\n");
1251 ret = -EINVAL;
1252 goto end;
1253
1254 case REG_STRING:
1255 insn->op = FILTER_OP_EQ_STRING;
1256 break;
1257 case REG_S64:
1258 if (reg[REG_R1].type == REG_S64)
1259 insn->op = FILTER_OP_EQ_S64;
1260 else
1261 insn->op = FILTER_OP_EQ_DOUBLE;
1262 break;
1263 case REG_DOUBLE:
1264 insn->op = FILTER_OP_EQ_DOUBLE;
1265 break;
1266 }
1267 reg[REG_R0].type = REG_S64;
1268 next_pc += sizeof(struct binary_op);
1269 break;
1270 }
1271
1272 case FILTER_OP_NE:
1273 {
1274 struct binary_op *insn = (struct binary_op *) pc;
1275
1276 switch(reg[REG_R0].type) {
1277 default:
1278 ERR("unknown register type\n");
1279 ret = -EINVAL;
1280 goto end;
1281
1282 case REG_STRING:
1283 insn->op = FILTER_OP_NE_STRING;
1284 break;
1285 case REG_S64:
1286 if (reg[REG_R1].type == REG_S64)
1287 insn->op = FILTER_OP_NE_S64;
1288 else
1289 insn->op = FILTER_OP_NE_DOUBLE;
1290 break;
1291 case REG_DOUBLE:
1292 insn->op = FILTER_OP_NE_DOUBLE;
1293 break;
1294 }
1295 reg[REG_R0].type = REG_S64;
1296 next_pc += sizeof(struct binary_op);
1297 break;
1298 }
1299
1300 case FILTER_OP_GT:
1301 {
1302 struct binary_op *insn = (struct binary_op *) pc;
1303
1304 switch(reg[REG_R0].type) {
1305 default:
1306 ERR("unknown register type\n");
1307 ret = -EINVAL;
1308 goto end;
1309
1310 case REG_STRING:
1311 insn->op = FILTER_OP_GT_STRING;
1312 break;
1313 case REG_S64:
1314 if (reg[REG_R1].type == REG_S64)
1315 insn->op = FILTER_OP_GT_S64;
1316 else
1317 insn->op = FILTER_OP_GT_DOUBLE;
1318 break;
1319 case REG_DOUBLE:
1320 insn->op = FILTER_OP_GT_DOUBLE;
1321 break;
1322 }
1323 reg[REG_R0].type = REG_S64;
1324 next_pc += sizeof(struct binary_op);
1325 break;
1326 }
1327
1328 case FILTER_OP_LT:
1329 {
1330 struct binary_op *insn = (struct binary_op *) pc;
1331
1332 switch(reg[REG_R0].type) {
1333 default:
1334 ERR("unknown register type\n");
1335 ret = -EINVAL;
1336 goto end;
1337
1338 case REG_STRING:
1339 insn->op = FILTER_OP_LT_STRING;
1340 break;
1341 case REG_S64:
1342 if (reg[REG_R1].type == REG_S64)
1343 insn->op = FILTER_OP_LT_S64;
1344 else
1345 insn->op = FILTER_OP_LT_DOUBLE;
1346 break;
1347 case REG_DOUBLE:
1348 insn->op = FILTER_OP_LT_DOUBLE;
1349 break;
1350 }
1351 reg[REG_R0].type = REG_S64;
1352 next_pc += sizeof(struct binary_op);
1353 break;
1354 }
1355
1356 case FILTER_OP_GE:
1357 {
1358 struct binary_op *insn = (struct binary_op *) pc;
1359
1360 switch(reg[REG_R0].type) {
1361 default:
1362 ERR("unknown register type\n");
1363 ret = -EINVAL;
1364 goto end;
1365
1366 case REG_STRING:
1367 insn->op = FILTER_OP_GE_STRING;
1368 break;
1369 case REG_S64:
1370 if (reg[REG_R1].type == REG_S64)
1371 insn->op = FILTER_OP_GE_S64;
1372 else
1373 insn->op = FILTER_OP_GE_DOUBLE;
1374 break;
1375 case REG_DOUBLE:
1376 insn->op = FILTER_OP_GE_DOUBLE;
1377 break;
1378 }
1379 reg[REG_R0].type = REG_S64;
1380 next_pc += sizeof(struct binary_op);
1381 break;
1382 }
1383 case FILTER_OP_LE:
1384 {
1385 struct binary_op *insn = (struct binary_op *) pc;
1386
1387 switch(reg[REG_R0].type) {
1388 default:
1389 ERR("unknown register type\n");
1390 ret = -EINVAL;
1391 goto end;
1392
1393 case REG_STRING:
1394 insn->op = FILTER_OP_LE_STRING;
1395 break;
1396 case REG_S64:
1397 if (reg[REG_R1].type == REG_S64)
1398 insn->op = FILTER_OP_LE_S64;
1399 else
1400 insn->op = FILTER_OP_LE_DOUBLE;
1401 break;
1402 case REG_DOUBLE:
1403 insn->op = FILTER_OP_LE_DOUBLE;
1404 break;
1405 }
1406 reg[REG_R0].type = REG_S64;
1407 next_pc += sizeof(struct binary_op);
1408 break;
1409 }
1410
1411 case FILTER_OP_EQ_STRING:
1412 case FILTER_OP_NE_STRING:
1413 case FILTER_OP_GT_STRING:
1414 case FILTER_OP_LT_STRING:
1415 case FILTER_OP_GE_STRING:
1416 case FILTER_OP_LE_STRING:
1417 case FILTER_OP_EQ_S64:
1418 case FILTER_OP_NE_S64:
1419 case FILTER_OP_GT_S64:
1420 case FILTER_OP_LT_S64:
1421 case FILTER_OP_GE_S64:
1422 case FILTER_OP_LE_S64:
1423 case FILTER_OP_EQ_DOUBLE:
1424 case FILTER_OP_NE_DOUBLE:
1425 case FILTER_OP_GT_DOUBLE:
1426 case FILTER_OP_LT_DOUBLE:
1427 case FILTER_OP_GE_DOUBLE:
1428 case FILTER_OP_LE_DOUBLE:
1429 {
1430 reg[REG_R0].type = REG_S64;
1431 next_pc += sizeof(struct binary_op);
1432 break;
1433 }
1434
1435 /* unary */
1436 case FILTER_OP_UNARY_PLUS:
1437 {
1438 struct unary_op *insn = (struct unary_op *) pc;
1439
1440 switch(reg[insn->reg].type) {
1441 default:
1442 ERR("unknown register type\n");
1443 ret = -EINVAL;
1444 goto end;
1445
1446 case REG_S64:
1447 insn->op = FILTER_OP_UNARY_PLUS_S64;
1448 break;
1449 case REG_DOUBLE:
1450 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1451 break;
1452 }
1453 break;
1454 }
1455
1456 case FILTER_OP_UNARY_MINUS:
1457 {
1458 struct unary_op *insn = (struct unary_op *) pc;
1459
1460 switch(reg[insn->reg].type) {
1461 default:
1462 ERR("unknown register type\n");
1463 ret = -EINVAL;
1464 goto end;
1465
1466 case REG_S64:
1467 insn->op = FILTER_OP_UNARY_MINUS_S64;
1468 break;
1469 case REG_DOUBLE:
1470 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1471 break;
1472 }
1473 break;
1474 }
1475
1476 case FILTER_OP_UNARY_NOT:
1477 {
1478 struct unary_op *insn = (struct unary_op *) pc;
1479
1480 switch(reg[insn->reg].type) {
1481 default:
1482 ERR("unknown register type\n");
1483 ret = -EINVAL;
1484 goto end;
1485
1486 case REG_S64:
1487 insn->op = FILTER_OP_UNARY_NOT_S64;
1488 break;
1489 case REG_DOUBLE:
1490 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1491 break;
1492 }
1493 break;
1494 }
1495
1496 case FILTER_OP_UNARY_PLUS_S64:
1497 case FILTER_OP_UNARY_MINUS_S64:
1498 case FILTER_OP_UNARY_NOT_S64:
1499 case FILTER_OP_UNARY_PLUS_DOUBLE:
1500 case FILTER_OP_UNARY_MINUS_DOUBLE:
1501 case FILTER_OP_UNARY_NOT_DOUBLE:
1502 {
1503 next_pc += sizeof(struct unary_op);
1504 break;
1505 }
1506
1507 /* logical */
1508 case FILTER_OP_AND:
1509 case FILTER_OP_OR:
1510 {
1511 next_pc += sizeof(struct logical_op);
1512 break;
1513 }
1514
1515 /* load */
1516 case FILTER_OP_LOAD_FIELD_REF:
1517 {
1518 ERR("Unknown field ref type\n");
1519 ret = -EINVAL;
1520 goto end;
1521 }
1522 case FILTER_OP_LOAD_FIELD_REF_STRING:
1523 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1524 {
1525 struct load_op *insn = (struct load_op *) pc;
1526
1527 reg[insn->reg].type = REG_STRING;
1528 reg[insn->reg].literal = 0;
1529 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1530 break;
1531 }
1532 case FILTER_OP_LOAD_FIELD_REF_S64:
1533 {
1534 struct load_op *insn = (struct load_op *) pc;
1535
1536 reg[insn->reg].type = REG_S64;
1537 reg[insn->reg].literal = 0;
1538 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1539 break;
1540 }
1541 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1542 {
1543 struct load_op *insn = (struct load_op *) pc;
1544
1545 reg[insn->reg].type = REG_DOUBLE;
1546 reg[insn->reg].literal = 0;
1547 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1548 break;
1549 }
1550
1551 case FILTER_OP_LOAD_STRING:
1552 {
1553 struct load_op *insn = (struct load_op *) pc;
1554
1555 reg[insn->reg].type = REG_STRING;
1556 reg[insn->reg].literal = 1;
1557 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1558 break;
1559 }
1560
1561 case FILTER_OP_LOAD_S64:
1562 {
1563 struct load_op *insn = (struct load_op *) pc;
1564
1565 reg[insn->reg].type = REG_S64;
1566 reg[insn->reg].literal = 1;
1567 next_pc += sizeof(struct load_op)
1568 + sizeof(struct literal_numeric);
1569 break;
1570 }
1571
1572 case FILTER_OP_LOAD_DOUBLE:
1573 {
1574 struct load_op *insn = (struct load_op *) pc;
1575
1576 reg[insn->reg].type = REG_DOUBLE;
1577 reg[insn->reg].literal = 1;
1578 next_pc += sizeof(struct load_op)
1579 + sizeof(struct literal_double);
1580 break;
1581 }
1582 }
1583 }
1584 end:
1585 return ret;
1586 }
1587
1588
1589
1590 static
1591 int apply_field_reloc(struct ltt_event *event,
1592 struct bytecode_runtime *runtime,
1593 uint32_t runtime_len,
1594 uint32_t reloc_offset,
1595 const char *field_name)
1596 {
1597 const struct lttng_event_desc *desc;
1598 const struct lttng_event_field *fields, *field = NULL;
1599 unsigned int nr_fields, i;
1600 struct field_ref *field_ref;
1601 struct load_op *op;
1602 uint32_t field_offset = 0;
1603
1604 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
1605
1606 /* Ensure that the reloc is within the code */
1607 if (runtime_len - reloc_offset < sizeof(uint16_t))
1608 return -EINVAL;
1609
1610 /* Lookup event by name */
1611 desc = event->desc;
1612 if (!desc)
1613 return -EINVAL;
1614 fields = desc->fields;
1615 if (!fields)
1616 return -EINVAL;
1617 nr_fields = desc->nr_fields;
1618 for (i = 0; i < nr_fields; i++) {
1619 if (!strcmp(fields[i].name, field_name)) {
1620 field = &fields[i];
1621 break;
1622 }
1623 /* compute field offset */
1624 switch (fields[i].type.atype) {
1625 case atype_integer:
1626 case atype_enum:
1627 field_offset += sizeof(int64_t);
1628 break;
1629 case atype_array:
1630 case atype_sequence:
1631 field_offset += sizeof(unsigned long);
1632 field_offset += sizeof(void *);
1633 break;
1634 case atype_string:
1635 field_offset += sizeof(void *);
1636 break;
1637 case atype_float:
1638 field_offset += sizeof(double);
1639 break;
1640 default:
1641 return -EINVAL;
1642 }
1643 }
1644 if (!field)
1645 return -EINVAL;
1646
1647 /* Check if field offset is too large for 16-bit offset */
1648 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1649 return -EINVAL;
1650
1651 /* set type */
1652 op = (struct load_op *) &runtime->data[reloc_offset];
1653 field_ref = (struct field_ref *) op->data;
1654 switch (field->type.atype) {
1655 case atype_integer:
1656 case atype_enum:
1657 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
1658 break;
1659 case atype_array:
1660 case atype_sequence:
1661 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
1662 break;
1663 case atype_string:
1664 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
1665 break;
1666 case atype_float:
1667 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
1668 break;
1669 default:
1670 return -EINVAL;
1671 }
1672 /* set offset */
1673 field_ref->offset = (uint16_t) field_offset;
1674 return 0;
1675 }
1676
1677 /*
1678 * Take a bytecode with reloc table and link it to an event to create a
1679 * bytecode runtime.
1680 */
1681 static
1682 int _lttng_filter_event_link_bytecode(struct ltt_event *event,
1683 struct lttng_ust_filter_bytecode *filter_bytecode)
1684 {
1685 int ret, offset, next_offset;
1686 struct bytecode_runtime *runtime = NULL;
1687 size_t runtime_alloc_len;
1688
1689 if (!filter_bytecode)
1690 return 0;
1691 /* Even is not connected to any description */
1692 if (!event->desc)
1693 return 0;
1694 /* Bytecode already linked */
1695 if (event->filter || event->filter_data)
1696 return 0;
1697
1698 dbg_printf("Linking\n");
1699
1700 /* We don't need the reloc table in the runtime */
1701 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
1702 runtime = zmalloc(runtime_alloc_len);
1703 if (!runtime) {
1704 ret = -ENOMEM;
1705 goto link_error;
1706 }
1707 runtime->len = filter_bytecode->reloc_offset;
1708 /* copy original bytecode */
1709 memcpy(runtime->data, filter_bytecode->data, runtime->len);
1710 /*
1711 * apply relocs. Those are a uint16_t (offset in bytecode)
1712 * followed by a string (field name).
1713 */
1714 for (offset = filter_bytecode->reloc_offset;
1715 offset < filter_bytecode->len;
1716 offset = next_offset) {
1717 uint16_t reloc_offset =
1718 *(uint16_t *) &filter_bytecode->data[offset];
1719 const char *field_name =
1720 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
1721
1722 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
1723 if (ret) {
1724 goto link_error;
1725 }
1726 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
1727 }
1728 /* Validate bytecode */
1729 ret = lttng_filter_validate_bytecode(runtime);
1730 if (ret) {
1731 goto link_error;
1732 }
1733 /* Specialize bytecode */
1734 ret = lttng_filter_specialize_bytecode(runtime);
1735 if (ret) {
1736 goto link_error;
1737 }
1738 event->filter_data = runtime;
1739 event->filter = lttng_filter_interpret_bytecode;
1740 return 0;
1741
1742 link_error:
1743 event->filter = lttng_filter_false;
1744 free(runtime);
1745 return ret;
1746 }
1747
1748 void lttng_filter_event_link_bytecode(struct ltt_event *event,
1749 struct lttng_ust_filter_bytecode *filter_bytecode)
1750 {
1751 int ret;
1752
1753 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
1754 if (ret) {
1755 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
1756 }
1757 }
1758
1759 /*
1760 * Link bytecode to all events for a wildcard. Skips events that already
1761 * have a bytecode linked.
1762 * We do not set each event's filter_bytecode field, because they do not
1763 * own the filter_bytecode: the wildcard owns it.
1764 */
1765 void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
1766 {
1767 struct ltt_event *event;
1768 int ret;
1769
1770 if (!wildcard->filter_bytecode)
1771 return;
1772
1773 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
1774 if (event->filter)
1775 continue;
1776 ret = _lttng_filter_event_link_bytecode(event,
1777 wildcard->filter_bytecode);
1778 if (ret) {
1779 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
1780 }
1781
1782 }
1783 return;
1784 }
1785
1786 /*
1787 * Need to attach filter to an event before starting tracing for the
1788 * session. We own the filter_bytecode if we return success.
1789 */
1790 int lttng_filter_event_attach_bytecode(struct ltt_event *event,
1791 struct lttng_ust_filter_bytecode *filter_bytecode)
1792 {
1793 if (event->chan->session->been_active)
1794 return -EPERM;
1795 if (event->filter_bytecode)
1796 return -EEXIST;
1797 event->filter_bytecode = filter_bytecode;
1798 return 0;
1799 }
1800
1801 /*
1802 * Need to attach filter to a wildcard before starting tracing for the
1803 * session. We own the filter_bytecode if we return success.
1804 */
1805 int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
1806 struct lttng_ust_filter_bytecode *filter_bytecode)
1807 {
1808 if (wildcard->chan->session->been_active)
1809 return -EPERM;
1810 if (wildcard->filter_bytecode)
1811 return -EEXIST;
1812 wildcard->filter_bytecode = filter_bytecode;
1813 return 0;
1814 }
This page took 0.067095 seconds and 5 git commands to generate.