2 * Copyright 2020 EfficiOS, Inc.
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include "bytecode.hpp"
13 #include "common/align.hpp"
15 #define INIT_ALLOC_SIZE 4
18 int get_count_order(unsigned int count
)
22 order
= lttng_fls(count
) - 1;
23 if (count
& (count
- 1))
28 int bytecode_init(struct lttng_bytecode_alloc
**fb
)
32 alloc_len
= sizeof(struct lttng_bytecode_alloc
) + INIT_ALLOC_SIZE
;
33 *fb
= (lttng_bytecode_alloc
*) calloc(alloc_len
, 1);
37 (*fb
)->alloc_len
= alloc_len
;
43 int32_t bytecode_reserve(struct lttng_bytecode_alloc
**fb
, uint32_t align
, uint32_t len
)
46 uint32_t padding
= lttng_offset_align((*fb
)->b
.len
, align
);
47 uint32_t new_len
= (*fb
)->b
.len
+ padding
+ len
;
48 uint32_t new_alloc_len
= sizeof(struct lttng_bytecode_alloc
) + new_len
;
49 uint32_t old_alloc_len
= (*fb
)->alloc_len
;
51 if (new_len
> LTTNG_FILTER_MAX_LEN
)
54 if (new_alloc_len
> old_alloc_len
) {
55 struct lttng_bytecode_alloc
*newptr
;
58 std::max(1U << get_count_order(new_alloc_len
), old_alloc_len
<< 1);
59 newptr
= (lttng_bytecode_alloc
*) realloc(*fb
, new_alloc_len
);
63 /* We zero directly the memory from start of allocation. */
64 memset(&((char *) *fb
)[old_alloc_len
], 0, new_alloc_len
- old_alloc_len
);
65 (*fb
)->alloc_len
= new_alloc_len
;
67 (*fb
)->b
.len
+= padding
;
73 int bytecode_push(struct lttng_bytecode_alloc
**fb
, const void *data
,
74 uint32_t align
, uint32_t len
)
78 offset
= bytecode_reserve(fb
, align
, len
);
81 memcpy(&(*fb
)->b
.data
[offset
], data
, len
);
85 int bytecode_push_logical(struct lttng_bytecode_alloc
**fb
,
86 struct logical_op
*data
,
87 uint32_t align
, uint32_t len
,
88 uint16_t *skip_offset
)
92 offset
= bytecode_reserve(fb
, align
, len
);
95 memcpy(&(*fb
)->b
.data
[offset
], data
, len
);
97 (char *) &((struct logical_op
*) &(*fb
)->b
.data
[offset
])->skip_offset
98 - (char *) &(*fb
)->b
.data
[0];
102 int bytecode_push_get_payload_root(struct lttng_bytecode_alloc
**bytecode
)
105 struct load_op
*insn
;
106 const uint32_t insn_len
= sizeof(struct load_op
);
108 insn
= (load_op
*) calloc(insn_len
, 1);
114 insn
->op
= BYTECODE_OP_GET_PAYLOAD_ROOT
;
115 ret
= bytecode_push(bytecode
, insn
, 1, insn_len
);
121 int bytecode_push_get_context_root(struct lttng_bytecode_alloc
**bytecode
)
124 struct load_op
*insn
;
125 const uint32_t insn_len
= sizeof(struct load_op
);
127 insn
= (load_op
*) calloc(insn_len
, 1);
133 insn
->op
= BYTECODE_OP_GET_CONTEXT_ROOT
;
134 ret
= bytecode_push(bytecode
, insn
, 1, insn_len
);
140 int bytecode_push_get_app_context_root(struct lttng_bytecode_alloc
**bytecode
)
143 struct load_op
*insn
;
144 const uint32_t insn_len
= sizeof(struct load_op
);
146 insn
= (load_op
*) calloc(insn_len
, 1);
152 insn
->op
= BYTECODE_OP_GET_APP_CONTEXT_ROOT
;
153 ret
= bytecode_push(bytecode
, insn
, 1, insn_len
);
159 int bytecode_push_get_index_u64(struct lttng_bytecode_alloc
**bytecode
,
163 struct load_op
*insn
;
164 struct get_index_u64 index_op_data
;
165 const uint32_t insn_len
=
166 sizeof(struct load_op
) + sizeof(struct get_index_u64
);
168 insn
= (load_op
*) calloc(insn_len
, 1);
174 insn
->op
= BYTECODE_OP_GET_INDEX_U64
;
175 index_op_data
.index
= index
;
176 memcpy(insn
->data
, &index_op_data
, sizeof(index
));
177 ret
= bytecode_push(bytecode
, insn
, 1, insn_len
);
184 int bytecode_push_get_symbol(struct lttng_bytecode_alloc
**bytecode
,
185 struct lttng_bytecode_alloc
**bytecode_reloc
,
189 struct load_op
*insn
;
190 struct get_symbol symbol_offset
;
191 uint32_t reloc_offset_u32
;
192 uint16_t reloc_offset
;
193 uint32_t bytecode_reloc_offset_u32
;
194 const uint32_t insn_len
=
195 sizeof(struct load_op
) + sizeof(struct get_symbol
);
197 insn
= (load_op
*) calloc(insn_len
, 1);
203 insn
->op
= BYTECODE_OP_GET_SYMBOL
;
206 * Get offset in the reloc portion at which the symbol name
207 * will end up at (GET_SYMBOL's operand points there).
209 bytecode_reloc_offset_u32
= bytecode_get_len(&(*bytecode_reloc
)->b
) +
210 sizeof(reloc_offset
);
211 symbol_offset
.offset
= (uint16_t) bytecode_reloc_offset_u32
;
212 memcpy(insn
->data
, &symbol_offset
, sizeof(symbol_offset
));
215 * Get offset in the bytecode where the opcode will end up at,
216 * the reloc offset points to it.
218 reloc_offset_u32
= bytecode_get_len(&(*bytecode
)->b
);
219 if (reloc_offset_u32
> LTTNG_FILTER_MAX_LEN
- 1) {
223 reloc_offset
= (uint16_t) reloc_offset_u32
;
225 /* Append op in bytecode. */
226 ret
= bytecode_push(bytecode
, insn
, 1, insn_len
);
231 /* Append reloc offset. */
232 ret
= bytecode_push(bytecode_reloc
, &reloc_offset
,
233 1, sizeof(reloc_offset
));
238 /* Append symbol name. */
239 ret
= bytecode_push(bytecode_reloc
, symbol
, 1, strlen(symbol
) + 1);
247 * Allocate an lttng_bytecode object and copy the given original bytecode.
249 * Return allocated bytecode or NULL on error.
251 struct lttng_bytecode
*lttng_bytecode_copy(
252 const struct lttng_bytecode
*orig_f
)
254 struct lttng_bytecode
*bytecode
= NULL
;
256 bytecode
= (lttng_bytecode
*) zmalloc(sizeof(*bytecode
) + orig_f
->len
);
261 memcpy(bytecode
, orig_f
, sizeof(*bytecode
) + orig_f
->len
);