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