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