Fix: timer_expire_entry changed in 4.19.312
[lttng-modules.git] / lttng-filter-interpreter.c
CommitLineData
9f36eaed
MJ
1/* SPDX-License-Identifier: MIT
2 *
07dfc1d0
MD
3 * lttng-filter-interpreter.c
4 *
5 * LTTng modules filter interpreter.
6 *
bbf3aef5 7 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
07dfc1d0
MD
8 */
9
1d00109f 10#include <wrapper/compiler_attributes.h>
80bb2600 11#include <wrapper/uaccess.h>
37b9cb0e 12#include <wrapper/objtool.h>
cbc19040 13#include <wrapper/types.h>
3834b99f 14#include <linux/swab.h>
f127e61e 15
241ae9a8 16#include <lttng-filter.h>
02aca193 17#include <lttng-string-utils.h>
c89271d4 18#include <probes/lttng-probe-user.h>
07dfc1d0 19
63155590
MD
20LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
21
f127e61e
MD
22/*
23 * get_char should be called with page fault handler disabled if it is expected
24 * to handle user-space read.
25 */
26static
23a2f61f 27char get_char(const struct estack_entry *reg, size_t offset)
f127e61e
MD
28{
29 if (unlikely(offset >= reg->u.s.seq_len))
30 return '\0';
31 if (reg->u.s.user) {
32 char c;
33
34 /* Handle invalid access as end of string. */
80bb2600 35 if (unlikely(!lttng_access_ok(VERIFY_READ,
f127e61e
MD
36 reg->u.s.user_str + offset,
37 sizeof(c))))
38 return '\0';
39 /* Handle fault (nonzero return value) as end of string. */
40 if (unlikely(__copy_from_user_inatomic(&c,
41 reg->u.s.user_str + offset,
42 sizeof(c))))
43 return '\0';
44 return c;
45 } else {
46 return reg->u.s.str[offset];
47 }
48}
49
07dfc1d0
MD
50/*
51 * -1: wildcard found.
52 * -2: unknown escape char.
53 * 0: normal char.
54 */
07dfc1d0 55static
f127e61e 56int parse_char(struct estack_entry *reg, char *c, size_t *offset)
07dfc1d0 57{
f127e61e 58 switch (*c) {
07dfc1d0 59 case '\\':
f127e61e
MD
60 (*offset)++;
61 *c = get_char(reg, *offset);
62 switch (*c) {
07dfc1d0
MD
63 case '\\':
64 case '*':
65 return 0;
66 default:
67 return -2;
68 }
69 case '*':
70 return -1;
71 default:
72 return 0;
73 }
74}
75
02aca193
PP
76static
77char get_char_at_cb(size_t at, void *data)
78{
79 return get_char(data, at);
80}
81
82static
83int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
84{
85 bool has_user = false;
02aca193
PP
86 int result;
87 struct estack_entry *pattern_reg;
88 struct estack_entry *candidate_reg;
89
6f9e33ea 90 /* Disable the page fault handler when reading from userspace. */
02aca193
PP
91 if (estack_bx(stack, top)->u.s.user
92 || estack_ax(stack, top)->u.s.user) {
93 has_user = true;
02aca193
PP
94 pagefault_disable();
95 }
96
97 /* Find out which side is the pattern vs. the candidate. */
98 if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
99 pattern_reg = estack_ax(stack, top);
100 candidate_reg = estack_bx(stack, top);
101 } else {
102 pattern_reg = estack_bx(stack, top);
103 candidate_reg = estack_ax(stack, top);
104 }
105
106 /* Perform the match operation. */
107 result = !strutils_star_glob_match_char_cb(get_char_at_cb,
108 pattern_reg, get_char_at_cb, candidate_reg);
6f9e33ea 109 if (has_user)
02aca193 110 pagefault_enable();
02aca193
PP
111
112 return result;
113}
114
07dfc1d0
MD
115static
116int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
117{
f127e61e
MD
118 size_t offset_bx = 0, offset_ax = 0;
119 int diff, has_user = 0;
f127e61e
MD
120
121 if (estack_bx(stack, top)->u.s.user
122 || estack_ax(stack, top)->u.s.user) {
123 has_user = 1;
f127e61e
MD
124 pagefault_disable();
125 }
07dfc1d0
MD
126
127 for (;;) {
f127e61e 128 int ret;
07dfc1d0 129 int escaped_r0 = 0;
f127e61e 130 char char_bx, char_ax;
07dfc1d0 131
f127e61e
MD
132 char_bx = get_char(estack_bx(stack, top), offset_bx);
133 char_ax = get_char(estack_ax(stack, top), offset_ax);
134
135 if (unlikely(char_bx == '\0')) {
136 if (char_ax == '\0') {
137 diff = 0;
138 break;
07dfc1d0 139 } else {
02aca193
PP
140 if (estack_ax(stack, top)->u.s.literal_type ==
141 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
142 ret = parse_char(estack_ax(stack, top),
143 &char_ax, &offset_ax);
144 if (ret == -1) {
145 diff = 0;
146 break;
147 }
07dfc1d0 148 }
f127e61e
MD
149 diff = -1;
150 break;
07dfc1d0
MD
151 }
152 }
f127e61e 153 if (unlikely(char_ax == '\0')) {
02aca193
PP
154 if (estack_bx(stack, top)->u.s.literal_type ==
155 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
abfd272b
MD
156 ret = parse_char(estack_bx(stack, top),
157 &char_bx, &offset_bx);
158 if (ret == -1) {
159 diff = 0;
160 break;
07dfc1d0 161 }
07dfc1d0 162 }
abfd272b
MD
163 diff = 1;
164 break;
07dfc1d0 165 }
02aca193
PP
166 if (estack_bx(stack, top)->u.s.literal_type ==
167 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
168 ret = parse_char(estack_bx(stack, top),
169 &char_bx, &offset_bx);
07dfc1d0 170 if (ret == -1) {
f127e61e
MD
171 diff = 0;
172 break;
07dfc1d0
MD
173 } else if (ret == -2) {
174 escaped_r0 = 1;
175 }
176 /* else compare both char */
177 }
02aca193
PP
178 if (estack_ax(stack, top)->u.s.literal_type ==
179 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
180 ret = parse_char(estack_ax(stack, top),
181 &char_ax, &offset_ax);
07dfc1d0 182 if (ret == -1) {
f127e61e
MD
183 diff = 0;
184 break;
07dfc1d0 185 } else if (ret == -2) {
f127e61e
MD
186 if (!escaped_r0) {
187 diff = -1;
188 break;
189 }
07dfc1d0 190 } else {
f127e61e
MD
191 if (escaped_r0) {
192 diff = 1;
193 break;
194 }
07dfc1d0
MD
195 }
196 } else {
f127e61e
MD
197 if (escaped_r0) {
198 diff = 1;
199 break;
200 }
07dfc1d0 201 }
f127e61e 202 diff = char_bx - char_ax;
07dfc1d0
MD
203 if (diff != 0)
204 break;
f127e61e
MD
205 offset_bx++;
206 offset_ax++;
207 }
6f9e33ea 208 if (has_user)
f127e61e 209 pagefault_enable();
6f9e33ea 210
07dfc1d0
MD
211 return diff;
212}
213
214uint64_t lttng_filter_false(void *filter_data,
79150a49 215 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
216 const char *filter_stack_data)
217{
218 return 0;
219}
220
221#ifdef INTERPRETER_USE_SWITCH
222
223/*
224 * Fallback for compilers that do not support taking address of labels.
225 */
226
227#define START_OP \
228 start_pc = &bytecode->data[0]; \
229 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
230 pc = next_pc) { \
231 dbg_printk("Executing op %s (%u)\n", \
232 lttng_filter_print_op((unsigned int) *(filter_opcode_t *) pc), \
233 (unsigned int) *(filter_opcode_t *) pc); \
234 switch (*(filter_opcode_t *) pc) {
235
236#define OP(name) case name
237
238#define PO break
239
240#define END_OP } \
241 }
242
243#else
244
245/*
246 * Dispatch-table based interpreter.
247 */
248
249#define START_OP \
3834b99f 250 start_pc = &bytecode->code[0]; \
07dfc1d0
MD
251 pc = next_pc = start_pc; \
252 if (unlikely(pc - start_pc >= bytecode->len)) \
253 goto end; \
254 goto *dispatch[*(filter_opcode_t *) pc];
255
256#define OP(name) \
257LABEL_##name
258
259#define PO \
260 pc = next_pc; \
261 goto *dispatch[*(filter_opcode_t *) pc];
262
263#define END_OP
264
265#endif
266
3834b99f
MD
267static int context_get_index(struct lttng_probe_ctx *lttng_probe_ctx,
268 struct load_ptr *ptr,
269 uint32_t idx)
270{
271
272 struct lttng_ctx_field *ctx_field;
273 struct lttng_event_field *field;
274 union lttng_ctx_value v;
275
276 ctx_field = &lttng_static_ctx->fields[idx];
277 field = &ctx_field->event_field;
278 ptr->type = LOAD_OBJECT;
279 /* field is only used for types nested within variants. */
280 ptr->field = NULL;
281
282 switch (field->type.atype) {
283 case atype_integer:
284 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
285 if (field->type.u.basic.integer.signedness) {
286 ptr->object_type = OBJECT_TYPE_S64;
287 ptr->u.s64 = v.s64;
288 ptr->ptr = &ptr->u.s64;
289 } else {
290 ptr->object_type = OBJECT_TYPE_U64;
291 ptr->u.u64 = v.s64; /* Cast. */
292 ptr->ptr = &ptr->u.u64;
293 }
fd6f8c5b 294 ptr->rev_bo = field->type.u.basic.integer.reverse_byte_order;
c89271d4 295 ptr->user = field->type.u.basic.integer.user;
3834b99f
MD
296 break;
297 case atype_enum:
298 {
299 const struct lttng_integer_type *itype =
300 &field->type.u.basic.enumeration.container_type;
301
302 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
303 if (itype->signedness) {
304 ptr->object_type = OBJECT_TYPE_S64;
305 ptr->u.s64 = v.s64;
306 ptr->ptr = &ptr->u.s64;
307 } else {
308 ptr->object_type = OBJECT_TYPE_U64;
309 ptr->u.u64 = v.s64; /* Cast. */
310 ptr->ptr = &ptr->u.u64;
311 }
fd6f8c5b 312 ptr->rev_bo = itype->reverse_byte_order;
c89271d4 313 ptr->user = itype->user;
3834b99f
MD
314 break;
315 }
316 case atype_array:
317 if (field->type.u.array.elem_type.atype != atype_integer) {
318 printk(KERN_WARNING "Array nesting only supports integer types.\n");
319 return -EINVAL;
320 }
321 if (field->type.u.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
322 printk(KERN_WARNING "Only string arrays are supported for contexts.\n");
323 return -EINVAL;
324 }
325 ptr->object_type = OBJECT_TYPE_STRING;
326 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
327 ptr->ptr = v.str;
c89271d4 328 ptr->user = field->type.u.array.elem_type.u.basic.integer.user;
3834b99f
MD
329 break;
330 case atype_sequence:
331 if (field->type.u.sequence.elem_type.atype != atype_integer) {
332 printk(KERN_WARNING "Sequence nesting only supports integer types.\n");
333 return -EINVAL;
334 }
335 if (field->type.u.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
336 printk(KERN_WARNING "Only string sequences are supported for contexts.\n");
337 return -EINVAL;
338 }
339 ptr->object_type = OBJECT_TYPE_STRING;
340 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
341 ptr->ptr = v.str;
c89271d4 342 ptr->user = field->type.u.sequence.elem_type.u.basic.integer.user;
3834b99f
MD
343 break;
344 case atype_array_bitfield:
345 printk(KERN_WARNING "Bitfield array type is not supported.\n");
346 return -EINVAL;
347 case atype_sequence_bitfield:
348 printk(KERN_WARNING "Bitfield sequence type is not supported.\n");
349 return -EINVAL;
350 case atype_string:
351 ptr->object_type = OBJECT_TYPE_STRING;
352 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
353 ptr->ptr = v.str;
c89271d4 354 ptr->user = field->type.u.basic.string.user;
3834b99f
MD
355 break;
356 case atype_struct:
357 printk(KERN_WARNING "Structure type cannot be loaded.\n");
358 return -EINVAL;
359 default:
360 printk(KERN_WARNING "Unknown type: %d", (int) field->type.atype);
361 return -EINVAL;
362 }
363 return 0;
364}
365
366static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_ctx,
367 struct bytecode_runtime *runtime,
368 uint64_t index, struct estack_entry *stack_top)
369{
370 int ret;
371 const struct filter_get_index_data *gid;
372
373 /*
374 * Types nested within variants need to perform dynamic lookup
375 * based on the field descriptions. LTTng-UST does not implement
376 * variants for now.
377 */
378 if (stack_top->u.ptr.field)
379 return -EINVAL;
380 gid = (const struct filter_get_index_data *) &runtime->data[index];
381 switch (stack_top->u.ptr.type) {
382 case LOAD_OBJECT:
383 switch (stack_top->u.ptr.object_type) {
384 case OBJECT_TYPE_ARRAY:
385 {
386 const char *ptr;
387
388 WARN_ON_ONCE(gid->offset >= gid->array_len);
389 /* Skip count (unsigned long) */
390 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
391 ptr = ptr + gid->offset;
392 stack_top->u.ptr.ptr = ptr;
393 stack_top->u.ptr.object_type = gid->elem.type;
394 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
c89271d4 395 stack_top->u.ptr.user = gid->elem.user;
3834b99f
MD
396 /* field is only used for types nested within variants. */
397 stack_top->u.ptr.field = NULL;
398 break;
399 }
400 case OBJECT_TYPE_SEQUENCE:
401 {
402 const char *ptr;
403 size_t ptr_seq_len;
404
405 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
406 ptr_seq_len = *(unsigned long *) stack_top->u.ptr.ptr;
407 if (gid->offset >= gid->elem.len * ptr_seq_len) {
408 ret = -EINVAL;
409 goto end;
410 }
411 ptr = ptr + gid->offset;
412 stack_top->u.ptr.ptr = ptr;
413 stack_top->u.ptr.object_type = gid->elem.type;
414 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
c89271d4 415 stack_top->u.ptr.user = gid->elem.user;
3834b99f
MD
416 /* field is only used for types nested within variants. */
417 stack_top->u.ptr.field = NULL;
418 break;
419 }
420 case OBJECT_TYPE_STRUCT:
421 printk(KERN_WARNING "Nested structures are not supported yet.\n");
422 ret = -EINVAL;
423 goto end;
424 case OBJECT_TYPE_VARIANT:
425 default:
426 printk(KERN_WARNING "Unexpected get index type %d",
427 (int) stack_top->u.ptr.object_type);
428 ret = -EINVAL;
429 goto end;
430 }
431 break;
432 case LOAD_ROOT_CONTEXT:
1d00109f
MJ
433 lttng_fallthrough;
434 case LOAD_ROOT_APP_CONTEXT:
3834b99f
MD
435 {
436 ret = context_get_index(lttng_probe_ctx,
437 &stack_top->u.ptr,
438 gid->ctx_index);
439 if (ret) {
440 goto end;
441 }
442 break;
443 }
444 case LOAD_ROOT_PAYLOAD:
445 stack_top->u.ptr.ptr += gid->offset;
446 if (gid->elem.type == OBJECT_TYPE_STRING)
447 stack_top->u.ptr.ptr = *(const char * const *) stack_top->u.ptr.ptr;
448 stack_top->u.ptr.object_type = gid->elem.type;
449 stack_top->u.ptr.type = LOAD_OBJECT;
450 /* field is only used for types nested within variants. */
451 stack_top->u.ptr.field = NULL;
31afaf8b 452 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
c89271d4 453 stack_top->u.ptr.user = gid->elem.user;
3834b99f
MD
454 break;
455 }
456 return 0;
457
458end:
459 return ret;
460}
461
462static int dynamic_load_field(struct estack_entry *stack_top)
463{
464 int ret;
465
466 switch (stack_top->u.ptr.type) {
467 case LOAD_OBJECT:
468 break;
469 case LOAD_ROOT_CONTEXT:
470 case LOAD_ROOT_APP_CONTEXT:
471 case LOAD_ROOT_PAYLOAD:
472 default:
473 dbg_printk("Filter warning: cannot load root, missing field name.\n");
474 ret = -EINVAL;
475 goto end;
476 }
477 switch (stack_top->u.ptr.object_type) {
478 case OBJECT_TYPE_S8:
479 dbg_printk("op load field s8\n");
c89271d4
MD
480 if (stack_top->u.ptr.user) {
481 if (lttng_copy_from_user_check_nofault(&stack_top->u.v, (int8_t __user *) stack_top->u.ptr.ptr, sizeof(int8_t)))
482 stack_top->u.v = 0;
483 } else {
484 stack_top->u.v = *(int8_t *) stack_top->u.ptr.ptr;
485 }
3834b99f
MD
486 break;
487 case OBJECT_TYPE_S16:
488 {
489 int16_t tmp;
490
491 dbg_printk("op load field s16\n");
c89271d4
MD
492 if (stack_top->u.ptr.user) {
493 if (lttng_copy_from_user_check_nofault(&tmp, (int16_t __user *) stack_top->u.ptr.ptr, sizeof(int16_t)))
494 tmp = 0;
495 } else {
496 tmp = *(int16_t *) stack_top->u.ptr.ptr;
497 }
3834b99f
MD
498 if (stack_top->u.ptr.rev_bo)
499 __swab16s(&tmp);
500 stack_top->u.v = tmp;
501 break;
502 }
503 case OBJECT_TYPE_S32:
504 {
505 int32_t tmp;
506
507 dbg_printk("op load field s32\n");
c89271d4
MD
508 if (stack_top->u.ptr.user) {
509 if (lttng_copy_from_user_check_nofault(&tmp, (int32_t __user *) stack_top->u.ptr.ptr, sizeof(int32_t)))
510 tmp = 0;
511 } else {
512 tmp = *(int32_t *) stack_top->u.ptr.ptr;
513 }
3834b99f
MD
514 if (stack_top->u.ptr.rev_bo)
515 __swab32s(&tmp);
516 stack_top->u.v = tmp;
517 break;
518 }
519 case OBJECT_TYPE_S64:
520 {
521 int64_t tmp;
522
523 dbg_printk("op load field s64\n");
c89271d4
MD
524 if (stack_top->u.ptr.user) {
525 if (lttng_copy_from_user_check_nofault(&tmp, (int64_t __user *) stack_top->u.ptr.ptr, sizeof(int64_t)))
526 tmp = 0;
527 } else {
528 tmp = *(int64_t *) stack_top->u.ptr.ptr;
529 }
3834b99f
MD
530 if (stack_top->u.ptr.rev_bo)
531 __swab64s(&tmp);
532 stack_top->u.v = tmp;
533 break;
534 }
535 case OBJECT_TYPE_U8:
536 dbg_printk("op load field u8\n");
c89271d4
MD
537 if (stack_top->u.ptr.user) {
538 if (lttng_copy_from_user_check_nofault(&stack_top->u.v, (uint8_t __user *) stack_top->u.ptr.ptr, sizeof(uint8_t)))
539 stack_top->u.v = 0;
540 } else {
541 stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr;
542 }
3834b99f
MD
543 break;
544 case OBJECT_TYPE_U16:
545 {
546 uint16_t tmp;
547
548 dbg_printk("op load field s16\n");
c89271d4
MD
549 if (stack_top->u.ptr.user) {
550 if (lttng_copy_from_user_check_nofault(&tmp, (uint16_t __user *) stack_top->u.ptr.ptr, sizeof(uint16_t)))
551 tmp = 0;
552 } else {
553 tmp = *(uint16_t *) stack_top->u.ptr.ptr;
554 }
3834b99f
MD
555 if (stack_top->u.ptr.rev_bo)
556 __swab16s(&tmp);
557 stack_top->u.v = tmp;
558 break;
559 }
560 case OBJECT_TYPE_U32:
561 {
562 uint32_t tmp;
563
564 dbg_printk("op load field u32\n");
c89271d4
MD
565 if (stack_top->u.ptr.user) {
566 if (lttng_copy_from_user_check_nofault(&tmp, (uint32_t __user *) stack_top->u.ptr.ptr, sizeof(uint32_t)))
567 tmp = 0;
568 } else {
569 tmp = *(uint32_t *) stack_top->u.ptr.ptr;
570 }
3834b99f
MD
571 if (stack_top->u.ptr.rev_bo)
572 __swab32s(&tmp);
573 stack_top->u.v = tmp;
574 break;
575 }
576 case OBJECT_TYPE_U64:
577 {
578 uint64_t tmp;
579
580 dbg_printk("op load field u64\n");
c89271d4
MD
581 if (stack_top->u.ptr.user) {
582 if (lttng_copy_from_user_check_nofault(&tmp, (uint64_t __user *) stack_top->u.ptr.ptr, sizeof(uint64_t)))
583 tmp = 0;
584 } else {
585 tmp = *(uint64_t *) stack_top->u.ptr.ptr;
586 }
3834b99f
MD
587 if (stack_top->u.ptr.rev_bo)
588 __swab64s(&tmp);
589 stack_top->u.v = tmp;
590 break;
591 }
592 case OBJECT_TYPE_STRING:
593 {
c89271d4
MD
594 dbg_printk("op load field string: user=%d\n", stack_top->u.ptr.user);
595 if (stack_top->u.ptr.user) {
596 const char __user *user_str = (const char __user *) stack_top->u.ptr.ptr;
3834b99f 597
c89271d4
MD
598 stack_top->u.s.user_str = user_str;
599 if (unlikely(!stack_top->u.s.user_str)) {
600 dbg_printk("Bytecode warning: loading a NULL user string.\n");
601 ret = -EINVAL;
602 goto end;
603 }
604 stack_top->u.s.user = 1;
605 } else {
606 const char *str = (const char *) stack_top->u.ptr.ptr;
607
608 stack_top->u.s.str = str;
609 if (unlikely(!stack_top->u.s.str)) {
610 dbg_printk("Bytecode warning: loading a NULL string.\n");
611 ret = -EINVAL;
612 goto end;
613 }
614 stack_top->u.s.user = 0;
3834b99f 615 }
4efe037b 616 stack_top->u.s.seq_len = LTTNG_SIZE_MAX;
c89271d4 617 stack_top->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE;
3834b99f
MD
618 break;
619 }
620 case OBJECT_TYPE_STRING_SEQUENCE:
621 {
622 const char *ptr;
623
624 dbg_printk("op load field string sequence\n");
625 ptr = stack_top->u.ptr.ptr;
626 stack_top->u.s.seq_len = *(unsigned long *) ptr;
c89271d4
MD
627 if (stack_top->u.ptr.user) {
628 stack_top->u.s.user_str = *(const char __user **) (ptr + sizeof(unsigned long));
629 if (unlikely(!stack_top->u.s.user_str)) {
630 dbg_printk("Bytecode warning: loading a NULL user sequence.\n");
631 ret = -EINVAL;
632 goto end;
633 }
634 stack_top->u.s.user = 1;
635 } else {
636 stack_top->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
637 if (unlikely(!stack_top->u.s.str)) {
638 dbg_printk("Bytecode warning: loading a NULL sequence.\n");
639 ret = -EINVAL;
640 goto end;
641 }
642 stack_top->u.s.user = 0;
3834b99f 643 }
c89271d4 644 stack_top->u.s.literal_type = ESTACK_STRING_LITERAL_TYPE_NONE;
3834b99f
MD
645 break;
646 }
647 case OBJECT_TYPE_DYNAMIC:
648 /*
649 * Dynamic types in context are looked up
650 * by context get index.
651 */
652 ret = -EINVAL;
653 goto end;
654 case OBJECT_TYPE_DOUBLE:
655 ret = -EINVAL;
656 goto end;
657 case OBJECT_TYPE_SEQUENCE:
658 case OBJECT_TYPE_ARRAY:
659 case OBJECT_TYPE_STRUCT:
660 case OBJECT_TYPE_VARIANT:
661 printk(KERN_WARNING "Sequences, arrays, struct and variant cannot be loaded (nested types).\n");
662 ret = -EINVAL;
663 goto end;
664 }
665 return 0;
666
667end:
668 return ret;
669}
670
23a2f61f
JG
671#ifdef DEBUG
672
673#define DBG_USER_STR_CUTOFF 32
674
675/*
676 * In debug mode, print user string (truncated, if necessary).
677 */
678static inline
679void dbg_load_ref_user_str_printk(const struct estack_entry *user_str_reg)
680{
681 size_t pos = 0;
682 char last_char;
683 char user_str[DBG_USER_STR_CUTOFF];
684
685 pagefault_disable();
686 do {
687 last_char = get_char(user_str_reg, pos);
688 user_str[pos] = last_char;
689 pos++;
690 } while (last_char != '\0' && pos < sizeof(user_str));
691 pagefault_enable();
692
693 user_str[sizeof(user_str) - 1] = '\0';
694 dbg_printk("load field ref user string: '%s%s'\n", user_str,
695 last_char != '\0' ? "[...]" : "");
696}
697#else
698static inline
699void dbg_load_ref_user_str_printk(const struct estack_entry *user_str_reg)
700{
701}
702#endif
703
07dfc1d0
MD
704/*
705 * Return 0 (discard), or raise the 0x1 flag (log event).
706 * Currently, other flags are kept for future extensions and have no
707 * effect.
708 */
709uint64_t lttng_filter_interpret_bytecode(void *filter_data,
79150a49 710 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
711 const char *filter_stack_data)
712{
713 struct bytecode_runtime *bytecode = filter_data;
714 void *pc, *next_pc, *start_pc;
715 int ret = -EINVAL;
716 uint64_t retval = 0;
717 struct estack _stack;
718 struct estack *stack = &_stack;
719 register int64_t ax = 0, bx = 0;
720 register int top = FILTER_STACK_EMPTY;
721#ifndef INTERPRETER_USE_SWITCH
722 static void *dispatch[NR_FILTER_OPS] = {
723 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
724
725 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
726
727 /* binary */
728 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
729 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
730 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
731 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
732 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
e16c054b
MD
733 [ FILTER_OP_BIT_RSHIFT ] = &&LABEL_FILTER_OP_BIT_RSHIFT,
734 [ FILTER_OP_BIT_LSHIFT ] = &&LABEL_FILTER_OP_BIT_LSHIFT,
3834b99f
MD
735 [ FILTER_OP_BIT_AND ] = &&LABEL_FILTER_OP_BIT_AND,
736 [ FILTER_OP_BIT_OR ] = &&LABEL_FILTER_OP_BIT_OR,
737 [ FILTER_OP_BIT_XOR ] = &&LABEL_FILTER_OP_BIT_XOR,
07dfc1d0
MD
738
739 /* binary comparators */
740 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
741 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
742 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
743 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
744 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
745 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
746
747 /* string binary comparator */
748 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
749 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
750 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
751 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
752 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
753 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
754
02aca193
PP
755 /* globbing pattern binary comparator */
756 [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
757 [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
758
07dfc1d0
MD
759 /* s64 binary comparator */
760 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
761 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
762 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
763 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
764 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
765 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
766
767 /* double binary comparator */
768 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
769 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
770 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
771 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
772 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
773 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
774
775 /* Mixed S64-double binary comparators */
776 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
777 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
778 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
779 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
780 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
781 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
782
783 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
784 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
785 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
786 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
787 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
788 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
789
790 /* unary */
791 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
792 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
793 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
794 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
795 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
796 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
797 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
798 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
799 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
800
801 /* logical */
802 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
803 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
804
805 /* load field ref */
806 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
807 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
808 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
809 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
810 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
811
812 /* load from immediate operand */
813 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
02aca193 814 [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
07dfc1d0
MD
815 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
816 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
817
818 /* cast */
819 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
820 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
821 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
822
823 /* get context ref */
824 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
825 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
826 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
827 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
f127e61e
MD
828
829 /* load userspace field ref */
830 [ FILTER_OP_LOAD_FIELD_REF_USER_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_STRING,
831 [ FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE,
3834b99f
MD
832
833 /* Instructions for recursive traversal through composed types. */
834 [ FILTER_OP_GET_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_CONTEXT_ROOT,
835 [ FILTER_OP_GET_APP_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_APP_CONTEXT_ROOT,
836 [ FILTER_OP_GET_PAYLOAD_ROOT ] = &&LABEL_FILTER_OP_GET_PAYLOAD_ROOT,
837
838 [ FILTER_OP_GET_SYMBOL ] = &&LABEL_FILTER_OP_GET_SYMBOL,
839 [ FILTER_OP_GET_SYMBOL_FIELD ] = &&LABEL_FILTER_OP_GET_SYMBOL_FIELD,
840 [ FILTER_OP_GET_INDEX_U16 ] = &&LABEL_FILTER_OP_GET_INDEX_U16,
841 [ FILTER_OP_GET_INDEX_U64 ] = &&LABEL_FILTER_OP_GET_INDEX_U64,
842
843 [ FILTER_OP_LOAD_FIELD ] = &&LABEL_FILTER_OP_LOAD_FIELD,
844 [ FILTER_OP_LOAD_FIELD_S8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S8,
845 [ FILTER_OP_LOAD_FIELD_S16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S16,
846 [ FILTER_OP_LOAD_FIELD_S32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S32,
847 [ FILTER_OP_LOAD_FIELD_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S64,
848 [ FILTER_OP_LOAD_FIELD_U8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U8,
849 [ FILTER_OP_LOAD_FIELD_U16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U16,
850 [ FILTER_OP_LOAD_FIELD_U32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U32,
851 [ FILTER_OP_LOAD_FIELD_U64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U64,
852 [ FILTER_OP_LOAD_FIELD_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_STRING,
853 [ FILTER_OP_LOAD_FIELD_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_SEQUENCE,
854 [ FILTER_OP_LOAD_FIELD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_DOUBLE,
e16c054b
MD
855
856 [ FILTER_OP_UNARY_BIT_NOT ] = &&LABEL_FILTER_OP_UNARY_BIT_NOT,
57ba4b41
MD
857
858 [ FILTER_OP_RETURN_S64 ] = &&LABEL_FILTER_OP_RETURN_S64,
07dfc1d0
MD
859 };
860#endif /* #ifndef INTERPRETER_USE_SWITCH */
861
862 START_OP
863
864 OP(FILTER_OP_UNKNOWN):
865 OP(FILTER_OP_LOAD_FIELD_REF):
866 OP(FILTER_OP_GET_CONTEXT_REF):
867#ifdef INTERPRETER_USE_SWITCH
868 default:
869#endif /* INTERPRETER_USE_SWITCH */
870 printk(KERN_WARNING "unknown bytecode op %u\n",
871 (unsigned int) *(filter_opcode_t *) pc);
872 ret = -EINVAL;
873 goto end;
874
875 OP(FILTER_OP_RETURN):
57ba4b41 876 OP(FILTER_OP_RETURN_S64):
07dfc1d0
MD
877 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
878 retval = !!estack_ax_v;
879 ret = 0;
880 goto end;
881
882 /* binary */
883 OP(FILTER_OP_MUL):
884 OP(FILTER_OP_DIV):
885 OP(FILTER_OP_MOD):
886 OP(FILTER_OP_PLUS):
887 OP(FILTER_OP_MINUS):
07dfc1d0
MD
888 printk(KERN_WARNING "unsupported bytecode op %u\n",
889 (unsigned int) *(filter_opcode_t *) pc);
890 ret = -EINVAL;
891 goto end;
892
893 OP(FILTER_OP_EQ):
894 OP(FILTER_OP_NE):
895 OP(FILTER_OP_GT):
896 OP(FILTER_OP_LT):
897 OP(FILTER_OP_GE):
898 OP(FILTER_OP_LE):
899 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
900 (unsigned int) *(filter_opcode_t *) pc);
901 ret = -EINVAL;
902 goto end;
903
904 OP(FILTER_OP_EQ_STRING):
905 {
906 int res;
907
908 res = (stack_strcmp(stack, top, "==") == 0);
909 estack_pop(stack, top, ax, bx);
910 estack_ax_v = res;
911 next_pc += sizeof(struct binary_op);
912 PO;
913 }
914 OP(FILTER_OP_NE_STRING):
915 {
916 int res;
917
918 res = (stack_strcmp(stack, top, "!=") != 0);
919 estack_pop(stack, top, ax, bx);
920 estack_ax_v = res;
921 next_pc += sizeof(struct binary_op);
922 PO;
923 }
924 OP(FILTER_OP_GT_STRING):
925 {
926 int res;
927
928 res = (stack_strcmp(stack, top, ">") > 0);
929 estack_pop(stack, top, ax, bx);
930 estack_ax_v = res;
931 next_pc += sizeof(struct binary_op);
932 PO;
933 }
934 OP(FILTER_OP_LT_STRING):
935 {
936 int res;
937
938 res = (stack_strcmp(stack, top, "<") < 0);
939 estack_pop(stack, top, ax, bx);
940 estack_ax_v = res;
941 next_pc += sizeof(struct binary_op);
942 PO;
943 }
944 OP(FILTER_OP_GE_STRING):
945 {
946 int res;
947
948 res = (stack_strcmp(stack, top, ">=") >= 0);
949 estack_pop(stack, top, ax, bx);
950 estack_ax_v = res;
951 next_pc += sizeof(struct binary_op);
952 PO;
953 }
954 OP(FILTER_OP_LE_STRING):
955 {
956 int res;
957
958 res = (stack_strcmp(stack, top, "<=") <= 0);
959 estack_pop(stack, top, ax, bx);
960 estack_ax_v = res;
961 next_pc += sizeof(struct binary_op);
962 PO;
963 }
964
02aca193
PP
965 OP(FILTER_OP_EQ_STAR_GLOB_STRING):
966 {
967 int res;
968
969 res = (stack_star_glob_match(stack, top, "==") == 0);
970 estack_pop(stack, top, ax, bx);
971 estack_ax_v = res;
972 next_pc += sizeof(struct binary_op);
973 PO;
974 }
975 OP(FILTER_OP_NE_STAR_GLOB_STRING):
976 {
977 int res;
978
979 res = (stack_star_glob_match(stack, top, "!=") != 0);
980 estack_pop(stack, top, ax, bx);
981 estack_ax_v = res;
982 next_pc += sizeof(struct binary_op);
983 PO;
984 }
985
07dfc1d0
MD
986 OP(FILTER_OP_EQ_S64):
987 {
988 int res;
989
990 res = (estack_bx_v == estack_ax_v);
991 estack_pop(stack, top, ax, bx);
992 estack_ax_v = res;
993 next_pc += sizeof(struct binary_op);
994 PO;
995 }
996 OP(FILTER_OP_NE_S64):
997 {
998 int res;
999
1000 res = (estack_bx_v != estack_ax_v);
1001 estack_pop(stack, top, ax, bx);
1002 estack_ax_v = res;
1003 next_pc += sizeof(struct binary_op);
1004 PO;
1005 }
1006 OP(FILTER_OP_GT_S64):
1007 {
1008 int res;
1009
1010 res = (estack_bx_v > estack_ax_v);
1011 estack_pop(stack, top, ax, bx);
1012 estack_ax_v = res;
1013 next_pc += sizeof(struct binary_op);
1014 PO;
1015 }
1016 OP(FILTER_OP_LT_S64):
1017 {
1018 int res;
1019
1020 res = (estack_bx_v < estack_ax_v);
1021 estack_pop(stack, top, ax, bx);
1022 estack_ax_v = res;
1023 next_pc += sizeof(struct binary_op);
1024 PO;
1025 }
1026 OP(FILTER_OP_GE_S64):
1027 {
1028 int res;
1029
1030 res = (estack_bx_v >= estack_ax_v);
1031 estack_pop(stack, top, ax, bx);
1032 estack_ax_v = res;
1033 next_pc += sizeof(struct binary_op);
1034 PO;
1035 }
1036 OP(FILTER_OP_LE_S64):
1037 {
1038 int res;
1039
1040 res = (estack_bx_v <= estack_ax_v);
1041 estack_pop(stack, top, ax, bx);
1042 estack_ax_v = res;
1043 next_pc += sizeof(struct binary_op);
1044 PO;
1045 }
1046
1047 OP(FILTER_OP_EQ_DOUBLE):
1048 OP(FILTER_OP_NE_DOUBLE):
1049 OP(FILTER_OP_GT_DOUBLE):
1050 OP(FILTER_OP_LT_DOUBLE):
1051 OP(FILTER_OP_GE_DOUBLE):
1052 OP(FILTER_OP_LE_DOUBLE):
1053 {
1054 BUG_ON(1);
1055 PO;
1056 }
1057
1058 /* Mixed S64-double binary comparators */
1059 OP(FILTER_OP_EQ_DOUBLE_S64):
1060 OP(FILTER_OP_NE_DOUBLE_S64):
1061 OP(FILTER_OP_GT_DOUBLE_S64):
1062 OP(FILTER_OP_LT_DOUBLE_S64):
1063 OP(FILTER_OP_GE_DOUBLE_S64):
1064 OP(FILTER_OP_LE_DOUBLE_S64):
1065 OP(FILTER_OP_EQ_S64_DOUBLE):
1066 OP(FILTER_OP_NE_S64_DOUBLE):
1067 OP(FILTER_OP_GT_S64_DOUBLE):
1068 OP(FILTER_OP_LT_S64_DOUBLE):
1069 OP(FILTER_OP_GE_S64_DOUBLE):
1070 OP(FILTER_OP_LE_S64_DOUBLE):
1071 {
1072 BUG_ON(1);
1073 PO;
1074 }
e16c054b
MD
1075 OP(FILTER_OP_BIT_RSHIFT):
1076 {
1077 int64_t res;
1078
ea13ec96
MD
1079 /* Catch undefined behavior. */
1080 if (unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
1081 ret = -EINVAL;
1082 goto end;
1083 }
f8d42740 1084 res = ((uint64_t) estack_bx_v >> (uint32_t) estack_ax_v);
e16c054b
MD
1085 estack_pop(stack, top, ax, bx);
1086 estack_ax_v = res;
1087 next_pc += sizeof(struct binary_op);
1088 PO;
1089 }
1090 OP(FILTER_OP_BIT_LSHIFT):
1091 {
1092 int64_t res;
1093
ea13ec96
MD
1094 /* Catch undefined behavior. */
1095 if (unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
1096 ret = -EINVAL;
1097 goto end;
1098 }
f8d42740 1099 res = ((uint64_t) estack_bx_v << (uint32_t) estack_ax_v);
e16c054b
MD
1100 estack_pop(stack, top, ax, bx);
1101 estack_ax_v = res;
1102 next_pc += sizeof(struct binary_op);
1103 PO;
1104 }
3834b99f
MD
1105 OP(FILTER_OP_BIT_AND):
1106 {
1107 int64_t res;
1108
f8d42740 1109 res = ((uint64_t) estack_bx_v & (uint64_t) estack_ax_v);
3834b99f
MD
1110 estack_pop(stack, top, ax, bx);
1111 estack_ax_v = res;
1112 next_pc += sizeof(struct binary_op);
1113 PO;
1114 }
1115 OP(FILTER_OP_BIT_OR):
1116 {
1117 int64_t res;
1118
f8d42740 1119 res = ((uint64_t) estack_bx_v | (uint64_t) estack_ax_v);
3834b99f
MD
1120 estack_pop(stack, top, ax, bx);
1121 estack_ax_v = res;
1122 next_pc += sizeof(struct binary_op);
1123 PO;
1124 }
1125 OP(FILTER_OP_BIT_XOR):
1126 {
1127 int64_t res;
1128
f8d42740 1129 res = ((uint64_t) estack_bx_v ^ (uint64_t) estack_ax_v);
3834b99f
MD
1130 estack_pop(stack, top, ax, bx);
1131 estack_ax_v = res;
1132 next_pc += sizeof(struct binary_op);
1133 PO;
1134 }
07dfc1d0
MD
1135
1136 /* unary */
1137 OP(FILTER_OP_UNARY_PLUS):
1138 OP(FILTER_OP_UNARY_MINUS):
1139 OP(FILTER_OP_UNARY_NOT):
1140 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
1141 (unsigned int) *(filter_opcode_t *) pc);
1142 ret = -EINVAL;
1143 goto end;
1144
1145
e16c054b
MD
1146 OP(FILTER_OP_UNARY_BIT_NOT):
1147 {
f8d42740 1148 estack_ax_v = ~(uint64_t) estack_ax_v;
e16c054b
MD
1149 next_pc += sizeof(struct unary_op);
1150 PO;
1151 }
1152
07dfc1d0
MD
1153 OP(FILTER_OP_UNARY_PLUS_S64):
1154 {
1155 next_pc += sizeof(struct unary_op);
1156 PO;
1157 }
1158 OP(FILTER_OP_UNARY_MINUS_S64):
1159 {
1160 estack_ax_v = -estack_ax_v;
1161 next_pc += sizeof(struct unary_op);
1162 PO;
1163 }
1164 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
1165 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
1166 {
1167 BUG_ON(1);
1168 PO;
1169 }
1170 OP(FILTER_OP_UNARY_NOT_S64):
1171 {
1172 estack_ax_v = !estack_ax_v;
1173 next_pc += sizeof(struct unary_op);
1174 PO;
1175 }
1176 OP(FILTER_OP_UNARY_NOT_DOUBLE):
1177 {
1178 BUG_ON(1);
1179 PO;
1180 }
1181
1182 /* logical */
1183 OP(FILTER_OP_AND):
1184 {
1185 struct logical_op *insn = (struct logical_op *) pc;
1186
1187 /* If AX is 0, skip and evaluate to 0 */
1188 if (unlikely(estack_ax_v == 0)) {
1189 dbg_printk("Jumping to bytecode offset %u\n",
1190 (unsigned int) insn->skip_offset);
1191 next_pc = start_pc + insn->skip_offset;
1192 } else {
1193 /* Pop 1 when jump not taken */
1194 estack_pop(stack, top, ax, bx);
1195 next_pc += sizeof(struct logical_op);
1196 }
1197 PO;
1198 }
1199 OP(FILTER_OP_OR):
1200 {
1201 struct logical_op *insn = (struct logical_op *) pc;
1202
1203 /* If AX is nonzero, skip and evaluate to 1 */
1204
1205 if (unlikely(estack_ax_v != 0)) {
1206 estack_ax_v = 1;
1207 dbg_printk("Jumping to bytecode offset %u\n",
1208 (unsigned int) insn->skip_offset);
1209 next_pc = start_pc + insn->skip_offset;
1210 } else {
1211 /* Pop 1 when jump not taken */
1212 estack_pop(stack, top, ax, bx);
1213 next_pc += sizeof(struct logical_op);
1214 }
1215 PO;
1216 }
1217
1218
1219 /* load field ref */
1220 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
1221 {
1222 struct load_op *insn = (struct load_op *) pc;
1223 struct field_ref *ref = (struct field_ref *) insn->data;
1224
1225 dbg_printk("load field ref offset %u type string\n",
1226 ref->offset);
1227 estack_push(stack, top, ax, bx);
1228 estack_ax(stack, top)->u.s.str =
1229 *(const char * const *) &filter_stack_data[ref->offset];
1230 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1231 dbg_printk("Filter warning: loading a NULL string.\n");
1232 ret = -EINVAL;
1233 goto end;
1234 }
cbc19040 1235 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1236 estack_ax(stack, top)->u.s.literal_type =
1237 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1238 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1239 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
1240 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1241 PO;
1242 }
1243
1244 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
1245 {
1246 struct load_op *insn = (struct load_op *) pc;
1247 struct field_ref *ref = (struct field_ref *) insn->data;
1248
1249 dbg_printk("load field ref offset %u type sequence\n",
1250 ref->offset);
1251 estack_push(stack, top, ax, bx);
1252 estack_ax(stack, top)->u.s.seq_len =
1253 *(unsigned long *) &filter_stack_data[ref->offset];
1254 estack_ax(stack, top)->u.s.str =
1255 *(const char **) (&filter_stack_data[ref->offset
1256 + sizeof(unsigned long)]);
1257 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1258 dbg_printk("Filter warning: loading a NULL sequence.\n");
1259 ret = -EINVAL;
1260 goto end;
1261 }
02aca193
PP
1262 estack_ax(stack, top)->u.s.literal_type =
1263 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1264 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1265 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1266 PO;
1267 }
1268
1269 OP(FILTER_OP_LOAD_FIELD_REF_S64):
1270 {
1271 struct load_op *insn = (struct load_op *) pc;
1272 struct field_ref *ref = (struct field_ref *) insn->data;
1273
1274 dbg_printk("load field ref offset %u type s64\n",
1275 ref->offset);
1276 estack_push(stack, top, ax, bx);
1277 estack_ax_v =
1278 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
1279 dbg_printk("ref load s64 %lld\n",
1280 (long long) estack_ax_v);
1281 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1282 PO;
1283 }
1284
1285 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
1286 {
1287 BUG_ON(1);
1288 PO;
1289 }
1290
1291 /* load from immediate operand */
1292 OP(FILTER_OP_LOAD_STRING):
1293 {
1294 struct load_op *insn = (struct load_op *) pc;
1295
1296 dbg_printk("load string %s\n", insn->data);
1297 estack_push(stack, top, ax, bx);
1298 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 1299 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1300 estack_ax(stack, top)->u.s.literal_type =
1301 ESTACK_STRING_LITERAL_TYPE_PLAIN;
1302 estack_ax(stack, top)->u.s.user = 0;
1303 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1304 PO;
1305 }
1306
1307 OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
1308 {
1309 struct load_op *insn = (struct load_op *) pc;
1310
1311 dbg_printk("load globbing pattern %s\n", insn->data);
1312 estack_push(stack, top, ax, bx);
1313 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 1314 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1315 estack_ax(stack, top)->u.s.literal_type =
1316 ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
f127e61e 1317 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1318 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1319 PO;
1320 }
1321
1322 OP(FILTER_OP_LOAD_S64):
1323 {
1324 struct load_op *insn = (struct load_op *) pc;
1325
1326 estack_push(stack, top, ax, bx);
1327 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
1328 dbg_printk("load s64 %lld\n",
1329 (long long) estack_ax_v);
1330 next_pc += sizeof(struct load_op)
1331 + sizeof(struct literal_numeric);
1332 PO;
1333 }
1334
1335 OP(FILTER_OP_LOAD_DOUBLE):
1336 {
1337 BUG_ON(1);
1338 PO;
1339 }
1340
1341 /* cast */
1342 OP(FILTER_OP_CAST_TO_S64):
1343 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
1344 (unsigned int) *(filter_opcode_t *) pc);
1345 ret = -EINVAL;
1346 goto end;
1347
1348 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
1349 {
1350 BUG_ON(1);
1351 PO;
1352 }
1353
1354 OP(FILTER_OP_CAST_NOP):
1355 {
1356 next_pc += sizeof(struct cast_op);
1357 PO;
1358 }
1359
1360 /* get context ref */
1361 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
1362 {
1363 struct load_op *insn = (struct load_op *) pc;
1364 struct field_ref *ref = (struct field_ref *) insn->data;
1365 struct lttng_ctx_field *ctx_field;
1366 union lttng_ctx_value v;
1367
1368 dbg_printk("get context ref offset %u type string\n",
1369 ref->offset);
1370 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 1371 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
1372 estack_push(stack, top, ax, bx);
1373 estack_ax(stack, top)->u.s.str = v.str;
1374 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1375 dbg_printk("Filter warning: loading a NULL string.\n");
1376 ret = -EINVAL;
1377 goto end;
1378 }
cbc19040 1379 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1380 estack_ax(stack, top)->u.s.literal_type =
1381 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1382 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1383 dbg_printk("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
1384 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1385 PO;
1386 }
1387
1388 OP(FILTER_OP_GET_CONTEXT_REF_S64):
1389 {
1390 struct load_op *insn = (struct load_op *) pc;
1391 struct field_ref *ref = (struct field_ref *) insn->data;
1392 struct lttng_ctx_field *ctx_field;
1393 union lttng_ctx_value v;
1394
1395 dbg_printk("get context ref offset %u type s64\n",
1396 ref->offset);
1397 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 1398 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
1399 estack_push(stack, top, ax, bx);
1400 estack_ax_v = v.s64;
1401 dbg_printk("ref get context s64 %lld\n",
1402 (long long) estack_ax_v);
1403 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1404 PO;
1405 }
1406
1407 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
1408 {
1409 BUG_ON(1);
1410 PO;
1411 }
1412
f127e61e
MD
1413 /* load userspace field ref */
1414 OP(FILTER_OP_LOAD_FIELD_REF_USER_STRING):
1415 {
1416 struct load_op *insn = (struct load_op *) pc;
1417 struct field_ref *ref = (struct field_ref *) insn->data;
1418
1419 dbg_printk("load field ref offset %u type user string\n",
1420 ref->offset);
1421 estack_push(stack, top, ax, bx);
5b4ad89f 1422 estack_ax(stack, top)->u.s.user_str =
f127e61e 1423 *(const char * const *) &filter_stack_data[ref->offset];
23a2f61f 1424 if (unlikely(!estack_ax(stack, top)->u.s.user_str)) {
f127e61e
MD
1425 dbg_printk("Filter warning: loading a NULL string.\n");
1426 ret = -EINVAL;
1427 goto end;
1428 }
cbc19040 1429 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1430 estack_ax(stack, top)->u.s.literal_type =
1431 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1432 estack_ax(stack, top)->u.s.user = 1;
23a2f61f 1433 dbg_load_ref_user_str_printk(estack_ax(stack, top));
f127e61e
MD
1434 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1435 PO;
1436 }
1437
1438 OP(FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE):
1439 {
1440 struct load_op *insn = (struct load_op *) pc;
1441 struct field_ref *ref = (struct field_ref *) insn->data;
1442
1443 dbg_printk("load field ref offset %u type user sequence\n",
1444 ref->offset);
1445 estack_push(stack, top, ax, bx);
1446 estack_ax(stack, top)->u.s.seq_len =
1447 *(unsigned long *) &filter_stack_data[ref->offset];
5b4ad89f 1448 estack_ax(stack, top)->u.s.user_str =
f127e61e
MD
1449 *(const char **) (&filter_stack_data[ref->offset
1450 + sizeof(unsigned long)]);
23a2f61f 1451 if (unlikely(!estack_ax(stack, top)->u.s.user_str)) {
f127e61e
MD
1452 dbg_printk("Filter warning: loading a NULL sequence.\n");
1453 ret = -EINVAL;
1454 goto end;
1455 }
02aca193
PP
1456 estack_ax(stack, top)->u.s.literal_type =
1457 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e
MD
1458 estack_ax(stack, top)->u.s.user = 1;
1459 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1460 PO;
1461 }
1462
3834b99f
MD
1463 OP(FILTER_OP_GET_CONTEXT_ROOT):
1464 {
1465 dbg_printk("op get context root\n");
1466 estack_push(stack, top, ax, bx);
1467 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_CONTEXT;
1468 /* "field" only needed for variants. */
1469 estack_ax(stack, top)->u.ptr.field = NULL;
1470 next_pc += sizeof(struct load_op);
1471 PO;
1472 }
1473
1474 OP(FILTER_OP_GET_APP_CONTEXT_ROOT):
1475 {
1476 BUG_ON(1);
1477 PO;
1478 }
1479
1480 OP(FILTER_OP_GET_PAYLOAD_ROOT):
1481 {
1482 dbg_printk("op get app payload root\n");
1483 estack_push(stack, top, ax, bx);
1484 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_PAYLOAD;
1485 estack_ax(stack, top)->u.ptr.ptr = filter_stack_data;
1486 /* "field" only needed for variants. */
1487 estack_ax(stack, top)->u.ptr.field = NULL;
1488 next_pc += sizeof(struct load_op);
1489 PO;
1490 }
1491
1492 OP(FILTER_OP_GET_SYMBOL):
1493 {
1494 dbg_printk("op get symbol\n");
1495 switch (estack_ax(stack, top)->u.ptr.type) {
1496 case LOAD_OBJECT:
1497 printk(KERN_WARNING "Nested fields not implemented yet.\n");
1498 ret = -EINVAL;
1499 goto end;
1500 case LOAD_ROOT_CONTEXT:
1501 case LOAD_ROOT_APP_CONTEXT:
1502 case LOAD_ROOT_PAYLOAD:
1503 /*
1504 * symbol lookup is performed by
1505 * specialization.
1506 */
1507 ret = -EINVAL;
1508 goto end;
1509 }
1510 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1511 PO;
1512 }
1513
1514 OP(FILTER_OP_GET_SYMBOL_FIELD):
1515 {
1516 /*
1517 * Used for first variant encountered in a
1518 * traversal. Variants are not implemented yet.
1519 */
1520 ret = -EINVAL;
1521 goto end;
1522 }
1523
1524 OP(FILTER_OP_GET_INDEX_U16):
1525 {
1526 struct load_op *insn = (struct load_op *) pc;
1527 struct get_index_u16 *index = (struct get_index_u16 *) insn->data;
1528
1529 dbg_printk("op get index u16\n");
1530 ret = dynamic_get_index(lttng_probe_ctx, bytecode, index->index, estack_ax(stack, top));
1531 if (ret)
1532 goto end;
1533 estack_ax_v = estack_ax(stack, top)->u.v;
1534 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1535 PO;
1536 }
1537
1538 OP(FILTER_OP_GET_INDEX_U64):
1539 {
1540 struct load_op *insn = (struct load_op *) pc;
1541 struct get_index_u64 *index = (struct get_index_u64 *) insn->data;
1542
1543 dbg_printk("op get index u64\n");
1544 ret = dynamic_get_index(lttng_probe_ctx, bytecode, index->index, estack_ax(stack, top));
1545 if (ret)
1546 goto end;
1547 estack_ax_v = estack_ax(stack, top)->u.v;
1548 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1549 PO;
1550 }
1551
1552 OP(FILTER_OP_LOAD_FIELD):
1553 {
1554 dbg_printk("op load field\n");
1555 ret = dynamic_load_field(estack_ax(stack, top));
1556 if (ret)
1557 goto end;
1558 estack_ax_v = estack_ax(stack, top)->u.v;
1559 next_pc += sizeof(struct load_op);
1560 PO;
1561 }
1562
1563 OP(FILTER_OP_LOAD_FIELD_S8):
1564 {
1565 dbg_printk("op load field s8\n");
1566
1567 estack_ax_v = *(int8_t *) estack_ax(stack, top)->u.ptr.ptr;
1568 next_pc += sizeof(struct load_op);
1569 PO;
1570 }
1571 OP(FILTER_OP_LOAD_FIELD_S16):
1572 {
1573 dbg_printk("op load field s16\n");
1574
1575 estack_ax_v = *(int16_t *) estack_ax(stack, top)->u.ptr.ptr;
1576 next_pc += sizeof(struct load_op);
1577 PO;
1578 }
1579 OP(FILTER_OP_LOAD_FIELD_S32):
1580 {
1581 dbg_printk("op load field s32\n");
1582
1583 estack_ax_v = *(int32_t *) estack_ax(stack, top)->u.ptr.ptr;
1584 next_pc += sizeof(struct load_op);
1585 PO;
1586 }
1587 OP(FILTER_OP_LOAD_FIELD_S64):
1588 {
1589 dbg_printk("op load field s64\n");
1590
1591 estack_ax_v = *(int64_t *) estack_ax(stack, top)->u.ptr.ptr;
1592 next_pc += sizeof(struct load_op);
1593 PO;
1594 }
1595 OP(FILTER_OP_LOAD_FIELD_U8):
1596 {
1597 dbg_printk("op load field u8\n");
1598
1599 estack_ax_v = *(uint8_t *) estack_ax(stack, top)->u.ptr.ptr;
1600 next_pc += sizeof(struct load_op);
1601 PO;
1602 }
1603 OP(FILTER_OP_LOAD_FIELD_U16):
1604 {
1605 dbg_printk("op load field u16\n");
1606
1607 estack_ax_v = *(uint16_t *) estack_ax(stack, top)->u.ptr.ptr;
1608 next_pc += sizeof(struct load_op);
1609 PO;
1610 }
1611 OP(FILTER_OP_LOAD_FIELD_U32):
1612 {
1613 dbg_printk("op load field u32\n");
1614
1615 estack_ax_v = *(uint32_t *) estack_ax(stack, top)->u.ptr.ptr;
1616 next_pc += sizeof(struct load_op);
1617 PO;
1618 }
1619 OP(FILTER_OP_LOAD_FIELD_U64):
1620 {
1621 dbg_printk("op load field u64\n");
1622
1623 estack_ax_v = *(uint64_t *) estack_ax(stack, top)->u.ptr.ptr;
1624 next_pc += sizeof(struct load_op);
1625 PO;
1626 }
1627 OP(FILTER_OP_LOAD_FIELD_DOUBLE):
1628 {
1629 ret = -EINVAL;
1630 goto end;
1631 }
1632
1633 OP(FILTER_OP_LOAD_FIELD_STRING):
1634 {
1635 const char *str;
1636
1637 dbg_printk("op load field string\n");
1638 str = (const char *) estack_ax(stack, top)->u.ptr.ptr;
1639 estack_ax(stack, top)->u.s.str = str;
1640 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1641 dbg_printk("Filter warning: loading a NULL string.\n");
1642 ret = -EINVAL;
1643 goto end;
1644 }
4efe037b 1645 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
3834b99f
MD
1646 estack_ax(stack, top)->u.s.literal_type =
1647 ESTACK_STRING_LITERAL_TYPE_NONE;
c89271d4 1648 estack_ax(stack, top)->u.s.user = 0;
3834b99f
MD
1649 next_pc += sizeof(struct load_op);
1650 PO;
1651 }
1652
1653 OP(FILTER_OP_LOAD_FIELD_SEQUENCE):
1654 {
1655 const char *ptr;
1656
1657 dbg_printk("op load field string sequence\n");
1658 ptr = estack_ax(stack, top)->u.ptr.ptr;
1659 estack_ax(stack, top)->u.s.seq_len = *(unsigned long *) ptr;
1660 estack_ax(stack, top)->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
1661 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1662 dbg_printk("Filter warning: loading a NULL sequence.\n");
1663 ret = -EINVAL;
1664 goto end;
1665 }
1666 estack_ax(stack, top)->u.s.literal_type =
1667 ESTACK_STRING_LITERAL_TYPE_NONE;
c89271d4 1668 estack_ax(stack, top)->u.s.user = 0;
3834b99f
MD
1669 next_pc += sizeof(struct load_op);
1670 PO;
1671 }
1672
07dfc1d0
MD
1673 END_OP
1674end:
1675 /* return 0 (discard) on error */
1676 if (ret)
1677 return 0;
1678 return retval;
1679}
1680
1681#undef START_OP
1682#undef OP
1683#undef PO
1684#undef END_OP
This page took 0.114278 seconds and 4 git commands to generate.