Filter code relicensing to MIT license
[lttng-ust.git] / liblttng-ust / lttng-filter-specialize.c
CommitLineData
97b58163
MD
1/*
2 * lttng-filter-specialize.c
3 *
4 * LTTng UST filter code specializer.
5 *
7e50015d 6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
97b58163 7 *
7e50015d
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:
97b58163 14 *
7e50015d
MD
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
97b58163 17 *
7e50015d
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.
97b58163
MD
25 */
26
3fbec7dc 27#define _LGPL_SOURCE
97b58163
MD
28#include "lttng-filter.h"
29
30int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
31{
32 void *pc, *next_pc, *start_pc;
33 int ret = -EINVAL;
0305960f
MD
34 struct vstack _stack;
35 struct vstack *stack = &_stack;
97b58163 36
0305960f 37 vstack_init(stack);
97b58163
MD
38
39 start_pc = &bytecode->data[0];
40 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
41 pc = next_pc) {
42 switch (*(filter_opcode_t *) pc) {
43 case FILTER_OP_UNKNOWN:
44 default:
45 ERR("unknown bytecode op %u\n",
46 (unsigned int) *(filter_opcode_t *) pc);
47 ret = -EINVAL;
48 goto end;
49
50 case FILTER_OP_RETURN:
51 ret = 0;
52 goto end;
53
54 /* binary */
55 case FILTER_OP_MUL:
56 case FILTER_OP_DIV:
57 case FILTER_OP_MOD:
58 case FILTER_OP_PLUS:
59 case FILTER_OP_MINUS:
60 case FILTER_OP_RSHIFT:
61 case FILTER_OP_LSHIFT:
62 case FILTER_OP_BIN_AND:
63 case FILTER_OP_BIN_OR:
64 case FILTER_OP_BIN_XOR:
65 ERR("unsupported bytecode op %u\n",
66 (unsigned int) *(filter_opcode_t *) pc);
67 ret = -EINVAL;
68 goto end;
69
70 case FILTER_OP_EQ:
71 {
72 struct binary_op *insn = (struct binary_op *) pc;
73
0305960f 74 switch(vstack_ax(stack)->type) {
97b58163
MD
75 default:
76 ERR("unknown register type\n");
77 ret = -EINVAL;
78 goto end;
79
80 case REG_STRING:
53569322
MD
81 if (vstack_bx(stack)->type == REG_UNKNOWN)
82 break;
97b58163
MD
83 insn->op = FILTER_OP_EQ_STRING;
84 break;
85 case REG_S64:
53569322
MD
86 if (vstack_bx(stack)->type == REG_UNKNOWN)
87 break;
0305960f 88 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
89 insn->op = FILTER_OP_EQ_S64;
90 else
dbea82ec 91 insn->op = FILTER_OP_EQ_DOUBLE_S64;
97b58163
MD
92 break;
93 case REG_DOUBLE:
53569322
MD
94 if (vstack_bx(stack)->type == REG_UNKNOWN)
95 break;
dbea82ec
MD
96 if (vstack_bx(stack)->type == REG_S64)
97 insn->op = FILTER_OP_EQ_S64_DOUBLE;
98 else
99 insn->op = FILTER_OP_EQ_DOUBLE;
97b58163 100 break;
53569322
MD
101 case REG_UNKNOWN:
102 break; /* Dynamic typing. */
97b58163 103 }
0305960f
MD
104 /* Pop 2, push 1 */
105 if (vstack_pop(stack)) {
106 ret = -EINVAL;
107 goto end;
108 }
109 vstack_ax(stack)->type = REG_S64;
97b58163
MD
110 next_pc += sizeof(struct binary_op);
111 break;
112 }
113
114 case FILTER_OP_NE:
115 {
116 struct binary_op *insn = (struct binary_op *) pc;
117
0305960f 118 switch(vstack_ax(stack)->type) {
97b58163
MD
119 default:
120 ERR("unknown register type\n");
121 ret = -EINVAL;
122 goto end;
123
124 case REG_STRING:
53569322
MD
125 if (vstack_bx(stack)->type == REG_UNKNOWN)
126 break;
97b58163
MD
127 insn->op = FILTER_OP_NE_STRING;
128 break;
129 case REG_S64:
53569322
MD
130 if (vstack_bx(stack)->type == REG_UNKNOWN)
131 break;
0305960f 132 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
133 insn->op = FILTER_OP_NE_S64;
134 else
dbea82ec 135 insn->op = FILTER_OP_NE_DOUBLE_S64;
97b58163
MD
136 break;
137 case REG_DOUBLE:
53569322
MD
138 if (vstack_bx(stack)->type == REG_UNKNOWN)
139 break;
dbea82ec
MD
140 if (vstack_bx(stack)->type == REG_S64)
141 insn->op = FILTER_OP_NE_S64_DOUBLE;
142 else
143 insn->op = FILTER_OP_NE_DOUBLE;
97b58163 144 break;
53569322
MD
145 case REG_UNKNOWN:
146 break; /* Dynamic typing. */
97b58163 147 }
0305960f
MD
148 /* Pop 2, push 1 */
149 if (vstack_pop(stack)) {
150 ret = -EINVAL;
151 goto end;
152 }
153 vstack_ax(stack)->type = REG_S64;
97b58163
MD
154 next_pc += sizeof(struct binary_op);
155 break;
156 }
157
158 case FILTER_OP_GT:
159 {
160 struct binary_op *insn = (struct binary_op *) pc;
161
0305960f 162 switch(vstack_ax(stack)->type) {
97b58163
MD
163 default:
164 ERR("unknown register type\n");
165 ret = -EINVAL;
166 goto end;
167
168 case REG_STRING:
53569322
MD
169 if (vstack_bx(stack)->type == REG_UNKNOWN)
170 break;
97b58163
MD
171 insn->op = FILTER_OP_GT_STRING;
172 break;
173 case REG_S64:
53569322
MD
174 if (vstack_bx(stack)->type == REG_UNKNOWN)
175 break;
0305960f 176 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
177 insn->op = FILTER_OP_GT_S64;
178 else
dbea82ec 179 insn->op = FILTER_OP_GT_DOUBLE_S64;
97b58163
MD
180 break;
181 case REG_DOUBLE:
53569322
MD
182 if (vstack_bx(stack)->type == REG_UNKNOWN)
183 break;
dbea82ec
MD
184 if (vstack_bx(stack)->type == REG_S64)
185 insn->op = FILTER_OP_GT_S64_DOUBLE;
186 else
187 insn->op = FILTER_OP_GT_DOUBLE;
97b58163 188 break;
53569322
MD
189 case REG_UNKNOWN:
190 break; /* Dynamic typing. */
97b58163 191 }
0305960f
MD
192 /* Pop 2, push 1 */
193 if (vstack_pop(stack)) {
194 ret = -EINVAL;
195 goto end;
196 }
197 vstack_ax(stack)->type = REG_S64;
97b58163
MD
198 next_pc += sizeof(struct binary_op);
199 break;
200 }
201
202 case FILTER_OP_LT:
203 {
204 struct binary_op *insn = (struct binary_op *) pc;
205
0305960f 206 switch(vstack_ax(stack)->type) {
97b58163
MD
207 default:
208 ERR("unknown register type\n");
209 ret = -EINVAL;
210 goto end;
211
212 case REG_STRING:
53569322
MD
213 if (vstack_bx(stack)->type == REG_UNKNOWN)
214 break;
97b58163
MD
215 insn->op = FILTER_OP_LT_STRING;
216 break;
217 case REG_S64:
53569322
MD
218 if (vstack_bx(stack)->type == REG_UNKNOWN)
219 break;
0305960f 220 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
221 insn->op = FILTER_OP_LT_S64;
222 else
dbea82ec 223 insn->op = FILTER_OP_LT_DOUBLE_S64;
97b58163
MD
224 break;
225 case REG_DOUBLE:
53569322
MD
226 if (vstack_bx(stack)->type == REG_UNKNOWN)
227 break;
dbea82ec
MD
228 if (vstack_bx(stack)->type == REG_S64)
229 insn->op = FILTER_OP_LT_S64_DOUBLE;
230 else
231 insn->op = FILTER_OP_LT_DOUBLE;
97b58163 232 break;
53569322
MD
233 case REG_UNKNOWN:
234 break; /* Dynamic typing. */
97b58163 235 }
0305960f
MD
236 /* Pop 2, push 1 */
237 if (vstack_pop(stack)) {
238 ret = -EINVAL;
239 goto end;
240 }
241 vstack_ax(stack)->type = REG_S64;
97b58163
MD
242 next_pc += sizeof(struct binary_op);
243 break;
244 }
245
246 case FILTER_OP_GE:
247 {
248 struct binary_op *insn = (struct binary_op *) pc;
249
0305960f 250 switch(vstack_ax(stack)->type) {
97b58163
MD
251 default:
252 ERR("unknown register type\n");
253 ret = -EINVAL;
254 goto end;
255
256 case REG_STRING:
53569322
MD
257 if (vstack_bx(stack)->type == REG_UNKNOWN)
258 break;
97b58163
MD
259 insn->op = FILTER_OP_GE_STRING;
260 break;
261 case REG_S64:
53569322
MD
262 if (vstack_bx(stack)->type == REG_UNKNOWN)
263 break;
0305960f 264 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
265 insn->op = FILTER_OP_GE_S64;
266 else
dbea82ec 267 insn->op = FILTER_OP_GE_DOUBLE_S64;
97b58163
MD
268 break;
269 case REG_DOUBLE:
53569322
MD
270 if (vstack_bx(stack)->type == REG_UNKNOWN)
271 break;
dbea82ec
MD
272 if (vstack_bx(stack)->type == REG_S64)
273 insn->op = FILTER_OP_GE_S64_DOUBLE;
274 else
275 insn->op = FILTER_OP_GE_DOUBLE;
97b58163 276 break;
53569322
MD
277 case REG_UNKNOWN:
278 break; /* Dynamic typing. */
97b58163 279 }
0305960f
MD
280 /* Pop 2, push 1 */
281 if (vstack_pop(stack)) {
282 ret = -EINVAL;
283 goto end;
284 }
285 vstack_ax(stack)->type = REG_S64;
97b58163
MD
286 next_pc += sizeof(struct binary_op);
287 break;
288 }
289 case FILTER_OP_LE:
290 {
291 struct binary_op *insn = (struct binary_op *) pc;
292
0305960f 293 switch(vstack_ax(stack)->type) {
97b58163
MD
294 default:
295 ERR("unknown register type\n");
296 ret = -EINVAL;
297 goto end;
298
299 case REG_STRING:
53569322
MD
300 if (vstack_bx(stack)->type == REG_UNKNOWN)
301 break;
97b58163
MD
302 insn->op = FILTER_OP_LE_STRING;
303 break;
304 case REG_S64:
53569322
MD
305 if (vstack_bx(stack)->type == REG_UNKNOWN)
306 break;
0305960f 307 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
308 insn->op = FILTER_OP_LE_S64;
309 else
dbea82ec 310 insn->op = FILTER_OP_LE_DOUBLE_S64;
97b58163
MD
311 break;
312 case REG_DOUBLE:
53569322
MD
313 if (vstack_bx(stack)->type == REG_UNKNOWN)
314 break;
dbea82ec
MD
315 if (vstack_bx(stack)->type == REG_S64)
316 insn->op = FILTER_OP_LE_S64_DOUBLE;
317 else
318 insn->op = FILTER_OP_LE_DOUBLE;
97b58163 319 break;
53569322
MD
320 case REG_UNKNOWN:
321 break; /* Dynamic typing. */
97b58163 322 }
0305960f 323 vstack_ax(stack)->type = REG_S64;
97b58163
MD
324 next_pc += sizeof(struct binary_op);
325 break;
326 }
327
328 case FILTER_OP_EQ_STRING:
329 case FILTER_OP_NE_STRING:
330 case FILTER_OP_GT_STRING:
331 case FILTER_OP_LT_STRING:
332 case FILTER_OP_GE_STRING:
333 case FILTER_OP_LE_STRING:
334 case FILTER_OP_EQ_S64:
335 case FILTER_OP_NE_S64:
336 case FILTER_OP_GT_S64:
337 case FILTER_OP_LT_S64:
338 case FILTER_OP_GE_S64:
339 case FILTER_OP_LE_S64:
340 case FILTER_OP_EQ_DOUBLE:
341 case FILTER_OP_NE_DOUBLE:
342 case FILTER_OP_GT_DOUBLE:
343 case FILTER_OP_LT_DOUBLE:
344 case FILTER_OP_GE_DOUBLE:
345 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
346 case FILTER_OP_EQ_DOUBLE_S64:
347 case FILTER_OP_NE_DOUBLE_S64:
348 case FILTER_OP_GT_DOUBLE_S64:
349 case FILTER_OP_LT_DOUBLE_S64:
350 case FILTER_OP_GE_DOUBLE_S64:
351 case FILTER_OP_LE_DOUBLE_S64:
352 case FILTER_OP_EQ_S64_DOUBLE:
353 case FILTER_OP_NE_S64_DOUBLE:
354 case FILTER_OP_GT_S64_DOUBLE:
355 case FILTER_OP_LT_S64_DOUBLE:
356 case FILTER_OP_GE_S64_DOUBLE:
357 case FILTER_OP_LE_S64_DOUBLE:
97b58163 358 {
0305960f
MD
359 /* Pop 2, push 1 */
360 if (vstack_pop(stack)) {
361 ret = -EINVAL;
362 goto end;
363 }
364 vstack_ax(stack)->type = REG_S64;
97b58163
MD
365 next_pc += sizeof(struct binary_op);
366 break;
367 }
368
369 /* unary */
370 case FILTER_OP_UNARY_PLUS:
371 {
372 struct unary_op *insn = (struct unary_op *) pc;
373
0305960f 374 switch(vstack_ax(stack)->type) {
97b58163
MD
375 default:
376 ERR("unknown register type\n");
377 ret = -EINVAL;
378 goto end;
379
380 case REG_S64:
381 insn->op = FILTER_OP_UNARY_PLUS_S64;
382 break;
383 case REG_DOUBLE:
384 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
385 break;
53569322
MD
386 case REG_UNKNOWN: /* Dynamic typing. */
387 break;
97b58163 388 }
0305960f 389 /* Pop 1, push 1 */
97b58163
MD
390 next_pc += sizeof(struct unary_op);
391 break;
392 }
393
394 case FILTER_OP_UNARY_MINUS:
395 {
396 struct unary_op *insn = (struct unary_op *) pc;
397
0305960f 398 switch(vstack_ax(stack)->type) {
97b58163
MD
399 default:
400 ERR("unknown register type\n");
401 ret = -EINVAL;
402 goto end;
403
404 case REG_S64:
405 insn->op = FILTER_OP_UNARY_MINUS_S64;
406 break;
407 case REG_DOUBLE:
408 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
409 break;
53569322
MD
410 case REG_UNKNOWN: /* Dynamic typing. */
411 break;
97b58163 412 }
0305960f 413 /* Pop 1, push 1 */
97b58163
MD
414 next_pc += sizeof(struct unary_op);
415 break;
416 }
417
418 case FILTER_OP_UNARY_NOT:
419 {
420 struct unary_op *insn = (struct unary_op *) pc;
421
0305960f 422 switch(vstack_ax(stack)->type) {
97b58163
MD
423 default:
424 ERR("unknown register type\n");
425 ret = -EINVAL;
426 goto end;
427
428 case REG_S64:
429 insn->op = FILTER_OP_UNARY_NOT_S64;
430 break;
431 case REG_DOUBLE:
432 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
433 break;
53569322
MD
434 case REG_UNKNOWN: /* Dynamic typing. */
435 break;
97b58163 436 }
0305960f 437 /* Pop 1, push 1 */
97b58163
MD
438 next_pc += sizeof(struct unary_op);
439 break;
440 }
441
442 case FILTER_OP_UNARY_PLUS_S64:
443 case FILTER_OP_UNARY_MINUS_S64:
444 case FILTER_OP_UNARY_NOT_S64:
445 case FILTER_OP_UNARY_PLUS_DOUBLE:
446 case FILTER_OP_UNARY_MINUS_DOUBLE:
447 case FILTER_OP_UNARY_NOT_DOUBLE:
448 {
0305960f 449 /* Pop 1, push 1 */
97b58163
MD
450 next_pc += sizeof(struct unary_op);
451 break;
452 }
453
454 /* logical */
455 case FILTER_OP_AND:
456 case FILTER_OP_OR:
457 {
b9f4cd79
MD
458 /* Continue to next instruction */
459 /* Pop 1 when jump not taken */
460 if (vstack_pop(stack)) {
461 ret = -EINVAL;
462 goto end;
463 }
97b58163
MD
464 next_pc += sizeof(struct logical_op);
465 break;
466 }
467
77aa5901 468 /* load field ref */
97b58163
MD
469 case FILTER_OP_LOAD_FIELD_REF:
470 {
471 ERR("Unknown field ref type\n");
472 ret = -EINVAL;
473 goto end;
474 }
77aa5901
MD
475 /* get context ref */
476 case FILTER_OP_GET_CONTEXT_REF:
477 {
53569322
MD
478 if (vstack_push(stack)) {
479 ret = -EINVAL;
480 goto end;
481 }
482 vstack_ax(stack)->type = REG_UNKNOWN;
483 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
484 break;
77aa5901 485 }
97b58163
MD
486 case FILTER_OP_LOAD_FIELD_REF_STRING:
487 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
77aa5901 488 case FILTER_OP_GET_CONTEXT_REF_STRING:
97b58163 489 {
0305960f
MD
490 if (vstack_push(stack)) {
491 ret = -EINVAL;
492 goto end;
493 }
494 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
495 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
496 break;
497 }
498 case FILTER_OP_LOAD_FIELD_REF_S64:
77aa5901 499 case FILTER_OP_GET_CONTEXT_REF_S64:
97b58163 500 {
0305960f
MD
501 if (vstack_push(stack)) {
502 ret = -EINVAL;
503 goto end;
504 }
505 vstack_ax(stack)->type = REG_S64;
97b58163
MD
506 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
507 break;
508 }
509 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901 510 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
97b58163 511 {
0305960f
MD
512 if (vstack_push(stack)) {
513 ret = -EINVAL;
514 goto end;
515 }
516 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
517 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
518 break;
519 }
520
77aa5901 521 /* load from immediate operand */
97b58163
MD
522 case FILTER_OP_LOAD_STRING:
523 {
524 struct load_op *insn = (struct load_op *) pc;
525
0305960f
MD
526 if (vstack_push(stack)) {
527 ret = -EINVAL;
528 goto end;
529 }
530 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
531 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
532 break;
533 }
534
535 case FILTER_OP_LOAD_S64:
536 {
0305960f
MD
537 if (vstack_push(stack)) {
538 ret = -EINVAL;
539 goto end;
540 }
541 vstack_ax(stack)->type = REG_S64;
97b58163
MD
542 next_pc += sizeof(struct load_op)
543 + sizeof(struct literal_numeric);
544 break;
545 }
546
547 case FILTER_OP_LOAD_DOUBLE:
548 {
0305960f
MD
549 if (vstack_push(stack)) {
550 ret = -EINVAL;
551 goto end;
552 }
553 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
554 next_pc += sizeof(struct load_op)
555 + sizeof(struct literal_double);
556 break;
557 }
558
559 /* cast */
560 case FILTER_OP_CAST_TO_S64:
561 {
562 struct cast_op *insn = (struct cast_op *) pc;
563
0305960f 564 switch (vstack_ax(stack)->type) {
97b58163
MD
565 default:
566 ERR("unknown register type\n");
567 ret = -EINVAL;
568 goto end;
569
570 case REG_STRING:
571 ERR("Cast op can only be applied to numeric or floating point registers\n");
572 ret = -EINVAL;
573 goto end;
574 case REG_S64:
575 insn->op = FILTER_OP_CAST_NOP;
576 break;
577 case REG_DOUBLE:
578 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
579 break;
53569322
MD
580 case REG_UNKNOWN:
581 break;
97b58163 582 }
0305960f
MD
583 /* Pop 1, push 1 */
584 vstack_ax(stack)->type = REG_S64;
97b58163
MD
585 next_pc += sizeof(struct cast_op);
586 break;
587 }
588 case FILTER_OP_CAST_DOUBLE_TO_S64:
589 {
0305960f
MD
590 /* Pop 1, push 1 */
591 vstack_ax(stack)->type = REG_S64;
97b58163
MD
592 next_pc += sizeof(struct cast_op);
593 break;
594 }
595 case FILTER_OP_CAST_NOP:
596 {
597 next_pc += sizeof(struct cast_op);
598 break;
599 }
600
97b58163
MD
601 }
602 }
603end:
604 return ret;
605}
This page took 0.05259 seconds and 4 git commands to generate.