Fix filter: fix stack leak on taken branch
[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 *
6 * Copyright (C) 2010-2012 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
25int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
26{
27 void *pc, *next_pc, *start_pc;
28 int ret = -EINVAL;
0305960f
MD
29 struct vstack _stack;
30 struct vstack *stack = &_stack;
97b58163 31
0305960f 32 vstack_init(stack);
97b58163
MD
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 ERR("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 ERR("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
0305960f 69 switch(vstack_ax(stack)->type) {
97b58163
MD
70 default:
71 ERR("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:
0305960f 79 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
80 insn->op = FILTER_OP_EQ_S64;
81 else
82 insn->op = FILTER_OP_EQ_DOUBLE;
83 break;
84 case REG_DOUBLE:
85 insn->op = FILTER_OP_EQ_DOUBLE;
86 break;
87 }
0305960f
MD
88 /* Pop 2, push 1 */
89 if (vstack_pop(stack)) {
90 ret = -EINVAL;
91 goto end;
92 }
93 vstack_ax(stack)->type = REG_S64;
97b58163
MD
94 next_pc += sizeof(struct binary_op);
95 break;
96 }
97
98 case FILTER_OP_NE:
99 {
100 struct binary_op *insn = (struct binary_op *) pc;
101
0305960f 102 switch(vstack_ax(stack)->type) {
97b58163
MD
103 default:
104 ERR("unknown register type\n");
105 ret = -EINVAL;
106 goto end;
107
108 case REG_STRING:
109 insn->op = FILTER_OP_NE_STRING;
110 break;
111 case REG_S64:
0305960f 112 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
113 insn->op = FILTER_OP_NE_S64;
114 else
115 insn->op = FILTER_OP_NE_DOUBLE;
116 break;
117 case REG_DOUBLE:
118 insn->op = FILTER_OP_NE_DOUBLE;
119 break;
120 }
0305960f
MD
121 /* Pop 2, push 1 */
122 if (vstack_pop(stack)) {
123 ret = -EINVAL;
124 goto end;
125 }
126 vstack_ax(stack)->type = REG_S64;
97b58163
MD
127 next_pc += sizeof(struct binary_op);
128 break;
129 }
130
131 case FILTER_OP_GT:
132 {
133 struct binary_op *insn = (struct binary_op *) pc;
134
0305960f 135 switch(vstack_ax(stack)->type) {
97b58163
MD
136 default:
137 ERR("unknown register type\n");
138 ret = -EINVAL;
139 goto end;
140
141 case REG_STRING:
142 insn->op = FILTER_OP_GT_STRING;
143 break;
144 case REG_S64:
0305960f 145 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
146 insn->op = FILTER_OP_GT_S64;
147 else
148 insn->op = FILTER_OP_GT_DOUBLE;
149 break;
150 case REG_DOUBLE:
151 insn->op = FILTER_OP_GT_DOUBLE;
152 break;
153 }
0305960f
MD
154 /* Pop 2, push 1 */
155 if (vstack_pop(stack)) {
156 ret = -EINVAL;
157 goto end;
158 }
159 vstack_ax(stack)->type = REG_S64;
97b58163
MD
160 next_pc += sizeof(struct binary_op);
161 break;
162 }
163
164 case FILTER_OP_LT:
165 {
166 struct binary_op *insn = (struct binary_op *) pc;
167
0305960f 168 switch(vstack_ax(stack)->type) {
97b58163
MD
169 default:
170 ERR("unknown register type\n");
171 ret = -EINVAL;
172 goto end;
173
174 case REG_STRING:
175 insn->op = FILTER_OP_LT_STRING;
176 break;
177 case REG_S64:
0305960f 178 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
179 insn->op = FILTER_OP_LT_S64;
180 else
181 insn->op = FILTER_OP_LT_DOUBLE;
182 break;
183 case REG_DOUBLE:
184 insn->op = FILTER_OP_LT_DOUBLE;
185 break;
186 }
0305960f
MD
187 /* Pop 2, push 1 */
188 if (vstack_pop(stack)) {
189 ret = -EINVAL;
190 goto end;
191 }
192 vstack_ax(stack)->type = REG_S64;
97b58163
MD
193 next_pc += sizeof(struct binary_op);
194 break;
195 }
196
197 case FILTER_OP_GE:
198 {
199 struct binary_op *insn = (struct binary_op *) pc;
200
0305960f 201 switch(vstack_ax(stack)->type) {
97b58163
MD
202 default:
203 ERR("unknown register type\n");
204 ret = -EINVAL;
205 goto end;
206
207 case REG_STRING:
208 insn->op = FILTER_OP_GE_STRING;
209 break;
210 case REG_S64:
0305960f 211 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
212 insn->op = FILTER_OP_GE_S64;
213 else
214 insn->op = FILTER_OP_GE_DOUBLE;
215 break;
216 case REG_DOUBLE:
217 insn->op = FILTER_OP_GE_DOUBLE;
218 break;
219 }
0305960f
MD
220 /* Pop 2, push 1 */
221 if (vstack_pop(stack)) {
222 ret = -EINVAL;
223 goto end;
224 }
225 vstack_ax(stack)->type = REG_S64;
97b58163
MD
226 next_pc += sizeof(struct binary_op);
227 break;
228 }
229 case FILTER_OP_LE:
230 {
231 struct binary_op *insn = (struct binary_op *) pc;
232
0305960f 233 switch(vstack_ax(stack)->type) {
97b58163
MD
234 default:
235 ERR("unknown register type\n");
236 ret = -EINVAL;
237 goto end;
238
239 case REG_STRING:
240 insn->op = FILTER_OP_LE_STRING;
241 break;
242 case REG_S64:
0305960f 243 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
244 insn->op = FILTER_OP_LE_S64;
245 else
246 insn->op = FILTER_OP_LE_DOUBLE;
247 break;
248 case REG_DOUBLE:
249 insn->op = FILTER_OP_LE_DOUBLE;
250 break;
251 }
0305960f 252 vstack_ax(stack)->type = REG_S64;
97b58163
MD
253 next_pc += sizeof(struct binary_op);
254 break;
255 }
256
257 case FILTER_OP_EQ_STRING:
258 case FILTER_OP_NE_STRING:
259 case FILTER_OP_GT_STRING:
260 case FILTER_OP_LT_STRING:
261 case FILTER_OP_GE_STRING:
262 case FILTER_OP_LE_STRING:
263 case FILTER_OP_EQ_S64:
264 case FILTER_OP_NE_S64:
265 case FILTER_OP_GT_S64:
266 case FILTER_OP_LT_S64:
267 case FILTER_OP_GE_S64:
268 case FILTER_OP_LE_S64:
269 case FILTER_OP_EQ_DOUBLE:
270 case FILTER_OP_NE_DOUBLE:
271 case FILTER_OP_GT_DOUBLE:
272 case FILTER_OP_LT_DOUBLE:
273 case FILTER_OP_GE_DOUBLE:
274 case FILTER_OP_LE_DOUBLE:
275 {
0305960f
MD
276 /* Pop 2, push 1 */
277 if (vstack_pop(stack)) {
278 ret = -EINVAL;
279 goto end;
280 }
281 vstack_ax(stack)->type = REG_S64;
97b58163
MD
282 next_pc += sizeof(struct binary_op);
283 break;
284 }
285
286 /* unary */
287 case FILTER_OP_UNARY_PLUS:
288 {
289 struct unary_op *insn = (struct unary_op *) pc;
290
0305960f 291 switch(vstack_ax(stack)->type) {
97b58163
MD
292 default:
293 ERR("unknown register type\n");
294 ret = -EINVAL;
295 goto end;
296
297 case REG_S64:
298 insn->op = FILTER_OP_UNARY_PLUS_S64;
299 break;
300 case REG_DOUBLE:
301 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
302 break;
303 }
0305960f 304 /* Pop 1, push 1 */
97b58163
MD
305 next_pc += sizeof(struct unary_op);
306 break;
307 }
308
309 case FILTER_OP_UNARY_MINUS:
310 {
311 struct unary_op *insn = (struct unary_op *) pc;
312
0305960f 313 switch(vstack_ax(stack)->type) {
97b58163
MD
314 default:
315 ERR("unknown register type\n");
316 ret = -EINVAL;
317 goto end;
318
319 case REG_S64:
320 insn->op = FILTER_OP_UNARY_MINUS_S64;
321 break;
322 case REG_DOUBLE:
323 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
324 break;
325 }
0305960f 326 /* Pop 1, push 1 */
97b58163
MD
327 next_pc += sizeof(struct unary_op);
328 break;
329 }
330
331 case FILTER_OP_UNARY_NOT:
332 {
333 struct unary_op *insn = (struct unary_op *) pc;
334
0305960f 335 switch(vstack_ax(stack)->type) {
97b58163
MD
336 default:
337 ERR("unknown register type\n");
338 ret = -EINVAL;
339 goto end;
340
341 case REG_S64:
342 insn->op = FILTER_OP_UNARY_NOT_S64;
343 break;
344 case REG_DOUBLE:
345 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
346 break;
347 }
0305960f 348 /* Pop 1, push 1 */
97b58163
MD
349 next_pc += sizeof(struct unary_op);
350 break;
351 }
352
353 case FILTER_OP_UNARY_PLUS_S64:
354 case FILTER_OP_UNARY_MINUS_S64:
355 case FILTER_OP_UNARY_NOT_S64:
356 case FILTER_OP_UNARY_PLUS_DOUBLE:
357 case FILTER_OP_UNARY_MINUS_DOUBLE:
358 case FILTER_OP_UNARY_NOT_DOUBLE:
359 {
0305960f 360 /* Pop 1, push 1 */
97b58163
MD
361 next_pc += sizeof(struct unary_op);
362 break;
363 }
364
365 /* logical */
366 case FILTER_OP_AND:
367 case FILTER_OP_OR:
368 {
369 next_pc += sizeof(struct logical_op);
370 break;
371 }
372
373 /* load */
374 case FILTER_OP_LOAD_FIELD_REF:
375 {
376 ERR("Unknown field ref type\n");
377 ret = -EINVAL;
378 goto end;
379 }
380 case FILTER_OP_LOAD_FIELD_REF_STRING:
381 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
382 {
0305960f
MD
383 if (vstack_push(stack)) {
384 ret = -EINVAL;
385 goto end;
386 }
387 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
388 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
389 break;
390 }
391 case FILTER_OP_LOAD_FIELD_REF_S64:
392 {
0305960f
MD
393 if (vstack_push(stack)) {
394 ret = -EINVAL;
395 goto end;
396 }
397 vstack_ax(stack)->type = REG_S64;
97b58163
MD
398 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
399 break;
400 }
401 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
402 {
0305960f
MD
403 if (vstack_push(stack)) {
404 ret = -EINVAL;
405 goto end;
406 }
407 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
408 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
409 break;
410 }
411
412 case FILTER_OP_LOAD_STRING:
413 {
414 struct load_op *insn = (struct load_op *) pc;
415
0305960f
MD
416 if (vstack_push(stack)) {
417 ret = -EINVAL;
418 goto end;
419 }
420 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
421 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
422 break;
423 }
424
425 case FILTER_OP_LOAD_S64:
426 {
0305960f
MD
427 if (vstack_push(stack)) {
428 ret = -EINVAL;
429 goto end;
430 }
431 vstack_ax(stack)->type = REG_S64;
97b58163
MD
432 next_pc += sizeof(struct load_op)
433 + sizeof(struct literal_numeric);
434 break;
435 }
436
437 case FILTER_OP_LOAD_DOUBLE:
438 {
0305960f
MD
439 if (vstack_push(stack)) {
440 ret = -EINVAL;
441 goto end;
442 }
443 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
444 next_pc += sizeof(struct load_op)
445 + sizeof(struct literal_double);
446 break;
447 }
448
449 /* cast */
450 case FILTER_OP_CAST_TO_S64:
451 {
452 struct cast_op *insn = (struct cast_op *) pc;
453
0305960f 454 switch (vstack_ax(stack)->type) {
97b58163
MD
455 default:
456 ERR("unknown register type\n");
457 ret = -EINVAL;
458 goto end;
459
460 case REG_STRING:
461 ERR("Cast op can only be applied to numeric or floating point registers\n");
462 ret = -EINVAL;
463 goto end;
464 case REG_S64:
465 insn->op = FILTER_OP_CAST_NOP;
466 break;
467 case REG_DOUBLE:
468 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
469 break;
470 }
0305960f
MD
471 /* Pop 1, push 1 */
472 vstack_ax(stack)->type = REG_S64;
97b58163
MD
473 next_pc += sizeof(struct cast_op);
474 break;
475 }
476 case FILTER_OP_CAST_DOUBLE_TO_S64:
477 {
0305960f
MD
478 /* Pop 1, push 1 */
479 vstack_ax(stack)->type = REG_S64;
97b58163
MD
480 next_pc += sizeof(struct cast_op);
481 break;
482 }
483 case FILTER_OP_CAST_NOP:
484 {
485 next_pc += sizeof(struct cast_op);
486 break;
487 }
488
489
490 }
491 }
492end:
493 return ret;
494}
This page took 0.042177 seconds and 4 git commands to generate.