Filter: we don't care if double/s64 are literals
[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;
2f0145d1
MD
771 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
772 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 773 PO;
2f0145d1
MD
774 }
775
064220d4 776 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
2f0145d1
MD
777 {
778 struct load_op *insn = (struct load_op *) pc;
779 struct field_ref *ref = (struct field_ref *) insn->data;
780
781 dbg_printf("load field ref offset %u type double\n",
782 ref->offset);
783 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
784 sizeof(struct literal_double));
785 reg[insn->reg].type = REG_DOUBLE;
2f0145d1 786 dbg_printf("ref load double %g\n", reg[insn->reg].d);
cd54f6d9 787 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
064220d4 788 PO;
cd54f6d9
MD
789 }
790
064220d4 791 OP(FILTER_OP_LOAD_STRING):
cd54f6d9
MD
792 {
793 struct load_op *insn = (struct load_op *) pc;
794
cd54f6d9
MD
795 dbg_printf("load string %s\n", insn->data);
796 reg[insn->reg].str = insn->data;
797 reg[insn->reg].type = REG_STRING;
798 reg[insn->reg].seq_len = UINT_MAX;
799 reg[insn->reg].literal = 1;
800 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
064220d4 801 PO;
cd54f6d9
MD
802 }
803
064220d4 804 OP(FILTER_OP_LOAD_S64):
cd54f6d9
MD
805 {
806 struct load_op *insn = (struct load_op *) pc;
807
cd54f6d9
MD
808 memcpy(&reg[insn->reg].v, insn->data,
809 sizeof(struct literal_numeric));
810 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
811 reg[insn->reg].type = REG_S64;
812 next_pc += sizeof(struct load_op)
813 + sizeof(struct literal_numeric);
064220d4 814 PO;
cd54f6d9 815 }
da6eed25 816
064220d4 817 OP(FILTER_OP_LOAD_DOUBLE):
da6eed25
MD
818 {
819 struct load_op *insn = (struct load_op *) pc;
820
da6eed25
MD
821 memcpy(&reg[insn->reg].d, insn->data,
822 sizeof(struct literal_double));
823 dbg_printf("load s64 %g\n", reg[insn->reg].d);
824 reg[insn->reg].type = REG_DOUBLE;
825 next_pc += sizeof(struct load_op)
826 + sizeof(struct literal_double);
064220d4 827 PO;
da6eed25 828 }
064220d4
MD
829
830 END_OP
cd54f6d9
MD
831end:
832 /* return 0 (discard) on error */
833 if (ret)
834 return 0;
835 return retval;
836}
837
86cc3805
MD
838#undef START_OP
839#undef OP
840#undef PO
841#undef END_OP
842
9522a886
MD
843static
844int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
845{
846 switch (reg[REG_R0].type) {
847 default:
848 goto error_unknown;
849
850 case REG_STRING:
851 switch (reg[REG_R1].type) {
852 default:
853 goto error_unknown;
854
855 case REG_STRING:
856 break;
857 case REG_S64:
858 case REG_DOUBLE:
859 goto error_mismatch;
860 }
861 break;
862 case REG_S64:
863 case REG_DOUBLE:
864 switch (reg[REG_R1].type) {
865 default:
866 goto error_unknown;
867
868 case REG_STRING:
869 goto error_mismatch;
870
871 case REG_S64:
872 case REG_DOUBLE:
873 break;
874 }
875 break;
876 }
877 return 0;
878
879error_unknown:
880
881 return -EINVAL;
882error_mismatch:
883 ERR("type mismatch for '%s' binary operator\n", str);
884 return -EINVAL;
885}
886
887static
888int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
889{
890 void *pc, *next_pc, *start_pc;
891 int ret = -EINVAL;
892 struct vreg reg[NR_REG];
893 int i;
894
895 for (i = 0; i < NR_REG; i++) {
225b6640 896 reg[i].type = REG_TYPE_UNKNOWN;
9522a886
MD
897 reg[i].literal = 0;
898 }
899
900 start_pc = &bytecode->data[0];
901 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
902 pc = next_pc) {
903 if (unlikely(pc >= start_pc + bytecode->len)) {
904 ERR("filter bytecode overflow\n");
905 ret = -EINVAL;
906 goto end;
907 }
908 dbg_printf("Validating op %s (%u)\n",
909 print_op((unsigned int) *(filter_opcode_t *) pc),
910 (unsigned int) *(filter_opcode_t *) pc);
911 switch (*(filter_opcode_t *) pc) {
912 case FILTER_OP_UNKNOWN:
913 default:
914 ERR("unknown bytecode op %u\n",
915 (unsigned int) *(filter_opcode_t *) pc);
916 ret = -EINVAL;
917 goto end;
918
919 case FILTER_OP_RETURN:
920 ret = 0;
921 goto end;
922
923 /* binary */
924 case FILTER_OP_MUL:
925 case FILTER_OP_DIV:
926 case FILTER_OP_MOD:
927 case FILTER_OP_PLUS:
928 case FILTER_OP_MINUS:
929 case FILTER_OP_RSHIFT:
930 case FILTER_OP_LSHIFT:
931 case FILTER_OP_BIN_AND:
932 case FILTER_OP_BIN_OR:
933 case FILTER_OP_BIN_XOR:
934 ERR("unsupported bytecode op %u\n",
935 (unsigned int) *(filter_opcode_t *) pc);
936 ret = -EINVAL;
937 goto end;
938
939 case FILTER_OP_EQ:
940 {
941 ret = bin_op_compare_check(reg, "==");
942 if (ret)
943 goto end;
944 reg[REG_R0].type = REG_S64;
945 next_pc += sizeof(struct binary_op);
946 break;
947 }
948 case FILTER_OP_NE:
949 {
950 ret = bin_op_compare_check(reg, "!=");
951 if (ret)
952 goto end;
953 reg[REG_R0].type = REG_S64;
954 next_pc += sizeof(struct binary_op);
955 break;
956 }
957 case FILTER_OP_GT:
958 {
959 ret = bin_op_compare_check(reg, ">");
960 if (ret)
961 goto end;
962 reg[REG_R0].type = REG_S64;
963 next_pc += sizeof(struct binary_op);
964 break;
965 }
966 case FILTER_OP_LT:
967 {
968 ret = bin_op_compare_check(reg, "<");
969 if (ret)
970 goto end;
971 reg[REG_R0].type = REG_S64;
972 next_pc += sizeof(struct binary_op);
973 break;
974 }
975 case FILTER_OP_GE:
976 {
977 ret = bin_op_compare_check(reg, ">=");
978 if (ret)
979 goto end;
980 reg[REG_R0].type = REG_S64;
981 next_pc += sizeof(struct binary_op);
982 break;
983 }
984 case FILTER_OP_LE:
985 {
986 ret = bin_op_compare_check(reg, "<=");
987 if (ret)
988 goto end;
989 reg[REG_R0].type = REG_S64;
990 next_pc += sizeof(struct binary_op);
991 break;
992 }
993
226106c0
MD
994 case FILTER_OP_EQ_STRING:
995 case FILTER_OP_NE_STRING:
996 case FILTER_OP_GT_STRING:
997 case FILTER_OP_LT_STRING:
998 case FILTER_OP_GE_STRING:
999 case FILTER_OP_LE_STRING:
1000 {
1001 if (reg[REG_R0].type != REG_STRING
1002 || reg[REG_R1].type != REG_STRING) {
1003 ERR("Unexpected register type for string comparator\n");
1004 ret = -EINVAL;
1005 goto end;
1006 }
1007 reg[REG_R0].type = REG_S64;
1008 next_pc += sizeof(struct binary_op);
1009 break;
1010 }
1011
1012 case FILTER_OP_EQ_S64:
1013 case FILTER_OP_NE_S64:
1014 case FILTER_OP_GT_S64:
1015 case FILTER_OP_LT_S64:
1016 case FILTER_OP_GE_S64:
1017 case FILTER_OP_LE_S64:
1018 {
1019 if (reg[REG_R0].type != REG_S64
1020 || reg[REG_R1].type != REG_S64) {
1021 ERR("Unexpected register type for s64 comparator\n");
1022 ret = -EINVAL;
1023 goto end;
1024 }
1025 reg[REG_R0].type = REG_S64;
1026 next_pc += sizeof(struct binary_op);
1027 break;
1028 }
1029
1030 case FILTER_OP_EQ_DOUBLE:
1031 case FILTER_OP_NE_DOUBLE:
1032 case FILTER_OP_GT_DOUBLE:
1033 case FILTER_OP_LT_DOUBLE:
1034 case FILTER_OP_GE_DOUBLE:
1035 case FILTER_OP_LE_DOUBLE:
1036 {
1037 if ((reg[REG_R0].type != REG_DOUBLE && reg[REG_R0].type != REG_S64)
1038 || (reg[REG_R1].type != REG_DOUBLE && reg[REG_R1].type != REG_S64)) {
1039 ERR("Unexpected register type for double comparator\n");
1040 ret = -EINVAL;
1041 goto end;
1042 }
96c9d846
MD
1043 if (reg[REG_R0].type != REG_DOUBLE && reg[REG_R1].type != REG_DOUBLE) {
1044 ERR("Double operator should have at least one double register\n");
1045 ret = -EINVAL;
1046 goto end;
1047 }
226106c0
MD
1048 reg[REG_R0].type = REG_DOUBLE;
1049 next_pc += sizeof(struct binary_op);
1050 break;
1051 }
1052
9522a886
MD
1053 /* unary */
1054 case FILTER_OP_UNARY_PLUS:
1055 case FILTER_OP_UNARY_MINUS:
1056 case FILTER_OP_UNARY_NOT:
1057 {
1058 struct unary_op *insn = (struct unary_op *) pc;
1059
1060 if (unlikely(insn->reg >= REG_ERROR)) {
1061 ERR("invalid register %u\n",
1062 (unsigned int) insn->reg);
1063 ret = -EINVAL;
1064 goto end;
1065 }
1066 switch (reg[insn->reg].type) {
1067 default:
1068 ERR("unknown register type\n");
1069 ret = -EINVAL;
1070 goto end;
1071
1072 case REG_STRING:
1073 ERR("Unary op can only be applied to numeric or floating point registers\n");
1074 ret = -EINVAL;
1075 goto end;
1076 case REG_S64:
1077 break;
1078 case REG_DOUBLE:
1079 break;
1080 }
1081 next_pc += sizeof(struct unary_op);
1082 break;
1083 }
08c84b15
MD
1084
1085 case FILTER_OP_UNARY_PLUS_S64:
1086 case FILTER_OP_UNARY_MINUS_S64:
1087 case FILTER_OP_UNARY_NOT_S64:
1088 {
1089 struct unary_op *insn = (struct unary_op *) pc;
1090
1091 if (unlikely(insn->reg >= REG_ERROR)) {
1092 ERR("invalid register %u\n",
1093 (unsigned int) insn->reg);
1094 ret = -EINVAL;
1095 goto end;
1096 }
1097 if (reg[insn->reg].type != REG_S64) {
1098 ERR("Invalid register type\n");
1099 ret = -EINVAL;
1100 goto end;
1101 }
1102 next_pc += sizeof(struct unary_op);
1103 break;
1104 }
1105
1106 case FILTER_OP_UNARY_PLUS_DOUBLE:
1107 case FILTER_OP_UNARY_MINUS_DOUBLE:
1108 case FILTER_OP_UNARY_NOT_DOUBLE:
1109 {
1110 struct unary_op *insn = (struct unary_op *) pc;
1111
1112 if (unlikely(insn->reg >= REG_ERROR)) {
1113 ERR("invalid register %u\n",
1114 (unsigned int) insn->reg);
1115 ret = -EINVAL;
1116 goto end;
1117 }
1118 if (reg[insn->reg].type != REG_DOUBLE) {
1119 ERR("Invalid register type\n");
1120 ret = -EINVAL;
1121 goto end;
1122 }
1123 next_pc += sizeof(struct unary_op);
1124 break;
1125 }
1126
9522a886
MD
1127 /* logical */
1128 case FILTER_OP_AND:
1129 case FILTER_OP_OR:
96c9d846
MD
1130 case FILTER_OP_AND_S64:
1131 case FILTER_OP_OR_S64:
1132 case FILTER_OP_AND_DOUBLE:
1133 case FILTER_OP_OR_DOUBLE:
9522a886
MD
1134 {
1135 struct logical_op *insn = (struct logical_op *) pc;
1136
225b6640 1137 if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
fb72494a 1138 || reg[REG_R1].type == REG_TYPE_UNKNOWN
225b6640
MD
1139 || reg[REG_R0].type == REG_STRING
1140 || reg[REG_R1].type == REG_STRING)) {
1141 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
9522a886
MD
1142 ret = -EINVAL;
1143 goto end;
1144 }
1145
1146 dbg_printf("Validate jumping to bytecode offset %u\n",
1147 (unsigned int) insn->skip_offset);
1148 if (unlikely(start_pc + insn->skip_offset <= pc)) {
1149 ERR("Loops are not allowed in bytecode\n");
1150 ret = -EINVAL;
1151 goto end;
1152 }
96c9d846
MD
1153 if (insn->op == FILTER_OP_AND_S64
1154 || insn->op == FILTER_OP_OR_S64) {
1155 if (reg[REG_R0].type != REG_S64
1156 || reg[REG_R1].type != REG_S64) {
1157 ret = -EINVAL;
1158 goto end;
1159 }
1160 }
1161 if (insn->op == FILTER_OP_AND_DOUBLE
1162 || insn->op == FILTER_OP_OR_DOUBLE) {
1163 if (reg[REG_R0].type != REG_DOUBLE
1164 && reg[REG_R1].type != REG_DOUBLE) {
1165 ERR("Double operator should have at least one double register\n");
1166 ret = -EINVAL;
1167 goto end;
1168 }
1169 }
1170 switch(reg[REG_R0].type) {
1171 default:
1172 case REG_STRING:
1173 ERR("unknown register type\n");
1174 ret = -EINVAL;
1175 goto end;
1176
1177 case REG_S64:
1178 if (reg[REG_R1].type == REG_S64) {
1179 reg[REG_R0].type = REG_S64;
1180 } else {
1181 reg[REG_R0].type = REG_DOUBLE;
1182 }
1183 break;
1184 case REG_DOUBLE:
1185 reg[REG_R0].type = REG_DOUBLE;
1186 break;
1187 }
9522a886
MD
1188 next_pc += sizeof(struct logical_op);
1189 break;
1190 }
1191
1192 /* load */
1193 case FILTER_OP_LOAD_FIELD_REF:
2f0145d1
MD
1194 {
1195 ERR("Unknown field ref type\n");
1196 ret = -EINVAL;
1197 goto end;
1198 }
1199 case FILTER_OP_LOAD_FIELD_REF_STRING:
1200 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
9522a886
MD
1201 {
1202 struct load_op *insn = (struct load_op *) pc;
1203 struct field_ref *ref = (struct field_ref *) insn->data;
1204
1205 if (unlikely(insn->reg >= REG_ERROR)) {
1206 ERR("invalid register %u\n",
1207 (unsigned int) insn->reg);
1208 ret = -EINVAL;
1209 goto end;
1210 }
2f0145d1
MD
1211 dbg_printf("Validate load field ref offset %u type string\n",
1212 ref->offset);
1213 reg[insn->reg].type = REG_STRING;
1214 reg[insn->reg].literal = 0;
1215 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1216 break;
1217 }
1218 case FILTER_OP_LOAD_FIELD_REF_S64:
1219 {
1220 struct load_op *insn = (struct load_op *) pc;
1221 struct field_ref *ref = (struct field_ref *) insn->data;
1222
1223 if (unlikely(insn->reg >= REG_ERROR)) {
1224 ERR("invalid register %u\n",
1225 (unsigned int) insn->reg);
9522a886
MD
1226 ret = -EINVAL;
1227 goto end;
9522a886 1228 }
2f0145d1
MD
1229 dbg_printf("Validate load field ref offset %u type s64\n",
1230 ref->offset);
1231 reg[insn->reg].type = REG_S64;
1232 reg[insn->reg].literal = 0;
1233 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1234 break;
1235 }
1236 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1237 {
1238 struct load_op *insn = (struct load_op *) pc;
1239 struct field_ref *ref = (struct field_ref *) insn->data;
9522a886 1240
2f0145d1
MD
1241 if (unlikely(insn->reg >= REG_ERROR)) {
1242 ERR("invalid register %u\n",
1243 (unsigned int) insn->reg);
1244 ret = -EINVAL;
1245 goto end;
1246 }
1247 dbg_printf("Validate load field ref offset %u type double\n",
1248 ref->offset);
1249 reg[insn->reg].type = REG_DOUBLE;
1250 reg[insn->reg].literal = 0;
9522a886
MD
1251 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1252 break;
1253 }
1254
1255 case FILTER_OP_LOAD_STRING:
1256 {
1257 struct load_op *insn = (struct load_op *) pc;
1258
1259 if (unlikely(insn->reg >= REG_ERROR)) {
1260 ERR("invalid register %u\n",
1261 (unsigned int) insn->reg);
1262 ret = -EINVAL;
1263 goto end;
1264 }
1265 reg[insn->reg].type = REG_STRING;
1266 reg[insn->reg].literal = 1;
1267 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1268 break;
1269 }
1270
1271 case FILTER_OP_LOAD_S64:
1272 {
1273 struct load_op *insn = (struct load_op *) pc;
1274
1275 if (unlikely(insn->reg >= REG_ERROR)) {
1276 ERR("invalid register %u\n",
1277 (unsigned int) insn->reg);
1278 ret = -EINVAL;
1279 goto end;
1280 }
1281 reg[insn->reg].type = REG_S64;
08c84b15 1282 reg[insn->reg].literal = 1;
9522a886
MD
1283 next_pc += sizeof(struct load_op)
1284 + sizeof(struct literal_numeric);
1285 break;
1286 }
1287
1288 case FILTER_OP_LOAD_DOUBLE:
1289 {
1290 struct load_op *insn = (struct load_op *) pc;
1291
1292 if (unlikely(insn->reg >= REG_ERROR)) {
1293 ERR("invalid register %u\n",
1294 (unsigned int) insn->reg);
1295 ret = -EINVAL;
1296 goto end;
1297 }
1298 reg[insn->reg].type = REG_DOUBLE;
08c84b15 1299 reg[insn->reg].literal = 1;
9522a886
MD
1300 next_pc += sizeof(struct load_op)
1301 + sizeof(struct literal_double);
1302 break;
1303 }
1304 }
1305 }
1306end:
1307 return ret;
1308}
1309
08c84b15
MD
1310static
1311int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
1312{
1313 void *pc, *next_pc, *start_pc;
1314 int ret = -EINVAL;
1315 struct vreg reg[NR_REG];
1316 int i;
1317
1318 for (i = 0; i < NR_REG; i++) {
1319 reg[i].type = REG_TYPE_UNKNOWN;
1320 reg[i].literal = 0;
1321 }
1322
1323 start_pc = &bytecode->data[0];
1324 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1325 pc = next_pc) {
1326 switch (*(filter_opcode_t *) pc) {
1327 case FILTER_OP_UNKNOWN:
1328 default:
1329 ERR("unknown bytecode op %u\n",
1330 (unsigned int) *(filter_opcode_t *) pc);
1331 ret = -EINVAL;
1332 goto end;
1333
1334 case FILTER_OP_RETURN:
1335 ret = 0;
1336 goto end;
1337
1338 /* binary */
1339 case FILTER_OP_MUL:
1340 case FILTER_OP_DIV:
1341 case FILTER_OP_MOD:
1342 case FILTER_OP_PLUS:
1343 case FILTER_OP_MINUS:
1344 case FILTER_OP_RSHIFT:
1345 case FILTER_OP_LSHIFT:
1346 case FILTER_OP_BIN_AND:
1347 case FILTER_OP_BIN_OR:
1348 case FILTER_OP_BIN_XOR:
1349 ERR("unsupported bytecode op %u\n",
1350 (unsigned int) *(filter_opcode_t *) pc);
1351 ret = -EINVAL;
1352 goto end;
1353
1354 case FILTER_OP_EQ:
226106c0
MD
1355 {
1356 struct binary_op *insn = (struct binary_op *) pc;
1357
1358 switch(reg[REG_R0].type) {
1359 default:
1360 ERR("unknown register type\n");
1361 ret = -EINVAL;
1362 goto end;
1363
1364 case REG_STRING:
1365 insn->op = FILTER_OP_EQ_STRING;
1366 break;
1367 case REG_S64:
1368 if (reg[REG_R1].type == REG_S64)
1369 insn->op = FILTER_OP_EQ_S64;
1370 else
1371 insn->op = FILTER_OP_EQ_DOUBLE;
1372 break;
1373 case REG_DOUBLE:
1374 insn->op = FILTER_OP_EQ_DOUBLE;
1375 break;
1376 }
1377 reg[REG_R0].type = REG_S64;
1378 next_pc += sizeof(struct binary_op);
1379 break;
1380 }
1381
08c84b15 1382 case FILTER_OP_NE:
226106c0
MD
1383 {
1384 struct binary_op *insn = (struct binary_op *) pc;
1385
1386 switch(reg[REG_R0].type) {
1387 default:
1388 ERR("unknown register type\n");
1389 ret = -EINVAL;
1390 goto end;
1391
1392 case REG_STRING:
1393 insn->op = FILTER_OP_NE_STRING;
1394 break;
1395 case REG_S64:
1396 if (reg[REG_R1].type == REG_S64)
1397 insn->op = FILTER_OP_NE_S64;
1398 else
1399 insn->op = FILTER_OP_NE_DOUBLE;
1400 break;
1401 case REG_DOUBLE:
1402 insn->op = FILTER_OP_NE_DOUBLE;
1403 break;
1404 }
1405 reg[REG_R0].type = REG_S64;
1406 next_pc += sizeof(struct binary_op);
1407 break;
1408 }
1409
08c84b15 1410 case FILTER_OP_GT:
226106c0
MD
1411 {
1412 struct binary_op *insn = (struct binary_op *) pc;
1413
1414 switch(reg[REG_R0].type) {
1415 default:
1416 ERR("unknown register type\n");
1417 ret = -EINVAL;
1418 goto end;
1419
1420 case REG_STRING:
1421 insn->op = FILTER_OP_GT_STRING;
1422 break;
1423 case REG_S64:
1424 if (reg[REG_R1].type == REG_S64)
1425 insn->op = FILTER_OP_GT_S64;
1426 else
1427 insn->op = FILTER_OP_GT_DOUBLE;
1428 break;
1429 case REG_DOUBLE:
1430 insn->op = FILTER_OP_GT_DOUBLE;
1431 break;
1432 }
1433 reg[REG_R0].type = REG_S64;
1434 next_pc += sizeof(struct binary_op);
1435 break;
1436 }
1437
08c84b15 1438 case FILTER_OP_LT:
226106c0
MD
1439 {
1440 struct binary_op *insn = (struct binary_op *) pc;
1441
1442 switch(reg[REG_R0].type) {
1443 default:
1444 ERR("unknown register type\n");
1445 ret = -EINVAL;
1446 goto end;
1447
1448 case REG_STRING:
1449 insn->op = FILTER_OP_LT_STRING;
1450 break;
1451 case REG_S64:
1452 if (reg[REG_R1].type == REG_S64)
1453 insn->op = FILTER_OP_LT_S64;
1454 else
1455 insn->op = FILTER_OP_LT_DOUBLE;
1456 break;
1457 case REG_DOUBLE:
1458 insn->op = FILTER_OP_LT_DOUBLE;
1459 break;
1460 }
1461 reg[REG_R0].type = REG_S64;
1462 next_pc += sizeof(struct binary_op);
1463 break;
1464 }
1465
08c84b15 1466 case FILTER_OP_GE:
226106c0
MD
1467 {
1468 struct binary_op *insn = (struct binary_op *) pc;
1469
1470 switch(reg[REG_R0].type) {
1471 default:
1472 ERR("unknown register type\n");
1473 ret = -EINVAL;
1474 goto end;
1475
1476 case REG_STRING:
1477 insn->op = FILTER_OP_GE_STRING;
1478 break;
1479 case REG_S64:
1480 if (reg[REG_R1].type == REG_S64)
1481 insn->op = FILTER_OP_GE_S64;
1482 else
1483 insn->op = FILTER_OP_GE_DOUBLE;
1484 break;
1485 case REG_DOUBLE:
1486 insn->op = FILTER_OP_GE_DOUBLE;
1487 break;
1488 }
1489 reg[REG_R0].type = REG_S64;
1490 next_pc += sizeof(struct binary_op);
1491 break;
1492 }
08c84b15 1493 case FILTER_OP_LE:
226106c0
MD
1494 {
1495 struct binary_op *insn = (struct binary_op *) pc;
1496
1497 switch(reg[REG_R0].type) {
1498 default:
1499 ERR("unknown register type\n");
1500 ret = -EINVAL;
1501 goto end;
1502
1503 case REG_STRING:
1504 insn->op = FILTER_OP_LE_STRING;
1505 break;
1506 case REG_S64:
1507 if (reg[REG_R1].type == REG_S64)
1508 insn->op = FILTER_OP_LE_S64;
1509 else
1510 insn->op = FILTER_OP_LE_DOUBLE;
1511 break;
1512 case REG_DOUBLE:
1513 insn->op = FILTER_OP_LE_DOUBLE;
1514 break;
1515 }
1516 reg[REG_R0].type = REG_S64;
1517 next_pc += sizeof(struct binary_op);
1518 break;
1519 }
1520
1521 case FILTER_OP_EQ_STRING:
1522 case FILTER_OP_NE_STRING:
1523 case FILTER_OP_GT_STRING:
1524 case FILTER_OP_LT_STRING:
1525 case FILTER_OP_GE_STRING:
1526 case FILTER_OP_LE_STRING:
1527 case FILTER_OP_EQ_S64:
1528 case FILTER_OP_NE_S64:
1529 case FILTER_OP_GT_S64:
1530 case FILTER_OP_LT_S64:
1531 case FILTER_OP_GE_S64:
1532 case FILTER_OP_LE_S64:
1533 case FILTER_OP_EQ_DOUBLE:
1534 case FILTER_OP_NE_DOUBLE:
1535 case FILTER_OP_GT_DOUBLE:
1536 case FILTER_OP_LT_DOUBLE:
1537 case FILTER_OP_GE_DOUBLE:
1538 case FILTER_OP_LE_DOUBLE:
08c84b15
MD
1539 {
1540 reg[REG_R0].type = REG_S64;
1541 next_pc += sizeof(struct binary_op);
1542 break;
1543 }
1544
1545 /* unary */
1546 case FILTER_OP_UNARY_PLUS:
1547 {
1548 struct unary_op *insn = (struct unary_op *) pc;
1549
1550 switch(reg[insn->reg].type) {
1551 default:
1552 ERR("unknown register type\n");
1553 ret = -EINVAL;
1554 goto end;
1555
1556 case REG_S64:
1557 insn->op = FILTER_OP_UNARY_PLUS_S64;
1558 break;
1559 case REG_DOUBLE:
1560 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1561 break;
1562 }
96c9d846 1563 next_pc += sizeof(struct unary_op);
08c84b15
MD
1564 break;
1565 }
1566
1567 case FILTER_OP_UNARY_MINUS:
1568 {
1569 struct unary_op *insn = (struct unary_op *) pc;
1570
1571 switch(reg[insn->reg].type) {
1572 default:
1573 ERR("unknown register type\n");
1574 ret = -EINVAL;
1575 goto end;
1576
1577 case REG_S64:
1578 insn->op = FILTER_OP_UNARY_MINUS_S64;
1579 break;
1580 case REG_DOUBLE:
1581 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1582 break;
1583 }
96c9d846 1584 next_pc += sizeof(struct unary_op);
08c84b15
MD
1585 break;
1586 }
1587
1588 case FILTER_OP_UNARY_NOT:
1589 {
1590 struct unary_op *insn = (struct unary_op *) pc;
1591
1592 switch(reg[insn->reg].type) {
1593 default:
1594 ERR("unknown register type\n");
1595 ret = -EINVAL;
1596 goto end;
1597
1598 case REG_S64:
1599 insn->op = FILTER_OP_UNARY_NOT_S64;
1600 break;
1601 case REG_DOUBLE:
1602 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1603 break;
1604 }
96c9d846 1605 next_pc += sizeof(struct unary_op);
08c84b15
MD
1606 break;
1607 }
1608
1609 case FILTER_OP_UNARY_PLUS_S64:
1610 case FILTER_OP_UNARY_MINUS_S64:
1611 case FILTER_OP_UNARY_NOT_S64:
1612 case FILTER_OP_UNARY_PLUS_DOUBLE:
1613 case FILTER_OP_UNARY_MINUS_DOUBLE:
1614 case FILTER_OP_UNARY_NOT_DOUBLE:
1615 {
1616 next_pc += sizeof(struct unary_op);
1617 break;
1618 }
1619
1620 /* logical */
1621 case FILTER_OP_AND:
96c9d846
MD
1622 {
1623 struct logical_op *insn = (struct logical_op *) pc;
1624
1625 switch(reg[REG_R0].type) {
1626 default:
1627 case REG_STRING:
1628 ERR("unknown register type\n");
1629 ret = -EINVAL;
1630 goto end;
1631
1632 case REG_S64:
1633 if (reg[REG_R1].type == REG_S64) {
1634 insn->op = FILTER_OP_AND_S64;
1635 reg[REG_R0].type = REG_S64;
1636 } else {
1637 insn->op = FILTER_OP_AND_DOUBLE;
1638 reg[REG_R0].type = REG_DOUBLE;
1639 }
1640 break;
1641 case REG_DOUBLE:
1642 insn->op = FILTER_OP_AND_DOUBLE;
1643 reg[REG_R0].type = REG_DOUBLE;
1644 break;
1645 }
1646 next_pc += sizeof(struct logical_op);
1647 break;
1648 }
08c84b15 1649 case FILTER_OP_OR:
96c9d846
MD
1650 {
1651 struct logical_op *insn = (struct logical_op *) pc;
1652
1653 switch(reg[REG_R0].type) {
1654 default:
1655 case REG_STRING:
1656 ERR("unknown register type\n");
1657 ret = -EINVAL;
1658 goto end;
1659
1660 case REG_S64:
1661 if (reg[REG_R1].type == REG_S64) {
1662 insn->op = FILTER_OP_OR_S64;
1663 reg[REG_R0].type = REG_S64;
1664 } else {
1665 insn->op = FILTER_OP_OR_DOUBLE;
1666 reg[REG_R0].type = REG_DOUBLE;
1667 }
1668 break;
1669 case REG_DOUBLE:
1670 insn->op = FILTER_OP_OR_DOUBLE;
1671 reg[REG_R0].type = REG_DOUBLE;
1672 break;
1673 }
1674 next_pc += sizeof(struct logical_op);
1675 break;
1676 }
1677
1678 case FILTER_OP_AND_S64:
1679 case FILTER_OP_OR_S64:
1680 case FILTER_OP_AND_DOUBLE:
1681 case FILTER_OP_OR_DOUBLE:
08c84b15
MD
1682 {
1683 next_pc += sizeof(struct logical_op);
1684 break;
1685 }
1686
1687 /* load */
1688 case FILTER_OP_LOAD_FIELD_REF:
1689 {
1690 ERR("Unknown field ref type\n");
1691 ret = -EINVAL;
1692 goto end;
1693 }
1694 case FILTER_OP_LOAD_FIELD_REF_STRING:
1695 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1696 {
1697 struct load_op *insn = (struct load_op *) pc;
1698
1699 reg[insn->reg].type = REG_STRING;
1700 reg[insn->reg].literal = 0;
1701 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1702 break;
1703 }
1704 case FILTER_OP_LOAD_FIELD_REF_S64:
1705 {
1706 struct load_op *insn = (struct load_op *) pc;
1707
1708 reg[insn->reg].type = REG_S64;
1709 reg[insn->reg].literal = 0;
1710 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1711 break;
1712 }
1713 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1714 {
1715 struct load_op *insn = (struct load_op *) pc;
1716
1717 reg[insn->reg].type = REG_DOUBLE;
1718 reg[insn->reg].literal = 0;
1719 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1720 break;
1721 }
1722
1723 case FILTER_OP_LOAD_STRING:
1724 {
1725 struct load_op *insn = (struct load_op *) pc;
1726
1727 reg[insn->reg].type = REG_STRING;
1728 reg[insn->reg].literal = 1;
1729 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1730 break;
1731 }
1732
1733 case FILTER_OP_LOAD_S64:
1734 {
1735 struct load_op *insn = (struct load_op *) pc;
1736
1737 reg[insn->reg].type = REG_S64;
1738 reg[insn->reg].literal = 1;
1739 next_pc += sizeof(struct load_op)
1740 + sizeof(struct literal_numeric);
1741 break;
1742 }
1743
1744 case FILTER_OP_LOAD_DOUBLE:
1745 {
1746 struct load_op *insn = (struct load_op *) pc;
1747
1748 reg[insn->reg].type = REG_DOUBLE;
1749 reg[insn->reg].literal = 1;
1750 next_pc += sizeof(struct load_op)
1751 + sizeof(struct literal_double);
1752 break;
1753 }
1754 }
1755 }
1756end:
1757 return ret;
1758}
1759
1760
1761
cd54f6d9
MD
1762static
1763int apply_field_reloc(struct ltt_event *event,
1764 struct bytecode_runtime *runtime,
1765 uint32_t runtime_len,
1766 uint32_t reloc_offset,
1767 const char *field_name)
1768{
1769 const struct lttng_event_desc *desc;
1770 const struct lttng_event_field *fields, *field = NULL;
1771 unsigned int nr_fields, i;
1772 struct field_ref *field_ref;
2f0145d1 1773 struct load_op *op;
cd54f6d9
MD
1774 uint32_t field_offset = 0;
1775
a8c27c7c 1776 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
cd54f6d9
MD
1777
1778 /* Ensure that the reloc is within the code */
1779 if (runtime_len - reloc_offset < sizeof(uint16_t))
1780 return -EINVAL;
1781
1782 /* Lookup event by name */
1783 desc = event->desc;
1784 if (!desc)
1785 return -EINVAL;
1786 fields = desc->fields;
1787 if (!fields)
1788 return -EINVAL;
1789 nr_fields = desc->nr_fields;
1790 for (i = 0; i < nr_fields; i++) {
1791 if (!strcmp(fields[i].name, field_name)) {
1792 field = &fields[i];
1793 break;
1794 }
1795 /* compute field offset */
1796 switch (fields[i].type.atype) {
1797 case atype_integer:
1798 case atype_enum:
1799 field_offset += sizeof(int64_t);
1800 break;
1801 case atype_array:
1802 case atype_sequence:
1803 field_offset += sizeof(unsigned long);
1804 field_offset += sizeof(void *);
1805 break;
1806 case atype_string:
1807 field_offset += sizeof(void *);
1808 break;
1809 case atype_float:
1810 field_offset += sizeof(double);
da6eed25 1811 break;
cd54f6d9
MD
1812 default:
1813 return -EINVAL;
1814 }
1815 }
1816 if (!field)
1817 return -EINVAL;
1818
1819 /* Check if field offset is too large for 16-bit offset */
1820 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1821 return -EINVAL;
1822
1823 /* set type */
2f0145d1
MD
1824 op = (struct load_op *) &runtime->data[reloc_offset];
1825 field_ref = (struct field_ref *) op->data;
cd54f6d9
MD
1826 switch (field->type.atype) {
1827 case atype_integer:
1828 case atype_enum:
2f0145d1 1829 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
cd54f6d9
MD
1830 break;
1831 case atype_array:
1832 case atype_sequence:
2f0145d1 1833 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
cd54f6d9
MD
1834 break;
1835 case atype_string:
2f0145d1 1836 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
cd54f6d9
MD
1837 break;
1838 case atype_float:
2f0145d1 1839 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
da6eed25 1840 break;
cd54f6d9
MD
1841 default:
1842 return -EINVAL;
1843 }
1844 /* set offset */
1845 field_ref->offset = (uint16_t) field_offset;
2d78951a
MD
1846 return 0;
1847}
1848
cd54f6d9
MD
1849/*
1850 * Take a bytecode with reloc table and link it to an event to create a
1851 * bytecode runtime.
1852 */
2d78951a
MD
1853static
1854int _lttng_filter_event_link_bytecode(struct ltt_event *event,
1855 struct lttng_ust_filter_bytecode *filter_bytecode)
1856{
cd54f6d9
MD
1857 int ret, offset, next_offset;
1858 struct bytecode_runtime *runtime = NULL;
1859 size_t runtime_alloc_len;
1860
2d78951a
MD
1861 if (!filter_bytecode)
1862 return 0;
cd54f6d9
MD
1863 /* Even is not connected to any description */
1864 if (!event->desc)
1865 return 0;
1866 /* Bytecode already linked */
1867 if (event->filter || event->filter_data)
1868 return 0;
2d78951a 1869
a8c27c7c 1870 dbg_printf("Linking\n");
cd54f6d9
MD
1871
1872 /* We don't need the reloc table in the runtime */
1873 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
1874 runtime = zmalloc(runtime_alloc_len);
1875 if (!runtime) {
1876 ret = -ENOMEM;
1877 goto link_error;
1878 }
1879 runtime->len = filter_bytecode->reloc_offset;
1880 /* copy original bytecode */
1881 memcpy(runtime->data, filter_bytecode->data, runtime->len);
1882 /*
1883 * apply relocs. Those are a uint16_t (offset in bytecode)
1884 * followed by a string (field name).
1885 */
cd54f6d9
MD
1886 for (offset = filter_bytecode->reloc_offset;
1887 offset < filter_bytecode->len;
1888 offset = next_offset) {
1889 uint16_t reloc_offset =
1890 *(uint16_t *) &filter_bytecode->data[offset];
1891 const char *field_name =
1892 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
1893
1894 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
1895 if (ret) {
1896 goto link_error;
1897 }
1898 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
1899 }
9522a886
MD
1900 /* Validate bytecode */
1901 ret = lttng_filter_validate_bytecode(runtime);
1902 if (ret) {
1903 goto link_error;
1904 }
08c84b15
MD
1905 /* Specialize bytecode */
1906 ret = lttng_filter_specialize_bytecode(runtime);
1907 if (ret) {
1908 goto link_error;
1909 }
cd54f6d9 1910 event->filter_data = runtime;
2d78951a 1911 event->filter = lttng_filter_interpret_bytecode;
2d78951a 1912 return 0;
cd54f6d9
MD
1913
1914link_error:
1915 event->filter = lttng_filter_false;
1916 free(runtime);
1917 return ret;
2d78951a
MD
1918}
1919
1920void lttng_filter_event_link_bytecode(struct ltt_event *event,
1921 struct lttng_ust_filter_bytecode *filter_bytecode)
1922{
1923 int ret;
1924
cd54f6d9 1925 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
2d78951a
MD
1926 if (ret) {
1927 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
1928 }
1929}
1930
1931/*
1932 * Link bytecode to all events for a wildcard. Skips events that already
1933 * have a bytecode linked.
1934 * We do not set each event's filter_bytecode field, because they do not
1935 * own the filter_bytecode: the wildcard owns it.
1936 */
1937void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
1938{
1939 struct ltt_event *event;
1940 int ret;
1941
1942 if (!wildcard->filter_bytecode)
1943 return;
1944
1945 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
1946 if (event->filter)
1947 continue;
1948 ret = _lttng_filter_event_link_bytecode(event,
1949 wildcard->filter_bytecode);
1950 if (ret) {
1951 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
1952 }
1953
1954 }
1955 return;
1956}
1957
1958/*
1959 * Need to attach filter to an event before starting tracing for the
cd54f6d9 1960 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1961 */
1962int lttng_filter_event_attach_bytecode(struct ltt_event *event,
1963 struct lttng_ust_filter_bytecode *filter_bytecode)
1964{
2d78951a
MD
1965 if (event->chan->session->been_active)
1966 return -EPERM;
1967 if (event->filter_bytecode)
1968 return -EEXIST;
cd54f6d9 1969 event->filter_bytecode = filter_bytecode;
2d78951a
MD
1970 return 0;
1971}
1972
1973/*
1974 * Need to attach filter to a wildcard before starting tracing for the
cd54f6d9 1975 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1976 */
1977int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
1978 struct lttng_ust_filter_bytecode *filter_bytecode)
1979{
2d78951a
MD
1980 if (wildcard->chan->session->been_active)
1981 return -EPERM;
1982 if (wildcard->filter_bytecode)
1983 return -EEXIST;
cd54f6d9 1984 wildcard->filter_bytecode = filter_bytecode;
2d78951a
MD
1985 return 0;
1986}
This page took 0.104855 seconds and 4 git commands to generate.