Commit | Line | Data |
---|---|---|
9f36eaed MJ |
1 | /* SPDX-License-Identifier: MIT |
2 | * | |
80c2a69a | 3 | * lttng-bytecode-specialize.c |
07dfc1d0 | 4 | * |
80c2a69a | 5 | * LTTng modules bytecode code specializer. |
07dfc1d0 | 6 | * |
bbf3aef5 | 7 | * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
07dfc1d0 MD |
8 | */ |
9 | ||
3834b99f | 10 | #include <linux/slab.h> |
80c2a69a | 11 | #include <lttng/lttng-bytecode.h> |
a071f25d | 12 | #include <lttng/align.h> |
07dfc1d0 | 13 | |
3834b99f MD |
14 | static ssize_t bytecode_reserve_data(struct bytecode_runtime *runtime, |
15 | size_t align, size_t len) | |
16 | { | |
17 | ssize_t ret; | |
18 | size_t padding = offset_align(runtime->data_len, align); | |
19 | size_t new_len = runtime->data_len + padding + len; | |
20 | size_t new_alloc_len = new_len; | |
21 | size_t old_alloc_len = runtime->data_alloc_len; | |
22 | ||
80c2a69a | 23 | if (new_len > INTERPRETER_MAX_DATA_LEN) |
3834b99f MD |
24 | return -EINVAL; |
25 | ||
26 | if (new_alloc_len > old_alloc_len) { | |
27 | char *newptr; | |
28 | ||
29 | new_alloc_len = | |
30 | max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1); | |
31 | newptr = krealloc(runtime->data, new_alloc_len, GFP_KERNEL); | |
32 | if (!newptr) | |
33 | return -ENOMEM; | |
34 | runtime->data = newptr; | |
35 | /* We zero directly the memory from start of allocation. */ | |
36 | memset(&runtime->data[old_alloc_len], 0, new_alloc_len - old_alloc_len); | |
37 | runtime->data_alloc_len = new_alloc_len; | |
38 | } | |
39 | runtime->data_len += padding; | |
40 | ret = runtime->data_len; | |
41 | runtime->data_len += len; | |
42 | return ret; | |
43 | } | |
44 | ||
45 | static ssize_t bytecode_push_data(struct bytecode_runtime *runtime, | |
46 | const void *p, size_t align, size_t len) | |
47 | { | |
48 | ssize_t offset; | |
49 | ||
50 | offset = bytecode_reserve_data(runtime, align, len); | |
51 | if (offset < 0) | |
52 | return -ENOMEM; | |
53 | memcpy(&runtime->data[offset], p, len); | |
54 | return offset; | |
55 | } | |
56 | ||
57 | static int specialize_load_field(struct vstack_entry *stack_top, | |
58 | struct load_op *insn) | |
59 | { | |
60 | int ret; | |
61 | ||
62 | switch (stack_top->load.type) { | |
63 | case LOAD_OBJECT: | |
64 | break; | |
65 | case LOAD_ROOT_CONTEXT: | |
66 | case LOAD_ROOT_APP_CONTEXT: | |
67 | case LOAD_ROOT_PAYLOAD: | |
68 | default: | |
80c2a69a | 69 | dbg_printk("Bytecode warning: cannot load root, missing field name.\n"); |
3834b99f MD |
70 | ret = -EINVAL; |
71 | goto end; | |
72 | } | |
73 | switch (stack_top->load.object_type) { | |
74 | case OBJECT_TYPE_S8: | |
75 | dbg_printk("op load field s8\n"); | |
76 | stack_top->type = REG_S64; | |
77 | if (!stack_top->load.rev_bo) | |
80c2a69a | 78 | insn->op = BYTECODE_OP_LOAD_FIELD_S8; |
3834b99f MD |
79 | break; |
80 | case OBJECT_TYPE_S16: | |
81 | dbg_printk("op load field s16\n"); | |
82 | stack_top->type = REG_S64; | |
83 | if (!stack_top->load.rev_bo) | |
80c2a69a | 84 | insn->op = BYTECODE_OP_LOAD_FIELD_S16; |
3834b99f MD |
85 | break; |
86 | case OBJECT_TYPE_S32: | |
87 | dbg_printk("op load field s32\n"); | |
88 | stack_top->type = REG_S64; | |
89 | if (!stack_top->load.rev_bo) | |
80c2a69a | 90 | insn->op = BYTECODE_OP_LOAD_FIELD_S32; |
3834b99f MD |
91 | break; |
92 | case OBJECT_TYPE_S64: | |
93 | dbg_printk("op load field s64\n"); | |
94 | stack_top->type = REG_S64; | |
95 | if (!stack_top->load.rev_bo) | |
80c2a69a | 96 | insn->op = BYTECODE_OP_LOAD_FIELD_S64; |
3834b99f | 97 | break; |
29a574c3 FD |
98 | case OBJECT_TYPE_SIGNED_ENUM: |
99 | dbg_printk("op load field signed enumeration\n"); | |
100 | stack_top->type = REG_PTR; | |
101 | break; | |
3834b99f MD |
102 | case OBJECT_TYPE_U8: |
103 | dbg_printk("op load field u8\n"); | |
104 | stack_top->type = REG_S64; | |
80c2a69a | 105 | insn->op = BYTECODE_OP_LOAD_FIELD_U8; |
3834b99f MD |
106 | break; |
107 | case OBJECT_TYPE_U16: | |
108 | dbg_printk("op load field u16\n"); | |
109 | stack_top->type = REG_S64; | |
110 | if (!stack_top->load.rev_bo) | |
80c2a69a | 111 | insn->op = BYTECODE_OP_LOAD_FIELD_U16; |
3834b99f MD |
112 | break; |
113 | case OBJECT_TYPE_U32: | |
114 | dbg_printk("op load field u32\n"); | |
115 | stack_top->type = REG_S64; | |
116 | if (!stack_top->load.rev_bo) | |
80c2a69a | 117 | insn->op = BYTECODE_OP_LOAD_FIELD_U32; |
3834b99f MD |
118 | break; |
119 | case OBJECT_TYPE_U64: | |
120 | dbg_printk("op load field u64\n"); | |
121 | stack_top->type = REG_S64; | |
122 | if (!stack_top->load.rev_bo) | |
80c2a69a | 123 | insn->op = BYTECODE_OP_LOAD_FIELD_U64; |
3834b99f | 124 | break; |
29a574c3 FD |
125 | case OBJECT_TYPE_UNSIGNED_ENUM: |
126 | dbg_printk("op load field unsigned enumeration\n"); | |
127 | stack_top->type = REG_PTR; | |
128 | break; | |
3834b99f | 129 | case OBJECT_TYPE_DOUBLE: |
80c2a69a | 130 | printk(KERN_WARNING "LTTng: bytecode: Double type unsupported\n\n"); |
3834b99f MD |
131 | ret = -EINVAL; |
132 | goto end; | |
133 | case OBJECT_TYPE_STRING: | |
134 | dbg_printk("op load field string\n"); | |
135 | stack_top->type = REG_STRING; | |
80c2a69a | 136 | insn->op = BYTECODE_OP_LOAD_FIELD_STRING; |
3834b99f MD |
137 | break; |
138 | case OBJECT_TYPE_STRING_SEQUENCE: | |
139 | dbg_printk("op load field string sequence\n"); | |
140 | stack_top->type = REG_STRING; | |
80c2a69a | 141 | insn->op = BYTECODE_OP_LOAD_FIELD_SEQUENCE; |
3834b99f MD |
142 | break; |
143 | case OBJECT_TYPE_DYNAMIC: | |
144 | ret = -EINVAL; | |
145 | goto end; | |
146 | case OBJECT_TYPE_SEQUENCE: | |
147 | case OBJECT_TYPE_ARRAY: | |
148 | case OBJECT_TYPE_STRUCT: | |
149 | case OBJECT_TYPE_VARIANT: | |
80c2a69a | 150 | printk(KERN_WARNING "LTTng: bytecode: Sequences, arrays, struct and variant cannot be loaded (nested types).\n"); |
3834b99f MD |
151 | ret = -EINVAL; |
152 | goto end; | |
153 | } | |
154 | return 0; | |
155 | ||
156 | end: | |
157 | return ret; | |
158 | } | |
159 | ||
160 | static int specialize_get_index_object_type(enum object_type *otype, | |
161 | int signedness, uint32_t elem_len) | |
162 | { | |
163 | switch (elem_len) { | |
164 | case 8: | |
165 | if (signedness) | |
166 | *otype = OBJECT_TYPE_S8; | |
167 | else | |
168 | *otype = OBJECT_TYPE_U8; | |
169 | break; | |
170 | case 16: | |
171 | if (signedness) | |
172 | *otype = OBJECT_TYPE_S16; | |
173 | else | |
174 | *otype = OBJECT_TYPE_U16; | |
175 | break; | |
176 | case 32: | |
177 | if (signedness) | |
178 | *otype = OBJECT_TYPE_S32; | |
179 | else | |
180 | *otype = OBJECT_TYPE_U32; | |
181 | break; | |
182 | case 64: | |
183 | if (signedness) | |
184 | *otype = OBJECT_TYPE_S64; | |
185 | else | |
186 | *otype = OBJECT_TYPE_U64; | |
187 | break; | |
188 | default: | |
189 | return -EINVAL; | |
190 | } | |
191 | return 0; | |
192 | } | |
193 | ||
194 | static int specialize_get_index(struct bytecode_runtime *runtime, | |
195 | struct load_op *insn, uint64_t index, | |
196 | struct vstack_entry *stack_top, | |
197 | int idx_len) | |
198 | { | |
199 | int ret; | |
80c2a69a | 200 | struct bytecode_get_index_data gid; |
3834b99f MD |
201 | ssize_t data_offset; |
202 | ||
203 | memset(&gid, 0, sizeof(gid)); | |
204 | switch (stack_top->load.type) { | |
205 | case LOAD_OBJECT: | |
206 | switch (stack_top->load.object_type) { | |
207 | case OBJECT_TYPE_ARRAY: | |
208 | { | |
ceabb767 | 209 | const struct lttng_integer_type *integer_type; |
3834b99f MD |
210 | const struct lttng_event_field *field; |
211 | uint32_t elem_len, num_elems; | |
212 | int signedness; | |
213 | ||
214 | field = stack_top->load.field; | |
ceabb767 MD |
215 | if (!lttng_is_bytewise_integer(field->type.u.array_nestable.elem_type)) { |
216 | ret = -EINVAL; | |
217 | goto end; | |
218 | } | |
219 | integer_type = &field->type.u.array_nestable.elem_type->u.integer; | |
220 | num_elems = field->type.u.array_nestable.length; | |
221 | elem_len = integer_type->size; | |
222 | signedness = integer_type->signedness; | |
3834b99f MD |
223 | if (index >= num_elems) { |
224 | ret = -EINVAL; | |
225 | goto end; | |
226 | } | |
227 | ret = specialize_get_index_object_type(&stack_top->load.object_type, | |
228 | signedness, elem_len); | |
229 | if (ret) | |
230 | goto end; | |
231 | gid.offset = index * (elem_len / CHAR_BIT); | |
232 | gid.array_len = num_elems * (elem_len / CHAR_BIT); | |
233 | gid.elem.type = stack_top->load.object_type; | |
234 | gid.elem.len = elem_len; | |
ceabb767 | 235 | if (integer_type->reverse_byte_order) |
3834b99f MD |
236 | gid.elem.rev_bo = true; |
237 | stack_top->load.rev_bo = gid.elem.rev_bo; | |
238 | break; | |
239 | } | |
240 | case OBJECT_TYPE_SEQUENCE: | |
241 | { | |
ceabb767 | 242 | const struct lttng_integer_type *integer_type; |
3834b99f MD |
243 | const struct lttng_event_field *field; |
244 | uint32_t elem_len; | |
245 | int signedness; | |
246 | ||
247 | field = stack_top->load.field; | |
ceabb767 MD |
248 | if (!lttng_is_bytewise_integer(field->type.u.sequence_nestable.elem_type)) { |
249 | ret = -EINVAL; | |
250 | goto end; | |
251 | } | |
252 | integer_type = &field->type.u.sequence_nestable.elem_type->u.integer; | |
253 | elem_len = integer_type->size; | |
254 | signedness = integer_type->signedness; | |
3834b99f MD |
255 | ret = specialize_get_index_object_type(&stack_top->load.object_type, |
256 | signedness, elem_len); | |
257 | if (ret) | |
258 | goto end; | |
259 | gid.offset = index * (elem_len / CHAR_BIT); | |
260 | gid.elem.type = stack_top->load.object_type; | |
261 | gid.elem.len = elem_len; | |
ceabb767 | 262 | if (integer_type->reverse_byte_order) |
3834b99f MD |
263 | gid.elem.rev_bo = true; |
264 | stack_top->load.rev_bo = gid.elem.rev_bo; | |
265 | break; | |
266 | } | |
267 | case OBJECT_TYPE_STRUCT: | |
268 | /* Only generated by the specialize phase. */ | |
269 | case OBJECT_TYPE_VARIANT: /* Fall-through */ | |
270 | default: | |
80c2a69a | 271 | printk(KERN_WARNING "LTTng: bytecode: Unexpected get index type %d", |
3834b99f MD |
272 | (int) stack_top->load.object_type); |
273 | ret = -EINVAL; | |
274 | goto end; | |
275 | } | |
276 | break; | |
277 | case LOAD_ROOT_CONTEXT: | |
278 | case LOAD_ROOT_APP_CONTEXT: | |
279 | case LOAD_ROOT_PAYLOAD: | |
80c2a69a | 280 | printk(KERN_WARNING "LTTng: bytecode: Index lookup for root field not implemented yet.\n"); |
3834b99f MD |
281 | ret = -EINVAL; |
282 | goto end; | |
283 | } | |
284 | data_offset = bytecode_push_data(runtime, &gid, | |
285 | __alignof__(gid), sizeof(gid)); | |
286 | if (data_offset < 0) { | |
287 | ret = -EINVAL; | |
288 | goto end; | |
289 | } | |
290 | switch (idx_len) { | |
291 | case 2: | |
292 | ((struct get_index_u16 *) insn->data)->index = data_offset; | |
293 | break; | |
294 | case 8: | |
295 | ((struct get_index_u64 *) insn->data)->index = data_offset; | |
296 | break; | |
297 | default: | |
298 | ret = -EINVAL; | |
299 | goto end; | |
300 | } | |
301 | ||
302 | return 0; | |
303 | ||
304 | end: | |
305 | return ret; | |
306 | } | |
307 | ||
2dfda770 FD |
308 | static int specialize_context_lookup_name(struct lttng_ctx *ctx, |
309 | struct bytecode_runtime *bytecode, | |
3834b99f MD |
310 | struct load_op *insn) |
311 | { | |
312 | uint16_t offset; | |
313 | const char *name; | |
314 | ||
315 | offset = ((struct get_symbol *) insn->data)->offset; | |
316 | name = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + offset; | |
2dfda770 | 317 | return lttng_get_context_index(ctx, name); |
3834b99f MD |
318 | } |
319 | ||
320 | static int specialize_load_object(const struct lttng_event_field *field, | |
321 | struct vstack_load *load, bool is_context) | |
322 | { | |
323 | load->type = LOAD_OBJECT; | |
1242217a | 324 | |
3834b99f MD |
325 | switch (field->type.atype) { |
326 | case atype_integer: | |
ceabb767 | 327 | if (field->type.u.integer.signedness) |
3834b99f MD |
328 | load->object_type = OBJECT_TYPE_S64; |
329 | else | |
330 | load->object_type = OBJECT_TYPE_U64; | |
331 | load->rev_bo = false; | |
332 | break; | |
ceabb767 | 333 | case atype_enum_nestable: |
3834b99f MD |
334 | { |
335 | const struct lttng_integer_type *itype = | |
ceabb767 | 336 | &field->type.u.enum_nestable.container_type->u.integer; |
3834b99f MD |
337 | |
338 | if (itype->signedness) | |
29a574c3 | 339 | load->object_type = OBJECT_TYPE_SIGNED_ENUM; |
3834b99f | 340 | else |
29a574c3 | 341 | load->object_type = OBJECT_TYPE_UNSIGNED_ENUM; |
3834b99f MD |
342 | load->rev_bo = false; |
343 | break; | |
344 | } | |
ceabb767 MD |
345 | case atype_array_nestable: |
346 | if (!lttng_is_bytewise_integer(field->type.u.array_nestable.elem_type)) { | |
80c2a69a | 347 | printk(KERN_WARNING "LTTng: bytecode: Array nesting only supports integer types.\n"); |
3834b99f MD |
348 | return -EINVAL; |
349 | } | |
350 | if (is_context) { | |
351 | load->object_type = OBJECT_TYPE_STRING; | |
352 | } else { | |
ceabb767 | 353 | if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) { |
3834b99f MD |
354 | load->object_type = OBJECT_TYPE_ARRAY; |
355 | load->field = field; | |
356 | } else { | |
357 | load->object_type = OBJECT_TYPE_STRING_SEQUENCE; | |
358 | } | |
359 | } | |
360 | break; | |
ceabb767 MD |
361 | case atype_sequence_nestable: |
362 | if (!lttng_is_bytewise_integer(field->type.u.sequence_nestable.elem_type)) { | |
80c2a69a | 363 | printk(KERN_WARNING "LTTng: bytecode: Sequence nesting only supports integer types.\n"); |
3834b99f MD |
364 | return -EINVAL; |
365 | } | |
366 | if (is_context) { | |
367 | load->object_type = OBJECT_TYPE_STRING; | |
368 | } else { | |
ceabb767 | 369 | if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) { |
3834b99f MD |
370 | load->object_type = OBJECT_TYPE_SEQUENCE; |
371 | load->field = field; | |
372 | } else { | |
373 | load->object_type = OBJECT_TYPE_STRING_SEQUENCE; | |
374 | } | |
375 | } | |
376 | break; | |
3834b99f MD |
377 | case atype_string: |
378 | load->object_type = OBJECT_TYPE_STRING; | |
379 | break; | |
ceabb767 | 380 | case atype_struct_nestable: |
80c2a69a | 381 | printk(KERN_WARNING "LTTng: bytecode: Structure type cannot be loaded.\n"); |
3834b99f | 382 | return -EINVAL; |
ceabb767 | 383 | case atype_variant_nestable: |
80c2a69a | 384 | printk(KERN_WARNING "LTTng: bytecode: Variant type cannot be loaded.\n"); |
ceabb767 | 385 | return -EINVAL; |
3834b99f | 386 | default: |
80c2a69a | 387 | printk(KERN_WARNING "LTTng: bytecode: Unknown type: %d", (int) field->type.atype); |
3834b99f MD |
388 | return -EINVAL; |
389 | } | |
390 | return 0; | |
391 | } | |
392 | ||
2dfda770 FD |
393 | static int specialize_context_lookup(struct lttng_ctx *ctx, |
394 | struct bytecode_runtime *runtime, | |
3834b99f MD |
395 | struct load_op *insn, |
396 | struct vstack_load *load) | |
397 | { | |
398 | int idx, ret; | |
399 | struct lttng_ctx_field *ctx_field; | |
400 | struct lttng_event_field *field; | |
80c2a69a | 401 | struct bytecode_get_index_data gid; |
3834b99f MD |
402 | ssize_t data_offset; |
403 | ||
2dfda770 | 404 | idx = specialize_context_lookup_name(ctx, runtime, insn); |
3834b99f MD |
405 | if (idx < 0) { |
406 | return -ENOENT; | |
407 | } | |
408 | ctx_field = <tng_static_ctx->fields[idx]; | |
409 | field = &ctx_field->event_field; | |
410 | ret = specialize_load_object(field, load, true); | |
411 | if (ret) | |
412 | return ret; | |
413 | /* Specialize each get_symbol into a get_index. */ | |
80c2a69a | 414 | insn->op = BYTECODE_OP_GET_INDEX_U16; |
3834b99f MD |
415 | memset(&gid, 0, sizeof(gid)); |
416 | gid.ctx_index = idx; | |
417 | gid.elem.type = load->object_type; | |
60e8b0d6 | 418 | gid.elem.rev_bo = load->rev_bo; |
03cb0cdd | 419 | gid.field = field; |
3834b99f MD |
420 | data_offset = bytecode_push_data(runtime, &gid, |
421 | __alignof__(gid), sizeof(gid)); | |
422 | if (data_offset < 0) { | |
423 | return -EINVAL; | |
424 | } | |
425 | ((struct get_index_u16 *) insn->data)->index = data_offset; | |
426 | return 0; | |
427 | } | |
428 | ||
2dfda770 | 429 | static int specialize_payload_lookup(const struct lttng_event_desc *event_desc, |
3834b99f MD |
430 | struct bytecode_runtime *runtime, |
431 | struct load_op *insn, | |
432 | struct vstack_load *load) | |
433 | { | |
434 | const char *name; | |
435 | uint16_t offset; | |
3834b99f MD |
436 | unsigned int i, nr_fields; |
437 | bool found = false; | |
438 | uint32_t field_offset = 0; | |
439 | const struct lttng_event_field *field; | |
440 | int ret; | |
80c2a69a | 441 | struct bytecode_get_index_data gid; |
3834b99f MD |
442 | ssize_t data_offset; |
443 | ||
2dfda770 | 444 | nr_fields = event_desc->nr_fields; |
3834b99f MD |
445 | offset = ((struct get_symbol *) insn->data)->offset; |
446 | name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset; | |
447 | for (i = 0; i < nr_fields; i++) { | |
2dfda770 | 448 | field = &event_desc->fields[i]; |
ceabb767 MD |
449 | if (field->nofilter) { |
450 | continue; | |
451 | } | |
3834b99f MD |
452 | if (!strcmp(field->name, name)) { |
453 | found = true; | |
454 | break; | |
455 | } | |
456 | /* compute field offset on stack */ | |
457 | switch (field->type.atype) { | |
458 | case atype_integer: | |
ceabb767 | 459 | case atype_enum_nestable: |
3834b99f MD |
460 | field_offset += sizeof(int64_t); |
461 | break; | |
ceabb767 MD |
462 | case atype_array_nestable: |
463 | case atype_sequence_nestable: | |
3834b99f MD |
464 | field_offset += sizeof(unsigned long); |
465 | field_offset += sizeof(void *); | |
466 | break; | |
467 | case atype_string: | |
468 | field_offset += sizeof(void *); | |
469 | break; | |
470 | default: | |
471 | ret = -EINVAL; | |
472 | goto end; | |
473 | } | |
474 | } | |
475 | if (!found) { | |
476 | ret = -EINVAL; | |
477 | goto end; | |
478 | } | |
479 | ||
480 | ret = specialize_load_object(field, load, false); | |
481 | if (ret) | |
482 | goto end; | |
483 | ||
484 | /* Specialize each get_symbol into a get_index. */ | |
80c2a69a | 485 | insn->op = BYTECODE_OP_GET_INDEX_U16; |
3834b99f MD |
486 | memset(&gid, 0, sizeof(gid)); |
487 | gid.offset = field_offset; | |
488 | gid.elem.type = load->object_type; | |
60e8b0d6 | 489 | gid.elem.rev_bo = load->rev_bo; |
03cb0cdd | 490 | gid.field = field; |
3834b99f MD |
491 | data_offset = bytecode_push_data(runtime, &gid, |
492 | __alignof__(gid), sizeof(gid)); | |
493 | if (data_offset < 0) { | |
494 | ret = -EINVAL; | |
495 | goto end; | |
496 | } | |
497 | ((struct get_index_u16 *) insn->data)->index = data_offset; | |
498 | ret = 0; | |
499 | end: | |
500 | return ret; | |
501 | } | |
502 | ||
80c2a69a | 503 | int lttng_bytecode_specialize(const struct lttng_event_desc *event_desc, |
3834b99f | 504 | struct bytecode_runtime *bytecode) |
07dfc1d0 MD |
505 | { |
506 | void *pc, *next_pc, *start_pc; | |
507 | int ret = -EINVAL; | |
508 | struct vstack _stack; | |
509 | struct vstack *stack = &_stack; | |
2dfda770 | 510 | struct lttng_ctx *ctx = bytecode->p.ctx; |
07dfc1d0 MD |
511 | |
512 | vstack_init(stack); | |
513 | ||
3834b99f | 514 | start_pc = &bytecode->code[0]; |
07dfc1d0 MD |
515 | for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; |
516 | pc = next_pc) { | |
80c2a69a FD |
517 | switch (*(bytecode_opcode_t *) pc) { |
518 | case BYTECODE_OP_UNKNOWN: | |
07dfc1d0 | 519 | default: |
80c2a69a FD |
520 | printk(KERN_WARNING "LTTng: bytecode: unknown bytecode op %u\n", |
521 | (unsigned int) *(bytecode_opcode_t *) pc); | |
07dfc1d0 MD |
522 | ret = -EINVAL; |
523 | goto end; | |
524 | ||
80c2a69a FD |
525 | case BYTECODE_OP_RETURN: |
526 | case BYTECODE_OP_RETURN_S64: | |
07dfc1d0 MD |
527 | ret = 0; |
528 | goto end; | |
529 | ||
530 | /* binary */ | |
80c2a69a FD |
531 | case BYTECODE_OP_MUL: |
532 | case BYTECODE_OP_DIV: | |
533 | case BYTECODE_OP_MOD: | |
534 | case BYTECODE_OP_PLUS: | |
535 | case BYTECODE_OP_MINUS: | |
536 | printk(KERN_WARNING "LTTng: bytecode: unknown bytecode op %u\n", | |
537 | (unsigned int) *(bytecode_opcode_t *) pc); | |
07dfc1d0 MD |
538 | ret = -EINVAL; |
539 | goto end; | |
540 | ||
80c2a69a | 541 | case BYTECODE_OP_EQ: |
07dfc1d0 MD |
542 | { |
543 | struct binary_op *insn = (struct binary_op *) pc; | |
544 | ||
545 | switch(vstack_ax(stack)->type) { | |
546 | default: | |
80c2a69a | 547 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
548 | ret = -EINVAL; |
549 | goto end; | |
550 | ||
551 | case REG_STRING: | |
02aca193 | 552 | if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING) |
80c2a69a | 553 | insn->op = BYTECODE_OP_EQ_STAR_GLOB_STRING; |
02aca193 | 554 | else |
80c2a69a | 555 | insn->op = BYTECODE_OP_EQ_STRING; |
02aca193 PP |
556 | break; |
557 | case REG_STAR_GLOB_STRING: | |
80c2a69a | 558 | insn->op = BYTECODE_OP_EQ_STAR_GLOB_STRING; |
07dfc1d0 MD |
559 | break; |
560 | case REG_S64: | |
561 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 562 | insn->op = BYTECODE_OP_EQ_S64; |
07dfc1d0 | 563 | else |
80c2a69a | 564 | insn->op = BYTECODE_OP_EQ_DOUBLE_S64; |
07dfc1d0 MD |
565 | break; |
566 | case REG_DOUBLE: | |
567 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 568 | insn->op = BYTECODE_OP_EQ_S64_DOUBLE; |
07dfc1d0 | 569 | else |
80c2a69a | 570 | insn->op = BYTECODE_OP_EQ_DOUBLE; |
07dfc1d0 MD |
571 | break; |
572 | } | |
573 | /* Pop 2, push 1 */ | |
574 | if (vstack_pop(stack)) { | |
575 | ret = -EINVAL; | |
576 | goto end; | |
577 | } | |
578 | vstack_ax(stack)->type = REG_S64; | |
579 | next_pc += sizeof(struct binary_op); | |
580 | break; | |
581 | } | |
582 | ||
80c2a69a | 583 | case BYTECODE_OP_NE: |
07dfc1d0 MD |
584 | { |
585 | struct binary_op *insn = (struct binary_op *) pc; | |
586 | ||
587 | switch(vstack_ax(stack)->type) { | |
588 | default: | |
80c2a69a | 589 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
590 | ret = -EINVAL; |
591 | goto end; | |
592 | ||
593 | case REG_STRING: | |
02aca193 | 594 | if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING) |
80c2a69a | 595 | insn->op = BYTECODE_OP_NE_STAR_GLOB_STRING; |
02aca193 | 596 | else |
80c2a69a | 597 | insn->op = BYTECODE_OP_NE_STRING; |
02aca193 PP |
598 | break; |
599 | case REG_STAR_GLOB_STRING: | |
80c2a69a | 600 | insn->op = BYTECODE_OP_NE_STAR_GLOB_STRING; |
07dfc1d0 MD |
601 | break; |
602 | case REG_S64: | |
603 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 604 | insn->op = BYTECODE_OP_NE_S64; |
07dfc1d0 | 605 | else |
80c2a69a | 606 | insn->op = BYTECODE_OP_NE_DOUBLE_S64; |
07dfc1d0 MD |
607 | break; |
608 | case REG_DOUBLE: | |
609 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 610 | insn->op = BYTECODE_OP_NE_S64_DOUBLE; |
07dfc1d0 | 611 | else |
80c2a69a | 612 | insn->op = BYTECODE_OP_NE_DOUBLE; |
07dfc1d0 MD |
613 | break; |
614 | } | |
615 | /* Pop 2, push 1 */ | |
616 | if (vstack_pop(stack)) { | |
617 | ret = -EINVAL; | |
618 | goto end; | |
619 | } | |
620 | vstack_ax(stack)->type = REG_S64; | |
621 | next_pc += sizeof(struct binary_op); | |
622 | break; | |
623 | } | |
624 | ||
80c2a69a | 625 | case BYTECODE_OP_GT: |
07dfc1d0 MD |
626 | { |
627 | struct binary_op *insn = (struct binary_op *) pc; | |
628 | ||
629 | switch(vstack_ax(stack)->type) { | |
630 | default: | |
80c2a69a | 631 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
632 | ret = -EINVAL; |
633 | goto end; | |
634 | ||
02aca193 | 635 | case REG_STAR_GLOB_STRING: |
80c2a69a | 636 | printk(KERN_WARNING "LTTng: bytecode: invalid register type for '>' binary operator\n"); |
02aca193 PP |
637 | ret = -EINVAL; |
638 | goto end; | |
07dfc1d0 | 639 | case REG_STRING: |
80c2a69a | 640 | insn->op = BYTECODE_OP_GT_STRING; |
07dfc1d0 MD |
641 | break; |
642 | case REG_S64: | |
643 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 644 | insn->op = BYTECODE_OP_GT_S64; |
07dfc1d0 | 645 | else |
80c2a69a | 646 | insn->op = BYTECODE_OP_GT_DOUBLE_S64; |
07dfc1d0 MD |
647 | break; |
648 | case REG_DOUBLE: | |
649 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 650 | insn->op = BYTECODE_OP_GT_S64_DOUBLE; |
07dfc1d0 | 651 | else |
80c2a69a | 652 | insn->op = BYTECODE_OP_GT_DOUBLE; |
07dfc1d0 MD |
653 | break; |
654 | } | |
655 | /* Pop 2, push 1 */ | |
656 | if (vstack_pop(stack)) { | |
657 | ret = -EINVAL; | |
658 | goto end; | |
659 | } | |
660 | vstack_ax(stack)->type = REG_S64; | |
661 | next_pc += sizeof(struct binary_op); | |
662 | break; | |
663 | } | |
664 | ||
80c2a69a | 665 | case BYTECODE_OP_LT: |
07dfc1d0 MD |
666 | { |
667 | struct binary_op *insn = (struct binary_op *) pc; | |
668 | ||
669 | switch(vstack_ax(stack)->type) { | |
670 | default: | |
80c2a69a | 671 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
672 | ret = -EINVAL; |
673 | goto end; | |
674 | ||
02aca193 | 675 | case REG_STAR_GLOB_STRING: |
80c2a69a | 676 | printk(KERN_WARNING "LTTng: bytecode: invalid register type for '<' binary operator\n"); |
02aca193 PP |
677 | ret = -EINVAL; |
678 | goto end; | |
07dfc1d0 | 679 | case REG_STRING: |
80c2a69a | 680 | insn->op = BYTECODE_OP_LT_STRING; |
07dfc1d0 MD |
681 | break; |
682 | case REG_S64: | |
683 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 684 | insn->op = BYTECODE_OP_LT_S64; |
07dfc1d0 | 685 | else |
80c2a69a | 686 | insn->op = BYTECODE_OP_LT_DOUBLE_S64; |
07dfc1d0 MD |
687 | break; |
688 | case REG_DOUBLE: | |
689 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 690 | insn->op = BYTECODE_OP_LT_S64_DOUBLE; |
07dfc1d0 | 691 | else |
80c2a69a | 692 | insn->op = BYTECODE_OP_LT_DOUBLE; |
07dfc1d0 MD |
693 | break; |
694 | } | |
695 | /* Pop 2, push 1 */ | |
696 | if (vstack_pop(stack)) { | |
697 | ret = -EINVAL; | |
698 | goto end; | |
699 | } | |
700 | vstack_ax(stack)->type = REG_S64; | |
701 | next_pc += sizeof(struct binary_op); | |
702 | break; | |
703 | } | |
704 | ||
80c2a69a | 705 | case BYTECODE_OP_GE: |
07dfc1d0 MD |
706 | { |
707 | struct binary_op *insn = (struct binary_op *) pc; | |
708 | ||
709 | switch(vstack_ax(stack)->type) { | |
710 | default: | |
80c2a69a | 711 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
712 | ret = -EINVAL; |
713 | goto end; | |
714 | ||
02aca193 | 715 | case REG_STAR_GLOB_STRING: |
80c2a69a | 716 | printk(KERN_WARNING "LTTng: bytecode: invalid register type for '>=' binary operator\n"); |
02aca193 PP |
717 | ret = -EINVAL; |
718 | goto end; | |
07dfc1d0 | 719 | case REG_STRING: |
80c2a69a | 720 | insn->op = BYTECODE_OP_GE_STRING; |
07dfc1d0 MD |
721 | break; |
722 | case REG_S64: | |
723 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 724 | insn->op = BYTECODE_OP_GE_S64; |
07dfc1d0 | 725 | else |
80c2a69a | 726 | insn->op = BYTECODE_OP_GE_DOUBLE_S64; |
07dfc1d0 MD |
727 | break; |
728 | case REG_DOUBLE: | |
729 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 730 | insn->op = BYTECODE_OP_GE_S64_DOUBLE; |
07dfc1d0 | 731 | else |
80c2a69a | 732 | insn->op = BYTECODE_OP_GE_DOUBLE; |
07dfc1d0 MD |
733 | break; |
734 | } | |
735 | /* Pop 2, push 1 */ | |
736 | if (vstack_pop(stack)) { | |
737 | ret = -EINVAL; | |
738 | goto end; | |
739 | } | |
740 | vstack_ax(stack)->type = REG_S64; | |
741 | next_pc += sizeof(struct binary_op); | |
742 | break; | |
743 | } | |
80c2a69a | 744 | case BYTECODE_OP_LE: |
07dfc1d0 MD |
745 | { |
746 | struct binary_op *insn = (struct binary_op *) pc; | |
747 | ||
748 | switch(vstack_ax(stack)->type) { | |
749 | default: | |
80c2a69a | 750 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
751 | ret = -EINVAL; |
752 | goto end; | |
753 | ||
02aca193 | 754 | case REG_STAR_GLOB_STRING: |
80c2a69a | 755 | printk(KERN_WARNING "LTTng: bytecode: invalid register type for '<=' binary operator\n"); |
02aca193 PP |
756 | ret = -EINVAL; |
757 | goto end; | |
07dfc1d0 | 758 | case REG_STRING: |
80c2a69a | 759 | insn->op = BYTECODE_OP_LE_STRING; |
07dfc1d0 MD |
760 | break; |
761 | case REG_S64: | |
762 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 763 | insn->op = BYTECODE_OP_LE_S64; |
07dfc1d0 | 764 | else |
80c2a69a | 765 | insn->op = BYTECODE_OP_LE_DOUBLE_S64; |
07dfc1d0 MD |
766 | break; |
767 | case REG_DOUBLE: | |
768 | if (vstack_bx(stack)->type == REG_S64) | |
80c2a69a | 769 | insn->op = BYTECODE_OP_LE_S64_DOUBLE; |
07dfc1d0 | 770 | else |
80c2a69a | 771 | insn->op = BYTECODE_OP_LE_DOUBLE; |
07dfc1d0 MD |
772 | break; |
773 | } | |
774 | vstack_ax(stack)->type = REG_S64; | |
775 | next_pc += sizeof(struct binary_op); | |
776 | break; | |
777 | } | |
778 | ||
80c2a69a FD |
779 | case BYTECODE_OP_EQ_STRING: |
780 | case BYTECODE_OP_NE_STRING: | |
781 | case BYTECODE_OP_GT_STRING: | |
782 | case BYTECODE_OP_LT_STRING: | |
783 | case BYTECODE_OP_GE_STRING: | |
784 | case BYTECODE_OP_LE_STRING: | |
785 | case BYTECODE_OP_EQ_STAR_GLOB_STRING: | |
786 | case BYTECODE_OP_NE_STAR_GLOB_STRING: | |
787 | case BYTECODE_OP_EQ_S64: | |
788 | case BYTECODE_OP_NE_S64: | |
789 | case BYTECODE_OP_GT_S64: | |
790 | case BYTECODE_OP_LT_S64: | |
791 | case BYTECODE_OP_GE_S64: | |
792 | case BYTECODE_OP_LE_S64: | |
793 | case BYTECODE_OP_EQ_DOUBLE: | |
794 | case BYTECODE_OP_NE_DOUBLE: | |
795 | case BYTECODE_OP_GT_DOUBLE: | |
796 | case BYTECODE_OP_LT_DOUBLE: | |
797 | case BYTECODE_OP_GE_DOUBLE: | |
798 | case BYTECODE_OP_LE_DOUBLE: | |
799 | case BYTECODE_OP_EQ_DOUBLE_S64: | |
800 | case BYTECODE_OP_NE_DOUBLE_S64: | |
801 | case BYTECODE_OP_GT_DOUBLE_S64: | |
802 | case BYTECODE_OP_LT_DOUBLE_S64: | |
803 | case BYTECODE_OP_GE_DOUBLE_S64: | |
804 | case BYTECODE_OP_LE_DOUBLE_S64: | |
805 | case BYTECODE_OP_EQ_S64_DOUBLE: | |
806 | case BYTECODE_OP_NE_S64_DOUBLE: | |
807 | case BYTECODE_OP_GT_S64_DOUBLE: | |
808 | case BYTECODE_OP_LT_S64_DOUBLE: | |
809 | case BYTECODE_OP_GE_S64_DOUBLE: | |
810 | case BYTECODE_OP_LE_S64_DOUBLE: | |
811 | case BYTECODE_OP_BIT_RSHIFT: | |
812 | case BYTECODE_OP_BIT_LSHIFT: | |
813 | case BYTECODE_OP_BIT_AND: | |
814 | case BYTECODE_OP_BIT_OR: | |
815 | case BYTECODE_OP_BIT_XOR: | |
07dfc1d0 MD |
816 | { |
817 | /* Pop 2, push 1 */ | |
818 | if (vstack_pop(stack)) { | |
819 | ret = -EINVAL; | |
820 | goto end; | |
821 | } | |
822 | vstack_ax(stack)->type = REG_S64; | |
823 | next_pc += sizeof(struct binary_op); | |
824 | break; | |
825 | } | |
826 | ||
827 | /* unary */ | |
80c2a69a | 828 | case BYTECODE_OP_UNARY_PLUS: |
07dfc1d0 MD |
829 | { |
830 | struct unary_op *insn = (struct unary_op *) pc; | |
831 | ||
832 | switch(vstack_ax(stack)->type) { | |
833 | default: | |
80c2a69a | 834 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
835 | ret = -EINVAL; |
836 | goto end; | |
837 | ||
838 | case REG_S64: | |
80c2a69a | 839 | insn->op = BYTECODE_OP_UNARY_PLUS_S64; |
07dfc1d0 MD |
840 | break; |
841 | case REG_DOUBLE: | |
80c2a69a | 842 | insn->op = BYTECODE_OP_UNARY_PLUS_DOUBLE; |
07dfc1d0 MD |
843 | break; |
844 | } | |
845 | /* Pop 1, push 1 */ | |
846 | next_pc += sizeof(struct unary_op); | |
847 | break; | |
848 | } | |
849 | ||
80c2a69a | 850 | case BYTECODE_OP_UNARY_MINUS: |
07dfc1d0 MD |
851 | { |
852 | struct unary_op *insn = (struct unary_op *) pc; | |
853 | ||
854 | switch(vstack_ax(stack)->type) { | |
855 | default: | |
80c2a69a | 856 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
857 | ret = -EINVAL; |
858 | goto end; | |
859 | ||
860 | case REG_S64: | |
80c2a69a | 861 | insn->op = BYTECODE_OP_UNARY_MINUS_S64; |
07dfc1d0 MD |
862 | break; |
863 | case REG_DOUBLE: | |
80c2a69a | 864 | insn->op = BYTECODE_OP_UNARY_MINUS_DOUBLE; |
07dfc1d0 MD |
865 | break; |
866 | } | |
867 | /* Pop 1, push 1 */ | |
868 | next_pc += sizeof(struct unary_op); | |
869 | break; | |
870 | } | |
871 | ||
80c2a69a | 872 | case BYTECODE_OP_UNARY_NOT: |
07dfc1d0 MD |
873 | { |
874 | struct unary_op *insn = (struct unary_op *) pc; | |
875 | ||
876 | switch(vstack_ax(stack)->type) { | |
877 | default: | |
80c2a69a | 878 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
879 | ret = -EINVAL; |
880 | goto end; | |
881 | ||
882 | case REG_S64: | |
80c2a69a | 883 | insn->op = BYTECODE_OP_UNARY_NOT_S64; |
07dfc1d0 MD |
884 | break; |
885 | case REG_DOUBLE: | |
80c2a69a | 886 | insn->op = BYTECODE_OP_UNARY_NOT_DOUBLE; |
07dfc1d0 MD |
887 | break; |
888 | } | |
889 | /* Pop 1, push 1 */ | |
890 | next_pc += sizeof(struct unary_op); | |
891 | break; | |
892 | } | |
893 | ||
80c2a69a | 894 | case BYTECODE_OP_UNARY_BIT_NOT: |
e16c054b MD |
895 | { |
896 | /* Pop 1, push 1 */ | |
897 | next_pc += sizeof(struct unary_op); | |
898 | break; | |
899 | } | |
900 | ||
80c2a69a FD |
901 | case BYTECODE_OP_UNARY_PLUS_S64: |
902 | case BYTECODE_OP_UNARY_MINUS_S64: | |
903 | case BYTECODE_OP_UNARY_NOT_S64: | |
904 | case BYTECODE_OP_UNARY_PLUS_DOUBLE: | |
905 | case BYTECODE_OP_UNARY_MINUS_DOUBLE: | |
906 | case BYTECODE_OP_UNARY_NOT_DOUBLE: | |
07dfc1d0 MD |
907 | { |
908 | /* Pop 1, push 1 */ | |
909 | next_pc += sizeof(struct unary_op); | |
910 | break; | |
911 | } | |
912 | ||
913 | /* logical */ | |
80c2a69a FD |
914 | case BYTECODE_OP_AND: |
915 | case BYTECODE_OP_OR: | |
07dfc1d0 MD |
916 | { |
917 | /* Continue to next instruction */ | |
918 | /* Pop 1 when jump not taken */ | |
919 | if (vstack_pop(stack)) { | |
920 | ret = -EINVAL; | |
921 | goto end; | |
922 | } | |
923 | next_pc += sizeof(struct logical_op); | |
924 | break; | |
925 | } | |
926 | ||
927 | /* load field ref */ | |
80c2a69a | 928 | case BYTECODE_OP_LOAD_FIELD_REF: |
07dfc1d0 | 929 | { |
80c2a69a | 930 | printk(KERN_WARNING "LTTng: bytecode: Unknown field ref type\n"); |
07dfc1d0 MD |
931 | ret = -EINVAL; |
932 | goto end; | |
933 | } | |
934 | /* get context ref */ | |
80c2a69a | 935 | case BYTECODE_OP_GET_CONTEXT_REF: |
07dfc1d0 | 936 | { |
80c2a69a | 937 | printk(KERN_WARNING "LTTng: bytecode: Unknown get context ref type\n"); |
07dfc1d0 MD |
938 | ret = -EINVAL; |
939 | goto end; | |
940 | } | |
80c2a69a FD |
941 | case BYTECODE_OP_LOAD_FIELD_REF_STRING: |
942 | case BYTECODE_OP_LOAD_FIELD_REF_SEQUENCE: | |
943 | case BYTECODE_OP_GET_CONTEXT_REF_STRING: | |
944 | case BYTECODE_OP_LOAD_FIELD_REF_USER_STRING: | |
945 | case BYTECODE_OP_LOAD_FIELD_REF_USER_SEQUENCE: | |
07dfc1d0 MD |
946 | { |
947 | if (vstack_push(stack)) { | |
948 | ret = -EINVAL; | |
949 | goto end; | |
950 | } | |
951 | vstack_ax(stack)->type = REG_STRING; | |
952 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); | |
953 | break; | |
954 | } | |
80c2a69a FD |
955 | case BYTECODE_OP_LOAD_FIELD_REF_S64: |
956 | case BYTECODE_OP_GET_CONTEXT_REF_S64: | |
07dfc1d0 MD |
957 | { |
958 | if (vstack_push(stack)) { | |
959 | ret = -EINVAL; | |
960 | goto end; | |
961 | } | |
962 | vstack_ax(stack)->type = REG_S64; | |
963 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); | |
964 | break; | |
965 | } | |
80c2a69a FD |
966 | case BYTECODE_OP_LOAD_FIELD_REF_DOUBLE: |
967 | case BYTECODE_OP_GET_CONTEXT_REF_DOUBLE: | |
07dfc1d0 MD |
968 | { |
969 | if (vstack_push(stack)) { | |
970 | ret = -EINVAL; | |
971 | goto end; | |
972 | } | |
973 | vstack_ax(stack)->type = REG_DOUBLE; | |
974 | next_pc += sizeof(struct load_op) + sizeof(struct field_ref); | |
975 | break; | |
976 | } | |
977 | ||
978 | /* load from immediate operand */ | |
80c2a69a | 979 | case BYTECODE_OP_LOAD_STRING: |
07dfc1d0 MD |
980 | { |
981 | struct load_op *insn = (struct load_op *) pc; | |
982 | ||
983 | if (vstack_push(stack)) { | |
984 | ret = -EINVAL; | |
985 | goto end; | |
986 | } | |
987 | vstack_ax(stack)->type = REG_STRING; | |
988 | next_pc += sizeof(struct load_op) + strlen(insn->data) + 1; | |
989 | break; | |
990 | } | |
991 | ||
80c2a69a | 992 | case BYTECODE_OP_LOAD_STAR_GLOB_STRING: |
02aca193 PP |
993 | { |
994 | struct load_op *insn = (struct load_op *) pc; | |
995 | ||
996 | if (vstack_push(stack)) { | |
997 | ret = -EINVAL; | |
998 | goto end; | |
999 | } | |
1000 | vstack_ax(stack)->type = REG_STAR_GLOB_STRING; | |
1001 | next_pc += sizeof(struct load_op) + strlen(insn->data) + 1; | |
1002 | break; | |
1003 | } | |
1004 | ||
80c2a69a | 1005 | case BYTECODE_OP_LOAD_S64: |
07dfc1d0 MD |
1006 | { |
1007 | if (vstack_push(stack)) { | |
1008 | ret = -EINVAL; | |
1009 | goto end; | |
1010 | } | |
1011 | vstack_ax(stack)->type = REG_S64; | |
1012 | next_pc += sizeof(struct load_op) | |
1013 | + sizeof(struct literal_numeric); | |
1014 | break; | |
1015 | } | |
1016 | ||
80c2a69a | 1017 | case BYTECODE_OP_LOAD_DOUBLE: |
07dfc1d0 MD |
1018 | { |
1019 | if (vstack_push(stack)) { | |
1020 | ret = -EINVAL; | |
1021 | goto end; | |
1022 | } | |
1023 | vstack_ax(stack)->type = REG_DOUBLE; | |
1024 | next_pc += sizeof(struct load_op) | |
1025 | + sizeof(struct literal_double); | |
1026 | break; | |
1027 | } | |
1028 | ||
1029 | /* cast */ | |
80c2a69a | 1030 | case BYTECODE_OP_CAST_TO_S64: |
07dfc1d0 MD |
1031 | { |
1032 | struct cast_op *insn = (struct cast_op *) pc; | |
1033 | ||
1034 | switch (vstack_ax(stack)->type) { | |
1035 | default: | |
80c2a69a | 1036 | printk(KERN_WARNING "LTTng: bytecode: unknown register type\n"); |
07dfc1d0 MD |
1037 | ret = -EINVAL; |
1038 | goto end; | |
1039 | ||
1040 | case REG_STRING: | |
02aca193 | 1041 | case REG_STAR_GLOB_STRING: |
80c2a69a | 1042 | printk(KERN_WARNING "LTTng: bytecode: Cast op can only be applied to numeric or floating point registers\n"); |
07dfc1d0 MD |
1043 | ret = -EINVAL; |
1044 | goto end; | |
1045 | case REG_S64: | |
80c2a69a | 1046 | insn->op = BYTECODE_OP_CAST_NOP; |
07dfc1d0 MD |
1047 | break; |
1048 | case REG_DOUBLE: | |
80c2a69a | 1049 | insn->op = BYTECODE_OP_CAST_DOUBLE_TO_S64; |
07dfc1d0 MD |
1050 | break; |
1051 | } | |
1052 | /* Pop 1, push 1 */ | |
1053 | vstack_ax(stack)->type = REG_S64; | |
1054 | next_pc += sizeof(struct cast_op); | |
1055 | break; | |
1056 | } | |
80c2a69a | 1057 | case BYTECODE_OP_CAST_DOUBLE_TO_S64: |
07dfc1d0 MD |
1058 | { |
1059 | /* Pop 1, push 1 */ | |
1060 | vstack_ax(stack)->type = REG_S64; | |
1061 | next_pc += sizeof(struct cast_op); | |
1062 | break; | |
1063 | } | |
80c2a69a | 1064 | case BYTECODE_OP_CAST_NOP: |
07dfc1d0 MD |
1065 | { |
1066 | next_pc += sizeof(struct cast_op); | |
1067 | break; | |
1068 | } | |
1069 | ||
3834b99f MD |
1070 | /* |
1071 | * Instructions for recursive traversal through composed types. | |
1072 | */ | |
80c2a69a | 1073 | case BYTECODE_OP_GET_CONTEXT_ROOT: |
3834b99f MD |
1074 | { |
1075 | if (vstack_push(stack)) { | |
1076 | ret = -EINVAL; | |
1077 | goto end; | |
1078 | } | |
1079 | vstack_ax(stack)->type = REG_PTR; | |
1080 | vstack_ax(stack)->load.type = LOAD_ROOT_CONTEXT; | |
1081 | next_pc += sizeof(struct load_op); | |
1082 | break; | |
1083 | } | |
80c2a69a | 1084 | case BYTECODE_OP_GET_APP_CONTEXT_ROOT: |
3834b99f MD |
1085 | { |
1086 | if (vstack_push(stack)) { | |
1087 | ret = -EINVAL; | |
1088 | goto end; | |
1089 | } | |
1090 | vstack_ax(stack)->type = REG_PTR; | |
1091 | vstack_ax(stack)->load.type = LOAD_ROOT_APP_CONTEXT; | |
1092 | next_pc += sizeof(struct load_op); | |
1093 | break; | |
1094 | } | |
80c2a69a | 1095 | case BYTECODE_OP_GET_PAYLOAD_ROOT: |
3834b99f MD |
1096 | { |
1097 | if (vstack_push(stack)) { | |
1098 | ret = -EINVAL; | |
1099 | goto end; | |
1100 | } | |
1101 | vstack_ax(stack)->type = REG_PTR; | |
1102 | vstack_ax(stack)->load.type = LOAD_ROOT_PAYLOAD; | |
1103 | next_pc += sizeof(struct load_op); | |
1104 | break; | |
1105 | } | |
1106 | ||
80c2a69a | 1107 | case BYTECODE_OP_LOAD_FIELD: |
3834b99f MD |
1108 | { |
1109 | struct load_op *insn = (struct load_op *) pc; | |
1110 | ||
1111 | WARN_ON_ONCE(vstack_ax(stack)->type != REG_PTR); | |
1112 | /* Pop 1, push 1 */ | |
1113 | ret = specialize_load_field(vstack_ax(stack), insn); | |
1114 | if (ret) | |
1115 | goto end; | |
1116 | ||
1117 | next_pc += sizeof(struct load_op); | |
1118 | break; | |
1119 | } | |
1120 | ||
80c2a69a FD |
1121 | case BYTECODE_OP_LOAD_FIELD_S8: |
1122 | case BYTECODE_OP_LOAD_FIELD_S16: | |
1123 | case BYTECODE_OP_LOAD_FIELD_S32: | |
1124 | case BYTECODE_OP_LOAD_FIELD_S64: | |
1125 | case BYTECODE_OP_LOAD_FIELD_U8: | |
1126 | case BYTECODE_OP_LOAD_FIELD_U16: | |
1127 | case BYTECODE_OP_LOAD_FIELD_U32: | |
1128 | case BYTECODE_OP_LOAD_FIELD_U64: | |
3834b99f MD |
1129 | { |
1130 | /* Pop 1, push 1 */ | |
1131 | vstack_ax(stack)->type = REG_S64; | |
1132 | next_pc += sizeof(struct load_op); | |
1133 | break; | |
1134 | } | |
1135 | ||
80c2a69a FD |
1136 | case BYTECODE_OP_LOAD_FIELD_STRING: |
1137 | case BYTECODE_OP_LOAD_FIELD_SEQUENCE: | |
3834b99f MD |
1138 | { |
1139 | /* Pop 1, push 1 */ | |
1140 | vstack_ax(stack)->type = REG_STRING; | |
1141 | next_pc += sizeof(struct load_op); | |
1142 | break; | |
1143 | } | |
1144 | ||
80c2a69a | 1145 | case BYTECODE_OP_LOAD_FIELD_DOUBLE: |
3834b99f MD |
1146 | { |
1147 | /* Pop 1, push 1 */ | |
1148 | vstack_ax(stack)->type = REG_DOUBLE; | |
1149 | next_pc += sizeof(struct load_op); | |
1150 | break; | |
1151 | } | |
1152 | ||
80c2a69a | 1153 | case BYTECODE_OP_GET_SYMBOL: |
3834b99f MD |
1154 | { |
1155 | struct load_op *insn = (struct load_op *) pc; | |
1156 | ||
1157 | dbg_printk("op get symbol\n"); | |
1158 | switch (vstack_ax(stack)->load.type) { | |
1159 | case LOAD_OBJECT: | |
80c2a69a | 1160 | printk(KERN_WARNING "LTTng: bytecode: Nested fields not implemented yet.\n"); |
3834b99f MD |
1161 | ret = -EINVAL; |
1162 | goto end; | |
1163 | case LOAD_ROOT_CONTEXT: | |
1164 | /* Lookup context field. */ | |
2dfda770 | 1165 | ret = specialize_context_lookup(ctx, bytecode, insn, |
3834b99f MD |
1166 | &vstack_ax(stack)->load); |
1167 | if (ret) | |
1168 | goto end; | |
1169 | break; | |
1170 | case LOAD_ROOT_APP_CONTEXT: | |
1171 | ret = -EINVAL; | |
1172 | goto end; | |
1173 | case LOAD_ROOT_PAYLOAD: | |
1174 | /* Lookup event payload field. */ | |
2dfda770 | 1175 | ret = specialize_payload_lookup(event_desc, |
3834b99f MD |
1176 | bytecode, insn, |
1177 | &vstack_ax(stack)->load); | |
1178 | if (ret) | |
1179 | goto end; | |
1180 | break; | |
1181 | } | |
1182 | next_pc += sizeof(struct load_op) + sizeof(struct get_symbol); | |
1183 | break; | |
1184 | } | |
1185 | ||
80c2a69a | 1186 | case BYTECODE_OP_GET_SYMBOL_FIELD: |
3834b99f MD |
1187 | { |
1188 | /* Always generated by specialize phase. */ | |
1189 | ret = -EINVAL; | |
1190 | goto end; | |
1191 | } | |
1192 | ||
80c2a69a | 1193 | case BYTECODE_OP_GET_INDEX_U16: |
3834b99f MD |
1194 | { |
1195 | struct load_op *insn = (struct load_op *) pc; | |
1196 | struct get_index_u16 *index = (struct get_index_u16 *) insn->data; | |
1197 | ||
1198 | dbg_printk("op get index u16\n"); | |
1199 | /* Pop 1, push 1 */ | |
1200 | ret = specialize_get_index(bytecode, insn, index->index, | |
1201 | vstack_ax(stack), sizeof(*index)); | |
1202 | if (ret) | |
1203 | goto end; | |
1204 | next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16); | |
1205 | break; | |
1206 | } | |
1207 | ||
80c2a69a | 1208 | case BYTECODE_OP_GET_INDEX_U64: |
3834b99f MD |
1209 | { |
1210 | struct load_op *insn = (struct load_op *) pc; | |
1211 | struct get_index_u64 *index = (struct get_index_u64 *) insn->data; | |
1212 | ||
1213 | dbg_printk("op get index u64\n"); | |
1214 | /* Pop 1, push 1 */ | |
1215 | ret = specialize_get_index(bytecode, insn, index->index, | |
1216 | vstack_ax(stack), sizeof(*index)); | |
1217 | if (ret) | |
1218 | goto end; | |
1219 | next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64); | |
1220 | break; | |
1221 | } | |
1222 | ||
07dfc1d0 MD |
1223 | } |
1224 | } | |
1225 | end: | |
1226 | return ret; | |
1227 | } |