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