Fix: network instrumentation protocol enum
[lttng-modules.git] / lttng-filter-interpreter.c
CommitLineData
07dfc1d0
MD
1/*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng modules filter interpreter.
5 *
bbf3aef5 6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
07dfc1d0 7 *
bbf3aef5
MD
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
07dfc1d0 14 *
bbf3aef5
MD
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
07dfc1d0 17 *
bbf3aef5
MD
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
07dfc1d0
MD
25 */
26
f127e61e 27#include <linux/uaccess.h>
63155590 28#include <wrapper/frame.h>
cbc19040 29#include <wrapper/types.h>
f127e61e 30
241ae9a8 31#include <lttng-filter.h>
02aca193 32#include <lttng-string-utils.h>
07dfc1d0 33
63155590
MD
34LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
35
f127e61e
MD
36/*
37 * get_char should be called with page fault handler disabled if it is expected
38 * to handle user-space read.
39 */
40static
41char get_char(struct estack_entry *reg, size_t offset)
42{
43 if (unlikely(offset >= reg->u.s.seq_len))
44 return '\0';
45 if (reg->u.s.user) {
46 char c;
47
48 /* Handle invalid access as end of string. */
49 if (unlikely(!access_ok(VERIFY_READ,
50 reg->u.s.user_str + offset,
51 sizeof(c))))
52 return '\0';
53 /* Handle fault (nonzero return value) as end of string. */
54 if (unlikely(__copy_from_user_inatomic(&c,
55 reg->u.s.user_str + offset,
56 sizeof(c))))
57 return '\0';
58 return c;
59 } else {
60 return reg->u.s.str[offset];
61 }
62}
63
07dfc1d0
MD
64/*
65 * -1: wildcard found.
66 * -2: unknown escape char.
67 * 0: normal char.
68 */
07dfc1d0 69static
f127e61e 70int parse_char(struct estack_entry *reg, char *c, size_t *offset)
07dfc1d0 71{
f127e61e 72 switch (*c) {
07dfc1d0 73 case '\\':
f127e61e
MD
74 (*offset)++;
75 *c = get_char(reg, *offset);
76 switch (*c) {
07dfc1d0
MD
77 case '\\':
78 case '*':
79 return 0;
80 default:
81 return -2;
82 }
83 case '*':
84 return -1;
85 default:
86 return 0;
87 }
88}
89
02aca193
PP
90static
91char get_char_at_cb(size_t at, void *data)
92{
93 return get_char(data, at);
94}
95
96static
97int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
98{
99 bool has_user = false;
100 mm_segment_t old_fs;
101 int result;
102 struct estack_entry *pattern_reg;
103 struct estack_entry *candidate_reg;
104
105 if (estack_bx(stack, top)->u.s.user
106 || estack_ax(stack, top)->u.s.user) {
107 has_user = true;
108 old_fs = get_fs();
109 set_fs(KERNEL_DS);
110 pagefault_disable();
111 }
112
113 /* Find out which side is the pattern vs. the candidate. */
114 if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
115 pattern_reg = estack_ax(stack, top);
116 candidate_reg = estack_bx(stack, top);
117 } else {
118 pattern_reg = estack_bx(stack, top);
119 candidate_reg = estack_ax(stack, top);
120 }
121
122 /* Perform the match operation. */
123 result = !strutils_star_glob_match_char_cb(get_char_at_cb,
124 pattern_reg, get_char_at_cb, candidate_reg);
125 if (has_user) {
126 pagefault_enable();
127 set_fs(old_fs);
128 }
129
130 return result;
131}
132
07dfc1d0
MD
133static
134int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
135{
f127e61e
MD
136 size_t offset_bx = 0, offset_ax = 0;
137 int diff, has_user = 0;
138 mm_segment_t old_fs;
139
140 if (estack_bx(stack, top)->u.s.user
141 || estack_ax(stack, top)->u.s.user) {
142 has_user = 1;
143 old_fs = get_fs();
144 set_fs(KERNEL_DS);
145 pagefault_disable();
146 }
07dfc1d0
MD
147
148 for (;;) {
f127e61e 149 int ret;
07dfc1d0 150 int escaped_r0 = 0;
f127e61e 151 char char_bx, char_ax;
07dfc1d0 152
f127e61e
MD
153 char_bx = get_char(estack_bx(stack, top), offset_bx);
154 char_ax = get_char(estack_ax(stack, top), offset_ax);
155
156 if (unlikely(char_bx == '\0')) {
157 if (char_ax == '\0') {
158 diff = 0;
159 break;
07dfc1d0 160 } else {
02aca193
PP
161 if (estack_ax(stack, top)->u.s.literal_type ==
162 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
163 ret = parse_char(estack_ax(stack, top),
164 &char_ax, &offset_ax);
165 if (ret == -1) {
166 diff = 0;
167 break;
168 }
07dfc1d0 169 }
f127e61e
MD
170 diff = -1;
171 break;
07dfc1d0
MD
172 }
173 }
f127e61e 174 if (unlikely(char_ax == '\0')) {
02aca193
PP
175 if (estack_bx(stack, top)->u.s.literal_type ==
176 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
abfd272b
MD
177 ret = parse_char(estack_bx(stack, top),
178 &char_bx, &offset_bx);
179 if (ret == -1) {
180 diff = 0;
181 break;
07dfc1d0 182 }
07dfc1d0 183 }
abfd272b
MD
184 diff = 1;
185 break;
07dfc1d0 186 }
02aca193
PP
187 if (estack_bx(stack, top)->u.s.literal_type ==
188 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
189 ret = parse_char(estack_bx(stack, top),
190 &char_bx, &offset_bx);
07dfc1d0 191 if (ret == -1) {
f127e61e
MD
192 diff = 0;
193 break;
07dfc1d0
MD
194 } else if (ret == -2) {
195 escaped_r0 = 1;
196 }
197 /* else compare both char */
198 }
02aca193
PP
199 if (estack_ax(stack, top)->u.s.literal_type ==
200 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
201 ret = parse_char(estack_ax(stack, top),
202 &char_ax, &offset_ax);
07dfc1d0 203 if (ret == -1) {
f127e61e
MD
204 diff = 0;
205 break;
07dfc1d0 206 } else if (ret == -2) {
f127e61e
MD
207 if (!escaped_r0) {
208 diff = -1;
209 break;
210 }
07dfc1d0 211 } else {
f127e61e
MD
212 if (escaped_r0) {
213 diff = 1;
214 break;
215 }
07dfc1d0
MD
216 }
217 } else {
f127e61e
MD
218 if (escaped_r0) {
219 diff = 1;
220 break;
221 }
07dfc1d0 222 }
f127e61e 223 diff = char_bx - char_ax;
07dfc1d0
MD
224 if (diff != 0)
225 break;
f127e61e
MD
226 offset_bx++;
227 offset_ax++;
228 }
229 if (has_user) {
230 pagefault_enable();
231 set_fs(old_fs);
07dfc1d0
MD
232 }
233 return diff;
234}
235
236uint64_t lttng_filter_false(void *filter_data,
79150a49 237 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
238 const char *filter_stack_data)
239{
240 return 0;
241}
242
243#ifdef INTERPRETER_USE_SWITCH
244
245/*
246 * Fallback for compilers that do not support taking address of labels.
247 */
248
249#define START_OP \
250 start_pc = &bytecode->data[0]; \
251 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
252 pc = next_pc) { \
253 dbg_printk("Executing op %s (%u)\n", \
254 lttng_filter_print_op((unsigned int) *(filter_opcode_t *) pc), \
255 (unsigned int) *(filter_opcode_t *) pc); \
256 switch (*(filter_opcode_t *) pc) {
257
258#define OP(name) case name
259
260#define PO break
261
262#define END_OP } \
263 }
264
265#else
266
267/*
268 * Dispatch-table based interpreter.
269 */
270
271#define START_OP \
272 start_pc = &bytecode->data[0]; \
273 pc = next_pc = start_pc; \
274 if (unlikely(pc - start_pc >= bytecode->len)) \
275 goto end; \
276 goto *dispatch[*(filter_opcode_t *) pc];
277
278#define OP(name) \
279LABEL_##name
280
281#define PO \
282 pc = next_pc; \
283 goto *dispatch[*(filter_opcode_t *) pc];
284
285#define END_OP
286
287#endif
288
289/*
290 * Return 0 (discard), or raise the 0x1 flag (log event).
291 * Currently, other flags are kept for future extensions and have no
292 * effect.
293 */
294uint64_t lttng_filter_interpret_bytecode(void *filter_data,
79150a49 295 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
296 const char *filter_stack_data)
297{
298 struct bytecode_runtime *bytecode = filter_data;
299 void *pc, *next_pc, *start_pc;
300 int ret = -EINVAL;
301 uint64_t retval = 0;
302 struct estack _stack;
303 struct estack *stack = &_stack;
304 register int64_t ax = 0, bx = 0;
305 register int top = FILTER_STACK_EMPTY;
306#ifndef INTERPRETER_USE_SWITCH
307 static void *dispatch[NR_FILTER_OPS] = {
308 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
309
310 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
311
312 /* binary */
313 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
314 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
315 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
316 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
317 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
318 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
319 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
320 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
321 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
322 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
323
324 /* binary comparators */
325 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
326 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
327 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
328 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
329 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
330 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
331
332 /* string binary comparator */
333 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
334 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
335 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
336 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
337 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
338 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
339
02aca193
PP
340 /* globbing pattern binary comparator */
341 [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
342 [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
343
07dfc1d0
MD
344 /* s64 binary comparator */
345 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
346 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
347 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
348 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
349 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
350 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
351
352 /* double binary comparator */
353 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
354 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
355 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
356 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
357 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
358 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
359
360 /* Mixed S64-double binary comparators */
361 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
362 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
363 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
364 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
365 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
366 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
367
368 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
369 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
370 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
371 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
372 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
373 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
374
375 /* unary */
376 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
377 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
378 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
379 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
380 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
381 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
382 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
383 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
384 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
385
386 /* logical */
387 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
388 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
389
390 /* load field ref */
391 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
392 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
393 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
394 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
395 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
396
397 /* load from immediate operand */
398 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
02aca193 399 [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
07dfc1d0
MD
400 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
401 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
402
403 /* cast */
404 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
405 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
406 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
407
408 /* get context ref */
409 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
410 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
411 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
412 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
f127e61e
MD
413
414 /* load userspace field ref */
415 [ FILTER_OP_LOAD_FIELD_REF_USER_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_STRING,
416 [ FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE,
07dfc1d0
MD
417 };
418#endif /* #ifndef INTERPRETER_USE_SWITCH */
419
420 START_OP
421
422 OP(FILTER_OP_UNKNOWN):
423 OP(FILTER_OP_LOAD_FIELD_REF):
424 OP(FILTER_OP_GET_CONTEXT_REF):
425#ifdef INTERPRETER_USE_SWITCH
426 default:
427#endif /* INTERPRETER_USE_SWITCH */
428 printk(KERN_WARNING "unknown bytecode op %u\n",
429 (unsigned int) *(filter_opcode_t *) pc);
430 ret = -EINVAL;
431 goto end;
432
433 OP(FILTER_OP_RETURN):
434 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
435 retval = !!estack_ax_v;
436 ret = 0;
437 goto end;
438
439 /* binary */
440 OP(FILTER_OP_MUL):
441 OP(FILTER_OP_DIV):
442 OP(FILTER_OP_MOD):
443 OP(FILTER_OP_PLUS):
444 OP(FILTER_OP_MINUS):
445 OP(FILTER_OP_RSHIFT):
446 OP(FILTER_OP_LSHIFT):
447 OP(FILTER_OP_BIN_AND):
448 OP(FILTER_OP_BIN_OR):
449 OP(FILTER_OP_BIN_XOR):
450 printk(KERN_WARNING "unsupported bytecode op %u\n",
451 (unsigned int) *(filter_opcode_t *) pc);
452 ret = -EINVAL;
453 goto end;
454
455 OP(FILTER_OP_EQ):
456 OP(FILTER_OP_NE):
457 OP(FILTER_OP_GT):
458 OP(FILTER_OP_LT):
459 OP(FILTER_OP_GE):
460 OP(FILTER_OP_LE):
461 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
462 (unsigned int) *(filter_opcode_t *) pc);
463 ret = -EINVAL;
464 goto end;
465
466 OP(FILTER_OP_EQ_STRING):
467 {
468 int res;
469
470 res = (stack_strcmp(stack, top, "==") == 0);
471 estack_pop(stack, top, ax, bx);
472 estack_ax_v = res;
473 next_pc += sizeof(struct binary_op);
474 PO;
475 }
476 OP(FILTER_OP_NE_STRING):
477 {
478 int res;
479
480 res = (stack_strcmp(stack, top, "!=") != 0);
481 estack_pop(stack, top, ax, bx);
482 estack_ax_v = res;
483 next_pc += sizeof(struct binary_op);
484 PO;
485 }
486 OP(FILTER_OP_GT_STRING):
487 {
488 int res;
489
490 res = (stack_strcmp(stack, top, ">") > 0);
491 estack_pop(stack, top, ax, bx);
492 estack_ax_v = res;
493 next_pc += sizeof(struct binary_op);
494 PO;
495 }
496 OP(FILTER_OP_LT_STRING):
497 {
498 int res;
499
500 res = (stack_strcmp(stack, top, "<") < 0);
501 estack_pop(stack, top, ax, bx);
502 estack_ax_v = res;
503 next_pc += sizeof(struct binary_op);
504 PO;
505 }
506 OP(FILTER_OP_GE_STRING):
507 {
508 int res;
509
510 res = (stack_strcmp(stack, top, ">=") >= 0);
511 estack_pop(stack, top, ax, bx);
512 estack_ax_v = res;
513 next_pc += sizeof(struct binary_op);
514 PO;
515 }
516 OP(FILTER_OP_LE_STRING):
517 {
518 int res;
519
520 res = (stack_strcmp(stack, top, "<=") <= 0);
521 estack_pop(stack, top, ax, bx);
522 estack_ax_v = res;
523 next_pc += sizeof(struct binary_op);
524 PO;
525 }
526
02aca193
PP
527 OP(FILTER_OP_EQ_STAR_GLOB_STRING):
528 {
529 int res;
530
531 res = (stack_star_glob_match(stack, top, "==") == 0);
532 estack_pop(stack, top, ax, bx);
533 estack_ax_v = res;
534 next_pc += sizeof(struct binary_op);
535 PO;
536 }
537 OP(FILTER_OP_NE_STAR_GLOB_STRING):
538 {
539 int res;
540
541 res = (stack_star_glob_match(stack, top, "!=") != 0);
542 estack_pop(stack, top, ax, bx);
543 estack_ax_v = res;
544 next_pc += sizeof(struct binary_op);
545 PO;
546 }
547
07dfc1d0
MD
548 OP(FILTER_OP_EQ_S64):
549 {
550 int res;
551
552 res = (estack_bx_v == estack_ax_v);
553 estack_pop(stack, top, ax, bx);
554 estack_ax_v = res;
555 next_pc += sizeof(struct binary_op);
556 PO;
557 }
558 OP(FILTER_OP_NE_S64):
559 {
560 int res;
561
562 res = (estack_bx_v != estack_ax_v);
563 estack_pop(stack, top, ax, bx);
564 estack_ax_v = res;
565 next_pc += sizeof(struct binary_op);
566 PO;
567 }
568 OP(FILTER_OP_GT_S64):
569 {
570 int res;
571
572 res = (estack_bx_v > estack_ax_v);
573 estack_pop(stack, top, ax, bx);
574 estack_ax_v = res;
575 next_pc += sizeof(struct binary_op);
576 PO;
577 }
578 OP(FILTER_OP_LT_S64):
579 {
580 int res;
581
582 res = (estack_bx_v < estack_ax_v);
583 estack_pop(stack, top, ax, bx);
584 estack_ax_v = res;
585 next_pc += sizeof(struct binary_op);
586 PO;
587 }
588 OP(FILTER_OP_GE_S64):
589 {
590 int res;
591
592 res = (estack_bx_v >= estack_ax_v);
593 estack_pop(stack, top, ax, bx);
594 estack_ax_v = res;
595 next_pc += sizeof(struct binary_op);
596 PO;
597 }
598 OP(FILTER_OP_LE_S64):
599 {
600 int res;
601
602 res = (estack_bx_v <= estack_ax_v);
603 estack_pop(stack, top, ax, bx);
604 estack_ax_v = res;
605 next_pc += sizeof(struct binary_op);
606 PO;
607 }
608
609 OP(FILTER_OP_EQ_DOUBLE):
610 OP(FILTER_OP_NE_DOUBLE):
611 OP(FILTER_OP_GT_DOUBLE):
612 OP(FILTER_OP_LT_DOUBLE):
613 OP(FILTER_OP_GE_DOUBLE):
614 OP(FILTER_OP_LE_DOUBLE):
615 {
616 BUG_ON(1);
617 PO;
618 }
619
620 /* Mixed S64-double binary comparators */
621 OP(FILTER_OP_EQ_DOUBLE_S64):
622 OP(FILTER_OP_NE_DOUBLE_S64):
623 OP(FILTER_OP_GT_DOUBLE_S64):
624 OP(FILTER_OP_LT_DOUBLE_S64):
625 OP(FILTER_OP_GE_DOUBLE_S64):
626 OP(FILTER_OP_LE_DOUBLE_S64):
627 OP(FILTER_OP_EQ_S64_DOUBLE):
628 OP(FILTER_OP_NE_S64_DOUBLE):
629 OP(FILTER_OP_GT_S64_DOUBLE):
630 OP(FILTER_OP_LT_S64_DOUBLE):
631 OP(FILTER_OP_GE_S64_DOUBLE):
632 OP(FILTER_OP_LE_S64_DOUBLE):
633 {
634 BUG_ON(1);
635 PO;
636 }
637
638 /* unary */
639 OP(FILTER_OP_UNARY_PLUS):
640 OP(FILTER_OP_UNARY_MINUS):
641 OP(FILTER_OP_UNARY_NOT):
642 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
643 (unsigned int) *(filter_opcode_t *) pc);
644 ret = -EINVAL;
645 goto end;
646
647
648 OP(FILTER_OP_UNARY_PLUS_S64):
649 {
650 next_pc += sizeof(struct unary_op);
651 PO;
652 }
653 OP(FILTER_OP_UNARY_MINUS_S64):
654 {
655 estack_ax_v = -estack_ax_v;
656 next_pc += sizeof(struct unary_op);
657 PO;
658 }
659 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
660 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
661 {
662 BUG_ON(1);
663 PO;
664 }
665 OP(FILTER_OP_UNARY_NOT_S64):
666 {
667 estack_ax_v = !estack_ax_v;
668 next_pc += sizeof(struct unary_op);
669 PO;
670 }
671 OP(FILTER_OP_UNARY_NOT_DOUBLE):
672 {
673 BUG_ON(1);
674 PO;
675 }
676
677 /* logical */
678 OP(FILTER_OP_AND):
679 {
680 struct logical_op *insn = (struct logical_op *) pc;
681
682 /* If AX is 0, skip and evaluate to 0 */
683 if (unlikely(estack_ax_v == 0)) {
684 dbg_printk("Jumping to bytecode offset %u\n",
685 (unsigned int) insn->skip_offset);
686 next_pc = start_pc + insn->skip_offset;
687 } else {
688 /* Pop 1 when jump not taken */
689 estack_pop(stack, top, ax, bx);
690 next_pc += sizeof(struct logical_op);
691 }
692 PO;
693 }
694 OP(FILTER_OP_OR):
695 {
696 struct logical_op *insn = (struct logical_op *) pc;
697
698 /* If AX is nonzero, skip and evaluate to 1 */
699
700 if (unlikely(estack_ax_v != 0)) {
701 estack_ax_v = 1;
702 dbg_printk("Jumping to bytecode offset %u\n",
703 (unsigned int) insn->skip_offset);
704 next_pc = start_pc + insn->skip_offset;
705 } else {
706 /* Pop 1 when jump not taken */
707 estack_pop(stack, top, ax, bx);
708 next_pc += sizeof(struct logical_op);
709 }
710 PO;
711 }
712
713
714 /* load field ref */
715 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
716 {
717 struct load_op *insn = (struct load_op *) pc;
718 struct field_ref *ref = (struct field_ref *) insn->data;
719
720 dbg_printk("load field ref offset %u type string\n",
721 ref->offset);
722 estack_push(stack, top, ax, bx);
723 estack_ax(stack, top)->u.s.str =
724 *(const char * const *) &filter_stack_data[ref->offset];
725 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
726 dbg_printk("Filter warning: loading a NULL string.\n");
727 ret = -EINVAL;
728 goto end;
729 }
cbc19040 730 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
731 estack_ax(stack, top)->u.s.literal_type =
732 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 733 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
734 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
735 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
736 PO;
737 }
738
739 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
740 {
741 struct load_op *insn = (struct load_op *) pc;
742 struct field_ref *ref = (struct field_ref *) insn->data;
743
744 dbg_printk("load field ref offset %u type sequence\n",
745 ref->offset);
746 estack_push(stack, top, ax, bx);
747 estack_ax(stack, top)->u.s.seq_len =
748 *(unsigned long *) &filter_stack_data[ref->offset];
749 estack_ax(stack, top)->u.s.str =
750 *(const char **) (&filter_stack_data[ref->offset
751 + sizeof(unsigned long)]);
752 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
753 dbg_printk("Filter warning: loading a NULL sequence.\n");
754 ret = -EINVAL;
755 goto end;
756 }
02aca193
PP
757 estack_ax(stack, top)->u.s.literal_type =
758 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 759 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
760 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
761 PO;
762 }
763
764 OP(FILTER_OP_LOAD_FIELD_REF_S64):
765 {
766 struct load_op *insn = (struct load_op *) pc;
767 struct field_ref *ref = (struct field_ref *) insn->data;
768
769 dbg_printk("load field ref offset %u type s64\n",
770 ref->offset);
771 estack_push(stack, top, ax, bx);
772 estack_ax_v =
773 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
774 dbg_printk("ref load s64 %lld\n",
775 (long long) estack_ax_v);
776 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
777 PO;
778 }
779
780 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
781 {
782 BUG_ON(1);
783 PO;
784 }
785
786 /* load from immediate operand */
787 OP(FILTER_OP_LOAD_STRING):
788 {
789 struct load_op *insn = (struct load_op *) pc;
790
791 dbg_printk("load string %s\n", insn->data);
792 estack_push(stack, top, ax, bx);
793 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 794 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
795 estack_ax(stack, top)->u.s.literal_type =
796 ESTACK_STRING_LITERAL_TYPE_PLAIN;
797 estack_ax(stack, top)->u.s.user = 0;
798 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
799 PO;
800 }
801
802 OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
803 {
804 struct load_op *insn = (struct load_op *) pc;
805
806 dbg_printk("load globbing pattern %s\n", insn->data);
807 estack_push(stack, top, ax, bx);
808 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 809 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
810 estack_ax(stack, top)->u.s.literal_type =
811 ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
f127e61e 812 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
813 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
814 PO;
815 }
816
817 OP(FILTER_OP_LOAD_S64):
818 {
819 struct load_op *insn = (struct load_op *) pc;
820
821 estack_push(stack, top, ax, bx);
822 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
823 dbg_printk("load s64 %lld\n",
824 (long long) estack_ax_v);
825 next_pc += sizeof(struct load_op)
826 + sizeof(struct literal_numeric);
827 PO;
828 }
829
830 OP(FILTER_OP_LOAD_DOUBLE):
831 {
832 BUG_ON(1);
833 PO;
834 }
835
836 /* cast */
837 OP(FILTER_OP_CAST_TO_S64):
838 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
839 (unsigned int) *(filter_opcode_t *) pc);
840 ret = -EINVAL;
841 goto end;
842
843 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
844 {
845 BUG_ON(1);
846 PO;
847 }
848
849 OP(FILTER_OP_CAST_NOP):
850 {
851 next_pc += sizeof(struct cast_op);
852 PO;
853 }
854
855 /* get context ref */
856 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
857 {
858 struct load_op *insn = (struct load_op *) pc;
859 struct field_ref *ref = (struct field_ref *) insn->data;
860 struct lttng_ctx_field *ctx_field;
861 union lttng_ctx_value v;
862
863 dbg_printk("get context ref offset %u type string\n",
864 ref->offset);
865 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 866 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
867 estack_push(stack, top, ax, bx);
868 estack_ax(stack, top)->u.s.str = v.str;
869 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
870 dbg_printk("Filter warning: loading a NULL string.\n");
871 ret = -EINVAL;
872 goto end;
873 }
cbc19040 874 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
875 estack_ax(stack, top)->u.s.literal_type =
876 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 877 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
878 dbg_printk("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
879 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
880 PO;
881 }
882
883 OP(FILTER_OP_GET_CONTEXT_REF_S64):
884 {
885 struct load_op *insn = (struct load_op *) pc;
886 struct field_ref *ref = (struct field_ref *) insn->data;
887 struct lttng_ctx_field *ctx_field;
888 union lttng_ctx_value v;
889
890 dbg_printk("get context ref offset %u type s64\n",
891 ref->offset);
892 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 893 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
894 estack_push(stack, top, ax, bx);
895 estack_ax_v = v.s64;
896 dbg_printk("ref get context s64 %lld\n",
897 (long long) estack_ax_v);
898 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
899 PO;
900 }
901
902 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
903 {
904 BUG_ON(1);
905 PO;
906 }
907
f127e61e
MD
908 /* load userspace field ref */
909 OP(FILTER_OP_LOAD_FIELD_REF_USER_STRING):
910 {
911 struct load_op *insn = (struct load_op *) pc;
912 struct field_ref *ref = (struct field_ref *) insn->data;
913
914 dbg_printk("load field ref offset %u type user string\n",
915 ref->offset);
916 estack_push(stack, top, ax, bx);
5b4ad89f 917 estack_ax(stack, top)->u.s.user_str =
f127e61e
MD
918 *(const char * const *) &filter_stack_data[ref->offset];
919 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
920 dbg_printk("Filter warning: loading a NULL string.\n");
921 ret = -EINVAL;
922 goto end;
923 }
cbc19040 924 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
925 estack_ax(stack, top)->u.s.literal_type =
926 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e
MD
927 estack_ax(stack, top)->u.s.user = 1;
928 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
929 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
930 PO;
931 }
932
933 OP(FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE):
934 {
935 struct load_op *insn = (struct load_op *) pc;
936 struct field_ref *ref = (struct field_ref *) insn->data;
937
938 dbg_printk("load field ref offset %u type user sequence\n",
939 ref->offset);
940 estack_push(stack, top, ax, bx);
941 estack_ax(stack, top)->u.s.seq_len =
942 *(unsigned long *) &filter_stack_data[ref->offset];
5b4ad89f 943 estack_ax(stack, top)->u.s.user_str =
f127e61e
MD
944 *(const char **) (&filter_stack_data[ref->offset
945 + sizeof(unsigned long)]);
946 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
947 dbg_printk("Filter warning: loading a NULL sequence.\n");
948 ret = -EINVAL;
949 goto end;
950 }
02aca193
PP
951 estack_ax(stack, top)->u.s.literal_type =
952 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e
MD
953 estack_ax(stack, top)->u.s.user = 1;
954 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
955 PO;
956 }
957
07dfc1d0
MD
958 END_OP
959end:
960 /* return 0 (discard) on error */
961 if (ret)
962 return 0;
963 return retval;
964}
965
966#undef START_OP
967#undef OP
968#undef PO
969#undef END_OP
This page took 0.063775 seconds and 4 git commands to generate.