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 insn
->op
= FILTER_OP_EQ_STRING
;
83 if (vstack_bx(stack
)->type
== REG_S64
)
84 insn
->op
= FILTER_OP_EQ_S64
;
86 insn
->op
= FILTER_OP_EQ_DOUBLE_S64
;
89 if (vstack_bx(stack
)->type
== REG_S64
)
90 insn
->op
= FILTER_OP_EQ_S64_DOUBLE
;
92 insn
->op
= FILTER_OP_EQ_DOUBLE
;
96 if (vstack_pop(stack
)) {
100 vstack_ax(stack
)->type
= REG_S64
;
101 next_pc
+= sizeof(struct binary_op
);
107 struct binary_op
*insn
= (struct binary_op
*) pc
;
109 switch(vstack_ax(stack
)->type
) {
111 printk(KERN_WARNING
"unknown register type\n");
116 insn
->op
= FILTER_OP_NE_STRING
;
119 if (vstack_bx(stack
)->type
== REG_S64
)
120 insn
->op
= FILTER_OP_NE_S64
;
122 insn
->op
= FILTER_OP_NE_DOUBLE_S64
;
125 if (vstack_bx(stack
)->type
== REG_S64
)
126 insn
->op
= FILTER_OP_NE_S64_DOUBLE
;
128 insn
->op
= FILTER_OP_NE_DOUBLE
;
132 if (vstack_pop(stack
)) {
136 vstack_ax(stack
)->type
= REG_S64
;
137 next_pc
+= sizeof(struct binary_op
);
143 struct binary_op
*insn
= (struct binary_op
*) pc
;
145 switch(vstack_ax(stack
)->type
) {
147 printk(KERN_WARNING
"unknown register type\n");
152 insn
->op
= FILTER_OP_GT_STRING
;
155 if (vstack_bx(stack
)->type
== REG_S64
)
156 insn
->op
= FILTER_OP_GT_S64
;
158 insn
->op
= FILTER_OP_GT_DOUBLE_S64
;
161 if (vstack_bx(stack
)->type
== REG_S64
)
162 insn
->op
= FILTER_OP_GT_S64_DOUBLE
;
164 insn
->op
= FILTER_OP_GT_DOUBLE
;
168 if (vstack_pop(stack
)) {
172 vstack_ax(stack
)->type
= REG_S64
;
173 next_pc
+= sizeof(struct binary_op
);
179 struct binary_op
*insn
= (struct binary_op
*) pc
;
181 switch(vstack_ax(stack
)->type
) {
183 printk(KERN_WARNING
"unknown register type\n");
188 insn
->op
= FILTER_OP_LT_STRING
;
191 if (vstack_bx(stack
)->type
== REG_S64
)
192 insn
->op
= FILTER_OP_LT_S64
;
194 insn
->op
= FILTER_OP_LT_DOUBLE_S64
;
197 if (vstack_bx(stack
)->type
== REG_S64
)
198 insn
->op
= FILTER_OP_LT_S64_DOUBLE
;
200 insn
->op
= FILTER_OP_LT_DOUBLE
;
204 if (vstack_pop(stack
)) {
208 vstack_ax(stack
)->type
= REG_S64
;
209 next_pc
+= sizeof(struct binary_op
);
215 struct binary_op
*insn
= (struct binary_op
*) pc
;
217 switch(vstack_ax(stack
)->type
) {
219 printk(KERN_WARNING
"unknown register type\n");
224 insn
->op
= FILTER_OP_GE_STRING
;
227 if (vstack_bx(stack
)->type
== REG_S64
)
228 insn
->op
= FILTER_OP_GE_S64
;
230 insn
->op
= FILTER_OP_GE_DOUBLE_S64
;
233 if (vstack_bx(stack
)->type
== REG_S64
)
234 insn
->op
= FILTER_OP_GE_S64_DOUBLE
;
236 insn
->op
= FILTER_OP_GE_DOUBLE
;
240 if (vstack_pop(stack
)) {
244 vstack_ax(stack
)->type
= REG_S64
;
245 next_pc
+= sizeof(struct binary_op
);
250 struct binary_op
*insn
= (struct binary_op
*) pc
;
252 switch(vstack_ax(stack
)->type
) {
254 printk(KERN_WARNING
"unknown register type\n");
259 insn
->op
= FILTER_OP_LE_STRING
;
262 if (vstack_bx(stack
)->type
== REG_S64
)
263 insn
->op
= FILTER_OP_LE_S64
;
265 insn
->op
= FILTER_OP_LE_DOUBLE_S64
;
268 if (vstack_bx(stack
)->type
== REG_S64
)
269 insn
->op
= FILTER_OP_LE_S64_DOUBLE
;
271 insn
->op
= FILTER_OP_LE_DOUBLE
;
274 vstack_ax(stack
)->type
= REG_S64
;
275 next_pc
+= sizeof(struct binary_op
);
279 case FILTER_OP_EQ_STRING
:
280 case FILTER_OP_NE_STRING
:
281 case FILTER_OP_GT_STRING
:
282 case FILTER_OP_LT_STRING
:
283 case FILTER_OP_GE_STRING
:
284 case FILTER_OP_LE_STRING
:
285 case FILTER_OP_EQ_S64
:
286 case FILTER_OP_NE_S64
:
287 case FILTER_OP_GT_S64
:
288 case FILTER_OP_LT_S64
:
289 case FILTER_OP_GE_S64
:
290 case FILTER_OP_LE_S64
:
291 case FILTER_OP_EQ_DOUBLE
:
292 case FILTER_OP_NE_DOUBLE
:
293 case FILTER_OP_GT_DOUBLE
:
294 case FILTER_OP_LT_DOUBLE
:
295 case FILTER_OP_GE_DOUBLE
:
296 case FILTER_OP_LE_DOUBLE
:
297 case FILTER_OP_EQ_DOUBLE_S64
:
298 case FILTER_OP_NE_DOUBLE_S64
:
299 case FILTER_OP_GT_DOUBLE_S64
:
300 case FILTER_OP_LT_DOUBLE_S64
:
301 case FILTER_OP_GE_DOUBLE_S64
:
302 case FILTER_OP_LE_DOUBLE_S64
:
303 case FILTER_OP_EQ_S64_DOUBLE
:
304 case FILTER_OP_NE_S64_DOUBLE
:
305 case FILTER_OP_GT_S64_DOUBLE
:
306 case FILTER_OP_LT_S64_DOUBLE
:
307 case FILTER_OP_GE_S64_DOUBLE
:
308 case FILTER_OP_LE_S64_DOUBLE
:
311 if (vstack_pop(stack
)) {
315 vstack_ax(stack
)->type
= REG_S64
;
316 next_pc
+= sizeof(struct binary_op
);
321 case FILTER_OP_UNARY_PLUS
:
323 struct unary_op
*insn
= (struct unary_op
*) pc
;
325 switch(vstack_ax(stack
)->type
) {
327 printk(KERN_WARNING
"unknown register type\n");
332 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
335 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
339 next_pc
+= sizeof(struct unary_op
);
343 case FILTER_OP_UNARY_MINUS
:
345 struct unary_op
*insn
= (struct unary_op
*) pc
;
347 switch(vstack_ax(stack
)->type
) {
349 printk(KERN_WARNING
"unknown register type\n");
354 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
357 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
361 next_pc
+= sizeof(struct unary_op
);
365 case FILTER_OP_UNARY_NOT
:
367 struct unary_op
*insn
= (struct unary_op
*) pc
;
369 switch(vstack_ax(stack
)->type
) {
371 printk(KERN_WARNING
"unknown register type\n");
376 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
379 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
383 next_pc
+= sizeof(struct unary_op
);
387 case FILTER_OP_UNARY_PLUS_S64
:
388 case FILTER_OP_UNARY_MINUS_S64
:
389 case FILTER_OP_UNARY_NOT_S64
:
390 case FILTER_OP_UNARY_PLUS_DOUBLE
:
391 case FILTER_OP_UNARY_MINUS_DOUBLE
:
392 case FILTER_OP_UNARY_NOT_DOUBLE
:
395 next_pc
+= sizeof(struct unary_op
);
403 /* Continue to next instruction */
404 /* Pop 1 when jump not taken */
405 if (vstack_pop(stack
)) {
409 next_pc
+= sizeof(struct logical_op
);
414 case FILTER_OP_LOAD_FIELD_REF
:
416 printk(KERN_WARNING
"Unknown field ref type\n");
420 /* get context ref */
421 case FILTER_OP_GET_CONTEXT_REF
:
423 printk(KERN_WARNING
"Unknown get context ref type\n");
427 case FILTER_OP_LOAD_FIELD_REF_STRING
:
428 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
429 case FILTER_OP_GET_CONTEXT_REF_STRING
:
430 case FILTER_OP_LOAD_FIELD_REF_USER_STRING
:
431 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE
:
433 if (vstack_push(stack
)) {
437 vstack_ax(stack
)->type
= REG_STRING
;
438 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
441 case FILTER_OP_LOAD_FIELD_REF_S64
:
442 case FILTER_OP_GET_CONTEXT_REF_S64
:
444 if (vstack_push(stack
)) {
448 vstack_ax(stack
)->type
= REG_S64
;
449 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
452 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
453 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
455 if (vstack_push(stack
)) {
459 vstack_ax(stack
)->type
= REG_DOUBLE
;
460 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
464 /* load from immediate operand */
465 case FILTER_OP_LOAD_STRING
:
467 struct load_op
*insn
= (struct load_op
*) pc
;
469 if (vstack_push(stack
)) {
473 vstack_ax(stack
)->type
= REG_STRING
;
474 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
478 case FILTER_OP_LOAD_S64
:
480 if (vstack_push(stack
)) {
484 vstack_ax(stack
)->type
= REG_S64
;
485 next_pc
+= sizeof(struct load_op
)
486 + sizeof(struct literal_numeric
);
490 case FILTER_OP_LOAD_DOUBLE
:
492 if (vstack_push(stack
)) {
496 vstack_ax(stack
)->type
= REG_DOUBLE
;
497 next_pc
+= sizeof(struct load_op
)
498 + sizeof(struct literal_double
);
503 case FILTER_OP_CAST_TO_S64
:
505 struct cast_op
*insn
= (struct cast_op
*) pc
;
507 switch (vstack_ax(stack
)->type
) {
509 printk(KERN_WARNING
"unknown register type\n");
514 printk(KERN_WARNING
"Cast op can only be applied to numeric or floating point registers\n");
518 insn
->op
= FILTER_OP_CAST_NOP
;
521 insn
->op
= FILTER_OP_CAST_DOUBLE_TO_S64
;
525 vstack_ax(stack
)->type
= REG_S64
;
526 next_pc
+= sizeof(struct cast_op
);
529 case FILTER_OP_CAST_DOUBLE_TO_S64
:
532 vstack_ax(stack
)->type
= REG_S64
;
533 next_pc
+= sizeof(struct cast_op
);
536 case FILTER_OP_CAST_NOP
:
538 next_pc
+= sizeof(struct cast_op
);