2 * lttng-filter-specialize.c
4 * LTTng modules filter code specializer.
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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
27 #include <lttng-filter.h>
29 int lttng_filter_specialize_bytecode(struct bytecode_runtime
*bytecode
)
31 void *pc
, *next_pc
, *start_pc
;
34 struct vstack
*stack
= &_stack
;
38 start_pc
= &bytecode
->data
[0];
39 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
41 switch (*(filter_opcode_t
*) pc
) {
42 case FILTER_OP_UNKNOWN
:
44 printk(KERN_WARNING
"unknown bytecode op %u\n",
45 (unsigned int) *(filter_opcode_t
*) pc
);
49 case FILTER_OP_RETURN
:
59 case FILTER_OP_RSHIFT
:
60 case FILTER_OP_LSHIFT
:
61 case FILTER_OP_BIN_AND
:
62 case FILTER_OP_BIN_OR
:
63 case FILTER_OP_BIN_XOR
:
64 printk(KERN_WARNING
"unsupported bytecode op %u\n",
65 (unsigned int) *(filter_opcode_t
*) pc
);
71 struct binary_op
*insn
= (struct binary_op
*) pc
;
73 switch(vstack_ax(stack
)->type
) {
75 printk(KERN_WARNING
"unknown register type\n");
80 if (vstack_bx(stack
)->type
== REG_STAR_GLOB_STRING
)
81 insn
->op
= FILTER_OP_EQ_STAR_GLOB_STRING
;
83 insn
->op
= FILTER_OP_EQ_STRING
;
85 case REG_STAR_GLOB_STRING
:
86 insn
->op
= FILTER_OP_EQ_STAR_GLOB_STRING
;
89 if (vstack_bx(stack
)->type
== REG_S64
)
90 insn
->op
= FILTER_OP_EQ_S64
;
92 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
95 if (vstack_bx(stack
)->type
== REG_S64
)
96 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
98 insn
->op
= FILTER_OP_EQ_DOUBLE
;
102 if (vstack_pop(stack
)) {
106 vstack_ax(stack
)->type
= REG_S64
;
107 next_pc
+= sizeof(struct binary_op
);
113 struct binary_op
*insn
= (struct binary_op
*) pc
;
115 switch(vstack_ax(stack
)->type
) {
117 printk(KERN_WARNING
"unknown register type\n");
122 if (vstack_bx(stack
)->type
== REG_STAR_GLOB_STRING
)
123 insn
->op
= FILTER_OP_NE_STAR_GLOB_STRING
;
125 insn
->op
= FILTER_OP_NE_STRING
;
127 case REG_STAR_GLOB_STRING
:
128 insn
->op
= FILTER_OP_NE_STAR_GLOB_STRING
;
131 if (vstack_bx(stack
)->type
== REG_S64
)
132 insn
->op
= FILTER_OP_NE_S64
;
134 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
137 if (vstack_bx(stack
)->type
== REG_S64
)
138 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
140 insn
->op
= FILTER_OP_NE_DOUBLE
;
144 if (vstack_pop(stack
)) {
148 vstack_ax(stack
)->type
= REG_S64
;
149 next_pc
+= sizeof(struct binary_op
);
155 struct binary_op
*insn
= (struct binary_op
*) pc
;
157 switch(vstack_ax(stack
)->type
) {
159 printk(KERN_WARNING
"unknown register type\n");
163 case REG_STAR_GLOB_STRING
:
164 printk(KERN_WARNING
"invalid register type for > binary operator\n");
168 insn
->op
= FILTER_OP_GT_STRING
;
171 if (vstack_bx(stack
)->type
== REG_S64
)
172 insn
->op
= FILTER_OP_GT_S64
;
174 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
177 if (vstack_bx(stack
)->type
== REG_S64
)
178 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
180 insn
->op
= FILTER_OP_GT_DOUBLE
;
184 if (vstack_pop(stack
)) {
188 vstack_ax(stack
)->type
= REG_S64
;
189 next_pc
+= sizeof(struct binary_op
);
195 struct binary_op
*insn
= (struct binary_op
*) pc
;
197 switch(vstack_ax(stack
)->type
) {
199 printk(KERN_WARNING
"unknown register type\n");
203 case REG_STAR_GLOB_STRING
:
204 printk(KERN_WARNING
"invalid register type for < binary operator\n");
208 insn
->op
= FILTER_OP_LT_STRING
;
211 if (vstack_bx(stack
)->type
== REG_S64
)
212 insn
->op
= FILTER_OP_LT_S64
;
214 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
217 if (vstack_bx(stack
)->type
== REG_S64
)
218 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
220 insn
->op
= FILTER_OP_LT_DOUBLE
;
224 if (vstack_pop(stack
)) {
228 vstack_ax(stack
)->type
= REG_S64
;
229 next_pc
+= sizeof(struct binary_op
);
235 struct binary_op
*insn
= (struct binary_op
*) pc
;
237 switch(vstack_ax(stack
)->type
) {
239 printk(KERN_WARNING
"unknown register type\n");
243 case REG_STAR_GLOB_STRING
:
244 printk(KERN_WARNING
"invalid register type for >= binary operator\n");
248 insn
->op
= FILTER_OP_GE_STRING
;
251 if (vstack_bx(stack
)->type
== REG_S64
)
252 insn
->op
= FILTER_OP_GE_S64
;
254 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
257 if (vstack_bx(stack
)->type
== REG_S64
)
258 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
260 insn
->op
= FILTER_OP_GE_DOUBLE
;
264 if (vstack_pop(stack
)) {
268 vstack_ax(stack
)->type
= REG_S64
;
269 next_pc
+= sizeof(struct binary_op
);
274 struct binary_op
*insn
= (struct binary_op
*) pc
;
276 switch(vstack_ax(stack
)->type
) {
278 printk(KERN_WARNING
"unknown register type\n");
282 case REG_STAR_GLOB_STRING
:
283 printk(KERN_WARNING
"invalid register type for <= binary operator\n");
287 insn
->op
= FILTER_OP_LE_STRING
;
290 if (vstack_bx(stack
)->type
== REG_S64
)
291 insn
->op
= FILTER_OP_LE_S64
;
293 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
296 if (vstack_bx(stack
)->type
== REG_S64
)
297 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
299 insn
->op
= FILTER_OP_LE_DOUBLE
;
302 vstack_ax(stack
)->type
= REG_S64
;
303 next_pc
+= sizeof(struct binary_op
);
307 case FILTER_OP_EQ_STRING
:
308 case FILTER_OP_NE_STRING
:
309 case FILTER_OP_GT_STRING
:
310 case FILTER_OP_LT_STRING
:
311 case FILTER_OP_GE_STRING
:
312 case FILTER_OP_LE_STRING
:
313 case FILTER_OP_EQ_STAR_GLOB_STRING
:
314 case FILTER_OP_NE_STAR_GLOB_STRING
:
315 case FILTER_OP_EQ_S64
:
316 case FILTER_OP_NE_S64
:
317 case FILTER_OP_GT_S64
:
318 case FILTER_OP_LT_S64
:
319 case FILTER_OP_GE_S64
:
320 case FILTER_OP_LE_S64
:
321 case FILTER_OP_EQ_DOUBLE
:
322 case FILTER_OP_NE_DOUBLE
:
323 case FILTER_OP_GT_DOUBLE
:
324 case FILTER_OP_LT_DOUBLE
:
325 case FILTER_OP_GE_DOUBLE
:
326 case FILTER_OP_LE_DOUBLE
:
327 case FILTER_OP_EQ_DOUBLE_S64
:
328 case FILTER_OP_NE_DOUBLE_S64
:
329 case FILTER_OP_GT_DOUBLE_S64
:
330 case FILTER_OP_LT_DOUBLE_S64
:
331 case FILTER_OP_GE_DOUBLE_S64
:
332 case FILTER_OP_LE_DOUBLE_S64
:
333 case FILTER_OP_EQ_S64_DOUBLE
:
334 case FILTER_OP_NE_S64_DOUBLE
:
335 case FILTER_OP_GT_S64_DOUBLE
:
336 case FILTER_OP_LT_S64_DOUBLE
:
337 case FILTER_OP_GE_S64_DOUBLE
:
338 case FILTER_OP_LE_S64_DOUBLE
:
341 if (vstack_pop(stack
)) {
345 vstack_ax(stack
)->type
= REG_S64
;
346 next_pc
+= sizeof(struct binary_op
);
351 case FILTER_OP_UNARY_PLUS
:
353 struct unary_op
*insn
= (struct unary_op
*) pc
;
355 switch(vstack_ax(stack
)->type
) {
357 printk(KERN_WARNING
"unknown register type\n");
362 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
365 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
369 next_pc
+= sizeof(struct unary_op
);
373 case FILTER_OP_UNARY_MINUS
:
375 struct unary_op
*insn
= (struct unary_op
*) pc
;
377 switch(vstack_ax(stack
)->type
) {
379 printk(KERN_WARNING
"unknown register type\n");
384 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
387 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
391 next_pc
+= sizeof(struct unary_op
);
395 case FILTER_OP_UNARY_NOT
:
397 struct unary_op
*insn
= (struct unary_op
*) pc
;
399 switch(vstack_ax(stack
)->type
) {
401 printk(KERN_WARNING
"unknown register type\n");
406 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
409 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
413 next_pc
+= sizeof(struct unary_op
);
417 case FILTER_OP_UNARY_PLUS_S64
:
418 case FILTER_OP_UNARY_MINUS_S64
:
419 case FILTER_OP_UNARY_NOT_S64
:
420 case FILTER_OP_UNARY_PLUS_DOUBLE
:
421 case FILTER_OP_UNARY_MINUS_DOUBLE
:
422 case FILTER_OP_UNARY_NOT_DOUBLE
:
425 next_pc
+= sizeof(struct unary_op
);
433 /* Continue to next instruction */
434 /* Pop 1 when jump not taken */
435 if (vstack_pop(stack
)) {
439 next_pc
+= sizeof(struct logical_op
);
444 case FILTER_OP_LOAD_FIELD_REF
:
446 printk(KERN_WARNING
"Unknown field ref type\n");
450 /* get context ref */
451 case FILTER_OP_GET_CONTEXT_REF
:
453 printk(KERN_WARNING
"Unknown get context ref type\n");
457 case FILTER_OP_LOAD_FIELD_REF_STRING
:
458 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
459 case FILTER_OP_GET_CONTEXT_REF_STRING
:
460 case FILTER_OP_LOAD_FIELD_REF_USER_STRING
:
461 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE
:
463 if (vstack_push(stack
)) {
467 vstack_ax(stack
)->type
= REG_STRING
;
468 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
471 case FILTER_OP_LOAD_FIELD_REF_S64
:
472 case FILTER_OP_GET_CONTEXT_REF_S64
:
474 if (vstack_push(stack
)) {
478 vstack_ax(stack
)->type
= REG_S64
;
479 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
482 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
483 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
485 if (vstack_push(stack
)) {
489 vstack_ax(stack
)->type
= REG_DOUBLE
;
490 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
494 /* load from immediate operand */
495 case FILTER_OP_LOAD_STRING
:
497 struct load_op
*insn
= (struct load_op
*) pc
;
499 if (vstack_push(stack
)) {
503 vstack_ax(stack
)->type
= REG_STRING
;
504 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
508 case FILTER_OP_LOAD_STAR_GLOB_STRING
:
510 struct load_op
*insn
= (struct load_op
*) pc
;
512 if (vstack_push(stack
)) {
516 vstack_ax(stack
)->type
= REG_STAR_GLOB_STRING
;
517 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
521 case FILTER_OP_LOAD_S64
:
523 if (vstack_push(stack
)) {
527 vstack_ax(stack
)->type
= REG_S64
;
528 next_pc
+= sizeof(struct load_op
)
529 + sizeof(struct literal_numeric
);
533 case FILTER_OP_LOAD_DOUBLE
:
535 if (vstack_push(stack
)) {
539 vstack_ax(stack
)->type
= REG_DOUBLE
;
540 next_pc
+= sizeof(struct load_op
)
541 + sizeof(struct literal_double
);
546 case FILTER_OP_CAST_TO_S64
:
548 struct cast_op
*insn
= (struct cast_op
*) pc
;
550 switch (vstack_ax(stack
)->type
) {
552 printk(KERN_WARNING
"unknown register type\n");
557 case REG_STAR_GLOB_STRING
:
558 printk(KERN_WARNING
"Cast op can only be applied to numeric or floating point registers\n");
562 insn
->op
= FILTER_OP_CAST_NOP
;
565 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
569 vstack_ax(stack
)->type
= REG_S64
;
570 next_pc
+= sizeof(struct cast_op
);
573 case FILTER_OP_CAST_DOUBLE_TO_S64
:
576 vstack_ax(stack
)->type
= REG_S64
;
577 next_pc
+= sizeof(struct cast_op
);
580 case FILTER_OP_CAST_NOP
:
582 next_pc
+= sizeof(struct cast_op
);