Filter code relicensing to MIT license
[lttng-modules.git] / lttng-filter-specialize.c
1 /*
2 * lttng-filter-specialize.c
3 *
4 * LTTng modules 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 #include <lttng-filter.h>
28
29 int 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:
80 insn->op = FILTER_OP_EQ_STRING;
81 break;
82 case REG_S64:
83 if (vstack_bx(stack)->type == REG_S64)
84 insn->op = FILTER_OP_EQ_S64;
85 else
86 insn->op = FILTER_OP_EQ_DOUBLE_S64;
87 break;
88 case REG_DOUBLE:
89 if (vstack_bx(stack)->type == REG_S64)
90 insn->op = FILTER_OP_EQ_S64_DOUBLE;
91 else
92 insn->op = FILTER_OP_EQ_DOUBLE;
93 break;
94 }
95 /* Pop 2, push 1 */
96 if (vstack_pop(stack)) {
97 ret = -EINVAL;
98 goto end;
99 }
100 vstack_ax(stack)->type = REG_S64;
101 next_pc += sizeof(struct binary_op);
102 break;
103 }
104
105 case FILTER_OP_NE:
106 {
107 struct binary_op *insn = (struct binary_op *) pc;
108
109 switch(vstack_ax(stack)->type) {
110 default:
111 printk(KERN_WARNING "unknown register type\n");
112 ret = -EINVAL;
113 goto end;
114
115 case REG_STRING:
116 insn->op = FILTER_OP_NE_STRING;
117 break;
118 case REG_S64:
119 if (vstack_bx(stack)->type == REG_S64)
120 insn->op = FILTER_OP_NE_S64;
121 else
122 insn->op = FILTER_OP_NE_DOUBLE_S64;
123 break;
124 case REG_DOUBLE:
125 if (vstack_bx(stack)->type == REG_S64)
126 insn->op = FILTER_OP_NE_S64_DOUBLE;
127 else
128 insn->op = FILTER_OP_NE_DOUBLE;
129 break;
130 }
131 /* Pop 2, push 1 */
132 if (vstack_pop(stack)) {
133 ret = -EINVAL;
134 goto end;
135 }
136 vstack_ax(stack)->type = REG_S64;
137 next_pc += sizeof(struct binary_op);
138 break;
139 }
140
141 case FILTER_OP_GT:
142 {
143 struct binary_op *insn = (struct binary_op *) pc;
144
145 switch(vstack_ax(stack)->type) {
146 default:
147 printk(KERN_WARNING "unknown register type\n");
148 ret = -EINVAL;
149 goto end;
150
151 case REG_STRING:
152 insn->op = FILTER_OP_GT_STRING;
153 break;
154 case REG_S64:
155 if (vstack_bx(stack)->type == REG_S64)
156 insn->op = FILTER_OP_GT_S64;
157 else
158 insn->op = FILTER_OP_GT_DOUBLE_S64;
159 break;
160 case REG_DOUBLE:
161 if (vstack_bx(stack)->type == REG_S64)
162 insn->op = FILTER_OP_GT_S64_DOUBLE;
163 else
164 insn->op = FILTER_OP_GT_DOUBLE;
165 break;
166 }
167 /* Pop 2, push 1 */
168 if (vstack_pop(stack)) {
169 ret = -EINVAL;
170 goto end;
171 }
172 vstack_ax(stack)->type = REG_S64;
173 next_pc += sizeof(struct binary_op);
174 break;
175 }
176
177 case FILTER_OP_LT:
178 {
179 struct binary_op *insn = (struct binary_op *) pc;
180
181 switch(vstack_ax(stack)->type) {
182 default:
183 printk(KERN_WARNING "unknown register type\n");
184 ret = -EINVAL;
185 goto end;
186
187 case REG_STRING:
188 insn->op = FILTER_OP_LT_STRING;
189 break;
190 case REG_S64:
191 if (vstack_bx(stack)->type == REG_S64)
192 insn->op = FILTER_OP_LT_S64;
193 else
194 insn->op = FILTER_OP_LT_DOUBLE_S64;
195 break;
196 case REG_DOUBLE:
197 if (vstack_bx(stack)->type == REG_S64)
198 insn->op = FILTER_OP_LT_S64_DOUBLE;
199 else
200 insn->op = FILTER_OP_LT_DOUBLE;
201 break;
202 }
203 /* Pop 2, push 1 */
204 if (vstack_pop(stack)) {
205 ret = -EINVAL;
206 goto end;
207 }
208 vstack_ax(stack)->type = REG_S64;
209 next_pc += sizeof(struct binary_op);
210 break;
211 }
212
213 case FILTER_OP_GE:
214 {
215 struct binary_op *insn = (struct binary_op *) pc;
216
217 switch(vstack_ax(stack)->type) {
218 default:
219 printk(KERN_WARNING "unknown register type\n");
220 ret = -EINVAL;
221 goto end;
222
223 case REG_STRING:
224 insn->op = FILTER_OP_GE_STRING;
225 break;
226 case REG_S64:
227 if (vstack_bx(stack)->type == REG_S64)
228 insn->op = FILTER_OP_GE_S64;
229 else
230 insn->op = FILTER_OP_GE_DOUBLE_S64;
231 break;
232 case REG_DOUBLE:
233 if (vstack_bx(stack)->type == REG_S64)
234 insn->op = FILTER_OP_GE_S64_DOUBLE;
235 else
236 insn->op = FILTER_OP_GE_DOUBLE;
237 break;
238 }
239 /* Pop 2, push 1 */
240 if (vstack_pop(stack)) {
241 ret = -EINVAL;
242 goto end;
243 }
244 vstack_ax(stack)->type = REG_S64;
245 next_pc += sizeof(struct binary_op);
246 break;
247 }
248 case FILTER_OP_LE:
249 {
250 struct binary_op *insn = (struct binary_op *) pc;
251
252 switch(vstack_ax(stack)->type) {
253 default:
254 printk(KERN_WARNING "unknown register type\n");
255 ret = -EINVAL;
256 goto end;
257
258 case REG_STRING:
259 insn->op = FILTER_OP_LE_STRING;
260 break;
261 case REG_S64:
262 if (vstack_bx(stack)->type == REG_S64)
263 insn->op = FILTER_OP_LE_S64;
264 else
265 insn->op = FILTER_OP_LE_DOUBLE_S64;
266 break;
267 case REG_DOUBLE:
268 if (vstack_bx(stack)->type == REG_S64)
269 insn->op = FILTER_OP_LE_S64_DOUBLE;
270 else
271 insn->op = FILTER_OP_LE_DOUBLE;
272 break;
273 }
274 vstack_ax(stack)->type = REG_S64;
275 next_pc += sizeof(struct binary_op);
276 break;
277 }
278
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:
309 {
310 /* Pop 2, push 1 */
311 if (vstack_pop(stack)) {
312 ret = -EINVAL;
313 goto end;
314 }
315 vstack_ax(stack)->type = REG_S64;
316 next_pc += sizeof(struct binary_op);
317 break;
318 }
319
320 /* unary */
321 case FILTER_OP_UNARY_PLUS:
322 {
323 struct unary_op *insn = (struct unary_op *) pc;
324
325 switch(vstack_ax(stack)->type) {
326 default:
327 printk(KERN_WARNING "unknown register type\n");
328 ret = -EINVAL;
329 goto end;
330
331 case REG_S64:
332 insn->op = FILTER_OP_UNARY_PLUS_S64;
333 break;
334 case REG_DOUBLE:
335 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
336 break;
337 }
338 /* Pop 1, push 1 */
339 next_pc += sizeof(struct unary_op);
340 break;
341 }
342
343 case FILTER_OP_UNARY_MINUS:
344 {
345 struct unary_op *insn = (struct unary_op *) pc;
346
347 switch(vstack_ax(stack)->type) {
348 default:
349 printk(KERN_WARNING "unknown register type\n");
350 ret = -EINVAL;
351 goto end;
352
353 case REG_S64:
354 insn->op = FILTER_OP_UNARY_MINUS_S64;
355 break;
356 case REG_DOUBLE:
357 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
358 break;
359 }
360 /* Pop 1, push 1 */
361 next_pc += sizeof(struct unary_op);
362 break;
363 }
364
365 case FILTER_OP_UNARY_NOT:
366 {
367 struct unary_op *insn = (struct unary_op *) pc;
368
369 switch(vstack_ax(stack)->type) {
370 default:
371 printk(KERN_WARNING "unknown register type\n");
372 ret = -EINVAL;
373 goto end;
374
375 case REG_S64:
376 insn->op = FILTER_OP_UNARY_NOT_S64;
377 break;
378 case REG_DOUBLE:
379 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
380 break;
381 }
382 /* Pop 1, push 1 */
383 next_pc += sizeof(struct unary_op);
384 break;
385 }
386
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:
393 {
394 /* Pop 1, push 1 */
395 next_pc += sizeof(struct unary_op);
396 break;
397 }
398
399 /* logical */
400 case FILTER_OP_AND:
401 case FILTER_OP_OR:
402 {
403 /* Continue to next instruction */
404 /* Pop 1 when jump not taken */
405 if (vstack_pop(stack)) {
406 ret = -EINVAL;
407 goto end;
408 }
409 next_pc += sizeof(struct logical_op);
410 break;
411 }
412
413 /* load field ref */
414 case FILTER_OP_LOAD_FIELD_REF:
415 {
416 printk(KERN_WARNING "Unknown field ref type\n");
417 ret = -EINVAL;
418 goto end;
419 }
420 /* get context ref */
421 case FILTER_OP_GET_CONTEXT_REF:
422 {
423 printk(KERN_WARNING "Unknown get context ref type\n");
424 ret = -EINVAL;
425 goto end;
426 }
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:
432 {
433 if (vstack_push(stack)) {
434 ret = -EINVAL;
435 goto end;
436 }
437 vstack_ax(stack)->type = REG_STRING;
438 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
439 break;
440 }
441 case FILTER_OP_LOAD_FIELD_REF_S64:
442 case FILTER_OP_GET_CONTEXT_REF_S64:
443 {
444 if (vstack_push(stack)) {
445 ret = -EINVAL;
446 goto end;
447 }
448 vstack_ax(stack)->type = REG_S64;
449 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
450 break;
451 }
452 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
453 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
454 {
455 if (vstack_push(stack)) {
456 ret = -EINVAL;
457 goto end;
458 }
459 vstack_ax(stack)->type = REG_DOUBLE;
460 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
461 break;
462 }
463
464 /* load from immediate operand */
465 case FILTER_OP_LOAD_STRING:
466 {
467 struct load_op *insn = (struct load_op *) pc;
468
469 if (vstack_push(stack)) {
470 ret = -EINVAL;
471 goto end;
472 }
473 vstack_ax(stack)->type = REG_STRING;
474 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
475 break;
476 }
477
478 case FILTER_OP_LOAD_S64:
479 {
480 if (vstack_push(stack)) {
481 ret = -EINVAL;
482 goto end;
483 }
484 vstack_ax(stack)->type = REG_S64;
485 next_pc += sizeof(struct load_op)
486 + sizeof(struct literal_numeric);
487 break;
488 }
489
490 case FILTER_OP_LOAD_DOUBLE:
491 {
492 if (vstack_push(stack)) {
493 ret = -EINVAL;
494 goto end;
495 }
496 vstack_ax(stack)->type = REG_DOUBLE;
497 next_pc += sizeof(struct load_op)
498 + sizeof(struct literal_double);
499 break;
500 }
501
502 /* cast */
503 case FILTER_OP_CAST_TO_S64:
504 {
505 struct cast_op *insn = (struct cast_op *) pc;
506
507 switch (vstack_ax(stack)->type) {
508 default:
509 printk(KERN_WARNING "unknown register type\n");
510 ret = -EINVAL;
511 goto end;
512
513 case REG_STRING:
514 printk(KERN_WARNING "Cast op can only be applied to numeric or floating point registers\n");
515 ret = -EINVAL;
516 goto end;
517 case REG_S64:
518 insn->op = FILTER_OP_CAST_NOP;
519 break;
520 case REG_DOUBLE:
521 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
522 break;
523 }
524 /* Pop 1, push 1 */
525 vstack_ax(stack)->type = REG_S64;
526 next_pc += sizeof(struct cast_op);
527 break;
528 }
529 case FILTER_OP_CAST_DOUBLE_TO_S64:
530 {
531 /* Pop 1, push 1 */
532 vstack_ax(stack)->type = REG_S64;
533 next_pc += sizeof(struct cast_op);
534 break;
535 }
536 case FILTER_OP_CAST_NOP:
537 {
538 next_pc += sizeof(struct cast_op);
539 break;
540 }
541
542 }
543 }
544 end:
545 return ret;
546 }
This page took 0.040358 seconds and 5 git commands to generate.