Implement filtering infrastructure
[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-2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "lttng-filter.h"
24
25 int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
26 {
27 void *pc, *next_pc, *start_pc;
28 int ret = -EINVAL;
29 struct vstack _stack;
30 struct vstack *stack = &_stack;
31
32 vstack_init(stack);
33
34 start_pc = &bytecode->data[0];
35 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
36 pc = next_pc) {
37 switch (*(filter_opcode_t *) pc) {
38 case FILTER_OP_UNKNOWN:
39 default:
40 printk(KERN_WARNING "unknown bytecode op %u\n",
41 (unsigned int) *(filter_opcode_t *) pc);
42 ret = -EINVAL;
43 goto end;
44
45 case FILTER_OP_RETURN:
46 ret = 0;
47 goto end;
48
49 /* binary */
50 case FILTER_OP_MUL:
51 case FILTER_OP_DIV:
52 case FILTER_OP_MOD:
53 case FILTER_OP_PLUS:
54 case FILTER_OP_MINUS:
55 case FILTER_OP_RSHIFT:
56 case FILTER_OP_LSHIFT:
57 case FILTER_OP_BIN_AND:
58 case FILTER_OP_BIN_OR:
59 case FILTER_OP_BIN_XOR:
60 printk(KERN_WARNING "unsupported bytecode op %u\n",
61 (unsigned int) *(filter_opcode_t *) pc);
62 ret = -EINVAL;
63 goto end;
64
65 case FILTER_OP_EQ:
66 {
67 struct binary_op *insn = (struct binary_op *) pc;
68
69 switch(vstack_ax(stack)->type) {
70 default:
71 printk(KERN_WARNING "unknown register type\n");
72 ret = -EINVAL;
73 goto end;
74
75 case REG_STRING:
76 insn->op = FILTER_OP_EQ_STRING;
77 break;
78 case REG_S64:
79 if (vstack_bx(stack)->type == REG_S64)
80 insn->op = FILTER_OP_EQ_S64;
81 else
82 insn->op = FILTER_OP_EQ_DOUBLE_S64;
83 break;
84 case REG_DOUBLE:
85 if (vstack_bx(stack)->type == REG_S64)
86 insn->op = FILTER_OP_EQ_S64_DOUBLE;
87 else
88 insn->op = FILTER_OP_EQ_DOUBLE;
89 break;
90 }
91 /* Pop 2, push 1 */
92 if (vstack_pop(stack)) {
93 ret = -EINVAL;
94 goto end;
95 }
96 vstack_ax(stack)->type = REG_S64;
97 next_pc += sizeof(struct binary_op);
98 break;
99 }
100
101 case FILTER_OP_NE:
102 {
103 struct binary_op *insn = (struct binary_op *) pc;
104
105 switch(vstack_ax(stack)->type) {
106 default:
107 printk(KERN_WARNING "unknown register type\n");
108 ret = -EINVAL;
109 goto end;
110
111 case REG_STRING:
112 insn->op = FILTER_OP_NE_STRING;
113 break;
114 case REG_S64:
115 if (vstack_bx(stack)->type == REG_S64)
116 insn->op = FILTER_OP_NE_S64;
117 else
118 insn->op = FILTER_OP_NE_DOUBLE_S64;
119 break;
120 case REG_DOUBLE:
121 if (vstack_bx(stack)->type == REG_S64)
122 insn->op = FILTER_OP_NE_S64_DOUBLE;
123 else
124 insn->op = FILTER_OP_NE_DOUBLE;
125 break;
126 }
127 /* Pop 2, push 1 */
128 if (vstack_pop(stack)) {
129 ret = -EINVAL;
130 goto end;
131 }
132 vstack_ax(stack)->type = REG_S64;
133 next_pc += sizeof(struct binary_op);
134 break;
135 }
136
137 case FILTER_OP_GT:
138 {
139 struct binary_op *insn = (struct binary_op *) pc;
140
141 switch(vstack_ax(stack)->type) {
142 default:
143 printk(KERN_WARNING "unknown register type\n");
144 ret = -EINVAL;
145 goto end;
146
147 case REG_STRING:
148 insn->op = FILTER_OP_GT_STRING;
149 break;
150 case REG_S64:
151 if (vstack_bx(stack)->type == REG_S64)
152 insn->op = FILTER_OP_GT_S64;
153 else
154 insn->op = FILTER_OP_GT_DOUBLE_S64;
155 break;
156 case REG_DOUBLE:
157 if (vstack_bx(stack)->type == REG_S64)
158 insn->op = FILTER_OP_GT_S64_DOUBLE;
159 else
160 insn->op = FILTER_OP_GT_DOUBLE;
161 break;
162 }
163 /* Pop 2, push 1 */
164 if (vstack_pop(stack)) {
165 ret = -EINVAL;
166 goto end;
167 }
168 vstack_ax(stack)->type = REG_S64;
169 next_pc += sizeof(struct binary_op);
170 break;
171 }
172
173 case FILTER_OP_LT:
174 {
175 struct binary_op *insn = (struct binary_op *) pc;
176
177 switch(vstack_ax(stack)->type) {
178 default:
179 printk(KERN_WARNING "unknown register type\n");
180 ret = -EINVAL;
181 goto end;
182
183 case REG_STRING:
184 insn->op = FILTER_OP_LT_STRING;
185 break;
186 case REG_S64:
187 if (vstack_bx(stack)->type == REG_S64)
188 insn->op = FILTER_OP_LT_S64;
189 else
190 insn->op = FILTER_OP_LT_DOUBLE_S64;
191 break;
192 case REG_DOUBLE:
193 if (vstack_bx(stack)->type == REG_S64)
194 insn->op = FILTER_OP_LT_S64_DOUBLE;
195 else
196 insn->op = FILTER_OP_LT_DOUBLE;
197 break;
198 }
199 /* Pop 2, push 1 */
200 if (vstack_pop(stack)) {
201 ret = -EINVAL;
202 goto end;
203 }
204 vstack_ax(stack)->type = REG_S64;
205 next_pc += sizeof(struct binary_op);
206 break;
207 }
208
209 case FILTER_OP_GE:
210 {
211 struct binary_op *insn = (struct binary_op *) pc;
212
213 switch(vstack_ax(stack)->type) {
214 default:
215 printk(KERN_WARNING "unknown register type\n");
216 ret = -EINVAL;
217 goto end;
218
219 case REG_STRING:
220 insn->op = FILTER_OP_GE_STRING;
221 break;
222 case REG_S64:
223 if (vstack_bx(stack)->type == REG_S64)
224 insn->op = FILTER_OP_GE_S64;
225 else
226 insn->op = FILTER_OP_GE_DOUBLE_S64;
227 break;
228 case REG_DOUBLE:
229 if (vstack_bx(stack)->type == REG_S64)
230 insn->op = FILTER_OP_GE_S64_DOUBLE;
231 else
232 insn->op = FILTER_OP_GE_DOUBLE;
233 break;
234 }
235 /* Pop 2, push 1 */
236 if (vstack_pop(stack)) {
237 ret = -EINVAL;
238 goto end;
239 }
240 vstack_ax(stack)->type = REG_S64;
241 next_pc += sizeof(struct binary_op);
242 break;
243 }
244 case FILTER_OP_LE:
245 {
246 struct binary_op *insn = (struct binary_op *) pc;
247
248 switch(vstack_ax(stack)->type) {
249 default:
250 printk(KERN_WARNING "unknown register type\n");
251 ret = -EINVAL;
252 goto end;
253
254 case REG_STRING:
255 insn->op = FILTER_OP_LE_STRING;
256 break;
257 case REG_S64:
258 if (vstack_bx(stack)->type == REG_S64)
259 insn->op = FILTER_OP_LE_S64;
260 else
261 insn->op = FILTER_OP_LE_DOUBLE_S64;
262 break;
263 case REG_DOUBLE:
264 if (vstack_bx(stack)->type == REG_S64)
265 insn->op = FILTER_OP_LE_S64_DOUBLE;
266 else
267 insn->op = FILTER_OP_LE_DOUBLE;
268 break;
269 }
270 vstack_ax(stack)->type = REG_S64;
271 next_pc += sizeof(struct binary_op);
272 break;
273 }
274
275 case FILTER_OP_EQ_STRING:
276 case FILTER_OP_NE_STRING:
277 case FILTER_OP_GT_STRING:
278 case FILTER_OP_LT_STRING:
279 case FILTER_OP_GE_STRING:
280 case FILTER_OP_LE_STRING:
281 case FILTER_OP_EQ_S64:
282 case FILTER_OP_NE_S64:
283 case FILTER_OP_GT_S64:
284 case FILTER_OP_LT_S64:
285 case FILTER_OP_GE_S64:
286 case FILTER_OP_LE_S64:
287 case FILTER_OP_EQ_DOUBLE:
288 case FILTER_OP_NE_DOUBLE:
289 case FILTER_OP_GT_DOUBLE:
290 case FILTER_OP_LT_DOUBLE:
291 case FILTER_OP_GE_DOUBLE:
292 case FILTER_OP_LE_DOUBLE:
293 case FILTER_OP_EQ_DOUBLE_S64:
294 case FILTER_OP_NE_DOUBLE_S64:
295 case FILTER_OP_GT_DOUBLE_S64:
296 case FILTER_OP_LT_DOUBLE_S64:
297 case FILTER_OP_GE_DOUBLE_S64:
298 case FILTER_OP_LE_DOUBLE_S64:
299 case FILTER_OP_EQ_S64_DOUBLE:
300 case FILTER_OP_NE_S64_DOUBLE:
301 case FILTER_OP_GT_S64_DOUBLE:
302 case FILTER_OP_LT_S64_DOUBLE:
303 case FILTER_OP_GE_S64_DOUBLE:
304 case FILTER_OP_LE_S64_DOUBLE:
305 {
306 /* Pop 2, push 1 */
307 if (vstack_pop(stack)) {
308 ret = -EINVAL;
309 goto end;
310 }
311 vstack_ax(stack)->type = REG_S64;
312 next_pc += sizeof(struct binary_op);
313 break;
314 }
315
316 /* unary */
317 case FILTER_OP_UNARY_PLUS:
318 {
319 struct unary_op *insn = (struct unary_op *) pc;
320
321 switch(vstack_ax(stack)->type) {
322 default:
323 printk(KERN_WARNING "unknown register type\n");
324 ret = -EINVAL;
325 goto end;
326
327 case REG_S64:
328 insn->op = FILTER_OP_UNARY_PLUS_S64;
329 break;
330 case REG_DOUBLE:
331 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
332 break;
333 }
334 /* Pop 1, push 1 */
335 next_pc += sizeof(struct unary_op);
336 break;
337 }
338
339 case FILTER_OP_UNARY_MINUS:
340 {
341 struct unary_op *insn = (struct unary_op *) pc;
342
343 switch(vstack_ax(stack)->type) {
344 default:
345 printk(KERN_WARNING "unknown register type\n");
346 ret = -EINVAL;
347 goto end;
348
349 case REG_S64:
350 insn->op = FILTER_OP_UNARY_MINUS_S64;
351 break;
352 case REG_DOUBLE:
353 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
354 break;
355 }
356 /* Pop 1, push 1 */
357 next_pc += sizeof(struct unary_op);
358 break;
359 }
360
361 case FILTER_OP_UNARY_NOT:
362 {
363 struct unary_op *insn = (struct unary_op *) pc;
364
365 switch(vstack_ax(stack)->type) {
366 default:
367 printk(KERN_WARNING "unknown register type\n");
368 ret = -EINVAL;
369 goto end;
370
371 case REG_S64:
372 insn->op = FILTER_OP_UNARY_NOT_S64;
373 break;
374 case REG_DOUBLE:
375 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
376 break;
377 }
378 /* Pop 1, push 1 */
379 next_pc += sizeof(struct unary_op);
380 break;
381 }
382
383 case FILTER_OP_UNARY_PLUS_S64:
384 case FILTER_OP_UNARY_MINUS_S64:
385 case FILTER_OP_UNARY_NOT_S64:
386 case FILTER_OP_UNARY_PLUS_DOUBLE:
387 case FILTER_OP_UNARY_MINUS_DOUBLE:
388 case FILTER_OP_UNARY_NOT_DOUBLE:
389 {
390 /* Pop 1, push 1 */
391 next_pc += sizeof(struct unary_op);
392 break;
393 }
394
395 /* logical */
396 case FILTER_OP_AND:
397 case FILTER_OP_OR:
398 {
399 /* Continue to next instruction */
400 /* Pop 1 when jump not taken */
401 if (vstack_pop(stack)) {
402 ret = -EINVAL;
403 goto end;
404 }
405 next_pc += sizeof(struct logical_op);
406 break;
407 }
408
409 /* load field ref */
410 case FILTER_OP_LOAD_FIELD_REF:
411 {
412 printk(KERN_WARNING "Unknown field ref type\n");
413 ret = -EINVAL;
414 goto end;
415 }
416 /* get context ref */
417 case FILTER_OP_GET_CONTEXT_REF:
418 {
419 printk(KERN_WARNING "Unknown get context ref type\n");
420 ret = -EINVAL;
421 goto end;
422 }
423 case FILTER_OP_LOAD_FIELD_REF_STRING:
424 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
425 case FILTER_OP_GET_CONTEXT_REF_STRING:
426 {
427 if (vstack_push(stack)) {
428 ret = -EINVAL;
429 goto end;
430 }
431 vstack_ax(stack)->type = REG_STRING;
432 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
433 break;
434 }
435 case FILTER_OP_LOAD_FIELD_REF_S64:
436 case FILTER_OP_GET_CONTEXT_REF_S64:
437 {
438 if (vstack_push(stack)) {
439 ret = -EINVAL;
440 goto end;
441 }
442 vstack_ax(stack)->type = REG_S64;
443 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
444 break;
445 }
446 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
447 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
448 {
449 if (vstack_push(stack)) {
450 ret = -EINVAL;
451 goto end;
452 }
453 vstack_ax(stack)->type = REG_DOUBLE;
454 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
455 break;
456 }
457
458 /* load from immediate operand */
459 case FILTER_OP_LOAD_STRING:
460 {
461 struct load_op *insn = (struct load_op *) pc;
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) + strlen(insn->data) + 1;
469 break;
470 }
471
472 case FILTER_OP_LOAD_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)
480 + sizeof(struct literal_numeric);
481 break;
482 }
483
484 case FILTER_OP_LOAD_DOUBLE:
485 {
486 if (vstack_push(stack)) {
487 ret = -EINVAL;
488 goto end;
489 }
490 vstack_ax(stack)->type = REG_DOUBLE;
491 next_pc += sizeof(struct load_op)
492 + sizeof(struct literal_double);
493 break;
494 }
495
496 /* cast */
497 case FILTER_OP_CAST_TO_S64:
498 {
499 struct cast_op *insn = (struct cast_op *) pc;
500
501 switch (vstack_ax(stack)->type) {
502 default:
503 printk(KERN_WARNING "unknown register type\n");
504 ret = -EINVAL;
505 goto end;
506
507 case REG_STRING:
508 printk(KERN_WARNING "Cast op can only be applied to numeric or floating point registers\n");
509 ret = -EINVAL;
510 goto end;
511 case REG_S64:
512 insn->op = FILTER_OP_CAST_NOP;
513 break;
514 case REG_DOUBLE:
515 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
516 break;
517 }
518 /* Pop 1, push 1 */
519 vstack_ax(stack)->type = REG_S64;
520 next_pc += sizeof(struct cast_op);
521 break;
522 }
523 case FILTER_OP_CAST_DOUBLE_TO_S64:
524 {
525 /* Pop 1, push 1 */
526 vstack_ax(stack)->type = REG_S64;
527 next_pc += sizeof(struct cast_op);
528 break;
529 }
530 case FILTER_OP_CAST_NOP:
531 {
532 next_pc += sizeof(struct cast_op);
533 break;
534 }
535
536 }
537 }
538 end:
539 return ret;
540 }
This page took 0.039698 seconds and 5 git commands to generate.