Filter code relicensing to MIT license
[lttng-ust.git] / liblttng-ust / lttng-filter-specialize.c
1 /*
2 * lttng-filter-specialize.c
3 *
4 * LTTng UST filter code specializer.
5 *
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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.
25 */
26
27 #define _LGPL_SOURCE
28 #include "lttng-filter.h"
29
30 int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
31 {
32 void *pc, *next_pc, *start_pc;
33 int ret = -EINVAL;
34 struct vstack _stack;
35 struct vstack *stack = &_stack;
36
37 vstack_init(stack);
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
74 switch(vstack_ax(stack)->type) {
75 default:
76 ERR("unknown register type\n");
77 ret = -EINVAL;
78 goto end;
79
80 case REG_STRING:
81 if (vstack_bx(stack)->type == REG_UNKNOWN)
82 break;
83 insn->op = FILTER_OP_EQ_STRING;
84 break;
85 case REG_S64:
86 if (vstack_bx(stack)->type == REG_UNKNOWN)
87 break;
88 if (vstack_bx(stack)->type == REG_S64)
89 insn->op = FILTER_OP_EQ_S64;
90 else
91 insn->op = FILTER_OP_EQ_DOUBLE_S64;
92 break;
93 case REG_DOUBLE:
94 if (vstack_bx(stack)->type == REG_UNKNOWN)
95 break;
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;
100 break;
101 case REG_UNKNOWN:
102 break; /* Dynamic typing. */
103 }
104 /* Pop 2, push 1 */
105 if (vstack_pop(stack)) {
106 ret = -EINVAL;
107 goto end;
108 }
109 vstack_ax(stack)->type = REG_S64;
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
118 switch(vstack_ax(stack)->type) {
119 default:
120 ERR("unknown register type\n");
121 ret = -EINVAL;
122 goto end;
123
124 case REG_STRING:
125 if (vstack_bx(stack)->type == REG_UNKNOWN)
126 break;
127 insn->op = FILTER_OP_NE_STRING;
128 break;
129 case REG_S64:
130 if (vstack_bx(stack)->type == REG_UNKNOWN)
131 break;
132 if (vstack_bx(stack)->type == REG_S64)
133 insn->op = FILTER_OP_NE_S64;
134 else
135 insn->op = FILTER_OP_NE_DOUBLE_S64;
136 break;
137 case REG_DOUBLE:
138 if (vstack_bx(stack)->type == REG_UNKNOWN)
139 break;
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;
144 break;
145 case REG_UNKNOWN:
146 break; /* Dynamic typing. */
147 }
148 /* Pop 2, push 1 */
149 if (vstack_pop(stack)) {
150 ret = -EINVAL;
151 goto end;
152 }
153 vstack_ax(stack)->type = REG_S64;
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
162 switch(vstack_ax(stack)->type) {
163 default:
164 ERR("unknown register type\n");
165 ret = -EINVAL;
166 goto end;
167
168 case REG_STRING:
169 if (vstack_bx(stack)->type == REG_UNKNOWN)
170 break;
171 insn->op = FILTER_OP_GT_STRING;
172 break;
173 case REG_S64:
174 if (vstack_bx(stack)->type == REG_UNKNOWN)
175 break;
176 if (vstack_bx(stack)->type == REG_S64)
177 insn->op = FILTER_OP_GT_S64;
178 else
179 insn->op = FILTER_OP_GT_DOUBLE_S64;
180 break;
181 case REG_DOUBLE:
182 if (vstack_bx(stack)->type == REG_UNKNOWN)
183 break;
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;
188 break;
189 case REG_UNKNOWN:
190 break; /* Dynamic typing. */
191 }
192 /* Pop 2, push 1 */
193 if (vstack_pop(stack)) {
194 ret = -EINVAL;
195 goto end;
196 }
197 vstack_ax(stack)->type = REG_S64;
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
206 switch(vstack_ax(stack)->type) {
207 default:
208 ERR("unknown register type\n");
209 ret = -EINVAL;
210 goto end;
211
212 case REG_STRING:
213 if (vstack_bx(stack)->type == REG_UNKNOWN)
214 break;
215 insn->op = FILTER_OP_LT_STRING;
216 break;
217 case REG_S64:
218 if (vstack_bx(stack)->type == REG_UNKNOWN)
219 break;
220 if (vstack_bx(stack)->type == REG_S64)
221 insn->op = FILTER_OP_LT_S64;
222 else
223 insn->op = FILTER_OP_LT_DOUBLE_S64;
224 break;
225 case REG_DOUBLE:
226 if (vstack_bx(stack)->type == REG_UNKNOWN)
227 break;
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;
232 break;
233 case REG_UNKNOWN:
234 break; /* Dynamic typing. */
235 }
236 /* Pop 2, push 1 */
237 if (vstack_pop(stack)) {
238 ret = -EINVAL;
239 goto end;
240 }
241 vstack_ax(stack)->type = REG_S64;
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
250 switch(vstack_ax(stack)->type) {
251 default:
252 ERR("unknown register type\n");
253 ret = -EINVAL;
254 goto end;
255
256 case REG_STRING:
257 if (vstack_bx(stack)->type == REG_UNKNOWN)
258 break;
259 insn->op = FILTER_OP_GE_STRING;
260 break;
261 case REG_S64:
262 if (vstack_bx(stack)->type == REG_UNKNOWN)
263 break;
264 if (vstack_bx(stack)->type == REG_S64)
265 insn->op = FILTER_OP_GE_S64;
266 else
267 insn->op = FILTER_OP_GE_DOUBLE_S64;
268 break;
269 case REG_DOUBLE:
270 if (vstack_bx(stack)->type == REG_UNKNOWN)
271 break;
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;
276 break;
277 case REG_UNKNOWN:
278 break; /* Dynamic typing. */
279 }
280 /* Pop 2, push 1 */
281 if (vstack_pop(stack)) {
282 ret = -EINVAL;
283 goto end;
284 }
285 vstack_ax(stack)->type = REG_S64;
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
293 switch(vstack_ax(stack)->type) {
294 default:
295 ERR("unknown register type\n");
296 ret = -EINVAL;
297 goto end;
298
299 case REG_STRING:
300 if (vstack_bx(stack)->type == REG_UNKNOWN)
301 break;
302 insn->op = FILTER_OP_LE_STRING;
303 break;
304 case REG_S64:
305 if (vstack_bx(stack)->type == REG_UNKNOWN)
306 break;
307 if (vstack_bx(stack)->type == REG_S64)
308 insn->op = FILTER_OP_LE_S64;
309 else
310 insn->op = FILTER_OP_LE_DOUBLE_S64;
311 break;
312 case REG_DOUBLE:
313 if (vstack_bx(stack)->type == REG_UNKNOWN)
314 break;
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;
319 break;
320 case REG_UNKNOWN:
321 break; /* Dynamic typing. */
322 }
323 vstack_ax(stack)->type = REG_S64;
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:
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:
358 {
359 /* Pop 2, push 1 */
360 if (vstack_pop(stack)) {
361 ret = -EINVAL;
362 goto end;
363 }
364 vstack_ax(stack)->type = REG_S64;
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
374 switch(vstack_ax(stack)->type) {
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;
386 case REG_UNKNOWN: /* Dynamic typing. */
387 break;
388 }
389 /* Pop 1, push 1 */
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
398 switch(vstack_ax(stack)->type) {
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;
410 case REG_UNKNOWN: /* Dynamic typing. */
411 break;
412 }
413 /* Pop 1, push 1 */
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
422 switch(vstack_ax(stack)->type) {
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;
434 case REG_UNKNOWN: /* Dynamic typing. */
435 break;
436 }
437 /* Pop 1, push 1 */
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 {
449 /* Pop 1, push 1 */
450 next_pc += sizeof(struct unary_op);
451 break;
452 }
453
454 /* logical */
455 case FILTER_OP_AND:
456 case FILTER_OP_OR:
457 {
458 /* Continue to next instruction */
459 /* Pop 1 when jump not taken */
460 if (vstack_pop(stack)) {
461 ret = -EINVAL;
462 goto end;
463 }
464 next_pc += sizeof(struct logical_op);
465 break;
466 }
467
468 /* load field ref */
469 case FILTER_OP_LOAD_FIELD_REF:
470 {
471 ERR("Unknown field ref type\n");
472 ret = -EINVAL;
473 goto end;
474 }
475 /* get context ref */
476 case FILTER_OP_GET_CONTEXT_REF:
477 {
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;
485 }
486 case FILTER_OP_LOAD_FIELD_REF_STRING:
487 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
488 case FILTER_OP_GET_CONTEXT_REF_STRING:
489 {
490 if (vstack_push(stack)) {
491 ret = -EINVAL;
492 goto end;
493 }
494 vstack_ax(stack)->type = REG_STRING;
495 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
496 break;
497 }
498 case FILTER_OP_LOAD_FIELD_REF_S64:
499 case FILTER_OP_GET_CONTEXT_REF_S64:
500 {
501 if (vstack_push(stack)) {
502 ret = -EINVAL;
503 goto end;
504 }
505 vstack_ax(stack)->type = REG_S64;
506 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
507 break;
508 }
509 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
510 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
511 {
512 if (vstack_push(stack)) {
513 ret = -EINVAL;
514 goto end;
515 }
516 vstack_ax(stack)->type = REG_DOUBLE;
517 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
518 break;
519 }
520
521 /* load from immediate operand */
522 case FILTER_OP_LOAD_STRING:
523 {
524 struct load_op *insn = (struct load_op *) pc;
525
526 if (vstack_push(stack)) {
527 ret = -EINVAL;
528 goto end;
529 }
530 vstack_ax(stack)->type = REG_STRING;
531 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
532 break;
533 }
534
535 case FILTER_OP_LOAD_S64:
536 {
537 if (vstack_push(stack)) {
538 ret = -EINVAL;
539 goto end;
540 }
541 vstack_ax(stack)->type = REG_S64;
542 next_pc += sizeof(struct load_op)
543 + sizeof(struct literal_numeric);
544 break;
545 }
546
547 case FILTER_OP_LOAD_DOUBLE:
548 {
549 if (vstack_push(stack)) {
550 ret = -EINVAL;
551 goto end;
552 }
553 vstack_ax(stack)->type = REG_DOUBLE;
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
564 switch (vstack_ax(stack)->type) {
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;
580 case REG_UNKNOWN:
581 break;
582 }
583 /* Pop 1, push 1 */
584 vstack_ax(stack)->type = REG_S64;
585 next_pc += sizeof(struct cast_op);
586 break;
587 }
588 case FILTER_OP_CAST_DOUBLE_TO_S64:
589 {
590 /* Pop 1, push 1 */
591 vstack_ax(stack)->type = REG_S64;
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
601 }
602 }
603 end:
604 return ret;
605 }
This page took 0.040884 seconds and 4 git commands to generate.