Rename lttng_condition_event_rule to lttng_condition_on_event
[lttng-tools.git] / src / common / bytecode / bytecode.c
CommitLineData
0ae3cfc6
SM
1/*
2 * Copyright 2020 EfficiOS, Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#include "bytecode.h"
9
10#include <errno.h>
11
12#include "common/align.h"
13
14#define INIT_ALLOC_SIZE 4
15
43a35373
JG
16static inline
17int get_count_order(unsigned int count)
0ae3cfc6
SM
18{
19 int order;
20
21 order = lttng_fls(count) - 1;
22 if (count & (count - 1))
23 order++;
24 return order;
25}
26
27LTTNG_HIDDEN
2b00d462 28int bytecode_init(struct lttng_bytecode_alloc **fb)
0ae3cfc6
SM
29{
30 uint32_t alloc_len;
31
2b00d462 32 alloc_len = sizeof(struct lttng_bytecode_alloc) + INIT_ALLOC_SIZE;
0ae3cfc6
SM
33 *fb = calloc(alloc_len, 1);
34 if (!*fb) {
35 return -ENOMEM;
36 } else {
37 (*fb)->alloc_len = alloc_len;
38 return 0;
39 }
40}
41
d0cede25 42static
2b00d462 43int32_t bytecode_reserve(struct lttng_bytecode_alloc **fb, uint32_t align, uint32_t len)
0ae3cfc6
SM
44{
45 int32_t ret;
46 uint32_t padding = offset_align((*fb)->b.len, align);
47 uint32_t new_len = (*fb)->b.len + padding + len;
2b00d462 48 uint32_t new_alloc_len = sizeof(struct lttng_bytecode_alloc) + new_len;
0ae3cfc6
SM
49 uint32_t old_alloc_len = (*fb)->alloc_len;
50
51 if (new_len > LTTNG_FILTER_MAX_LEN)
52 return -EINVAL;
53
54 if (new_alloc_len > old_alloc_len) {
2b00d462 55 struct lttng_bytecode_alloc *newptr;
0ae3cfc6
SM
56
57 new_alloc_len =
58 max_t(uint32_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
59 newptr = realloc(*fb, new_alloc_len);
60 if (!newptr)
61 return -ENOMEM;
62 *fb = newptr;
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;
66 }
67 (*fb)->b.len += padding;
68 ret = (*fb)->b.len;
69 (*fb)->b.len += len;
70 return ret;
71}
72
73LTTNG_HIDDEN
2b00d462 74int bytecode_push(struct lttng_bytecode_alloc **fb, const void *data,
0ae3cfc6
SM
75 uint32_t align, uint32_t len)
76{
77 int32_t offset;
78
79 offset = bytecode_reserve(fb, align, len);
80 if (offset < 0)
81 return offset;
82 memcpy(&(*fb)->b.data[offset], data, len);
83 return 0;
84}
85
86LTTNG_HIDDEN
2b00d462 87int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
0ae3cfc6
SM
88 struct logical_op *data,
89 uint32_t align, uint32_t len,
90 uint16_t *skip_offset)
91{
92 int32_t offset;
93
94 offset = bytecode_reserve(fb, align, len);
95 if (offset < 0)
96 return offset;
97 memcpy(&(*fb)->b.data[offset], data, len);
98 *skip_offset =
99 (void *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset
100 - (void *) &(*fb)->b.data[0];
101 return 0;
102}
763f0d4c 103
6afbab01
SM
104LTTNG_HIDDEN
105int bytecode_push_get_payload_root(struct lttng_bytecode_alloc **bytecode)
106{
107 int ret;
108 struct load_op *insn;
109 const uint32_t insn_len = sizeof(struct load_op);
110
111 insn = calloc(insn_len, 1);
112 if (!insn) {
113 ret = -ENOMEM;
114 goto end;
115 }
116
117 insn->op = BYTECODE_OP_GET_PAYLOAD_ROOT;
118 ret = bytecode_push(bytecode, insn, 1, insn_len);
119 free(insn);
120end:
121 return ret;
122}
123
124LTTNG_HIDDEN
125int bytecode_push_get_context_root(struct lttng_bytecode_alloc **bytecode)
126{
127 int ret;
128 struct load_op *insn;
129 const uint32_t insn_len = sizeof(struct load_op);
130
131 insn = calloc(insn_len, 1);
132 if (!insn) {
133 ret = -ENOMEM;
134 goto end;
135 }
136
137 insn->op = BYTECODE_OP_GET_CONTEXT_ROOT;
138 ret = bytecode_push(bytecode, insn, 1, insn_len);
139 free(insn);
140end:
141 return ret;
142}
143
144LTTNG_HIDDEN
145int bytecode_push_get_app_context_root(struct lttng_bytecode_alloc **bytecode)
146{
147 int ret;
148 struct load_op *insn;
149 const uint32_t insn_len = sizeof(struct load_op);
150
151 insn = calloc(insn_len, 1);
152 if (!insn) {
153 ret = -ENOMEM;
154 goto end;
155 }
156
157 insn->op = BYTECODE_OP_GET_APP_CONTEXT_ROOT;
158 ret = bytecode_push(bytecode, insn, 1, insn_len);
159 free(insn);
160end:
161 return ret;
162}
163
164LTTNG_HIDDEN
165int bytecode_push_get_index_u64(struct lttng_bytecode_alloc **bytecode,
166 uint64_t index)
167{
168 int ret;
169 struct load_op *insn;
170 struct get_index_u64 index_op_data;
171 const uint32_t insn_len =
172 sizeof(struct load_op) + sizeof(struct get_index_u64);
173
174 insn = calloc(insn_len, 1);
175 if (!insn) {
176 ret = -ENOMEM;
177 goto end;
178 }
179
180 insn->op = BYTECODE_OP_GET_INDEX_U64;
181 index_op_data.index = index;
182 memcpy(insn->data, &index_op_data, sizeof(index));
183 ret = bytecode_push(bytecode, insn, 1, insn_len);
184
185 free(insn);
186end:
187 return ret;
188}
189
190LTTNG_HIDDEN
191int bytecode_push_get_symbol(struct lttng_bytecode_alloc **bytecode,
192 struct lttng_bytecode_alloc **bytecode_reloc,
193 const char *symbol)
194{
195 int ret;
196 struct load_op *insn;
197 struct get_symbol symbol_offset;
198 uint32_t reloc_offset_u32;
199 uint16_t reloc_offset;
200 uint32_t bytecode_reloc_offset_u32;
201 const uint32_t insn_len =
202 sizeof(struct load_op) + sizeof(struct get_symbol);
203
204 insn = calloc(insn_len, 1);
205 if (!insn) {
206 ret = -ENOMEM;
207 goto end;
208 }
209
210 insn->op = BYTECODE_OP_GET_SYMBOL;
211
212 /*
213 * Get offset in the reloc portion at which the symbol name
214 * will end up at (GET_SYMBOL's operand points there).
215 */
216 bytecode_reloc_offset_u32 = bytecode_get_len(&(*bytecode_reloc)->b) +
217 sizeof(reloc_offset);
218 symbol_offset.offset = (uint16_t) bytecode_reloc_offset_u32;
219 memcpy(insn->data, &symbol_offset, sizeof(symbol_offset));
220
221 /*
222 * Get offset in the bytecode where the opcode will end up at,
223 * the reloc offset points to it.
224 */
225 reloc_offset_u32 = bytecode_get_len(&(*bytecode)->b);
226 if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
227 ret = -EINVAL;
228 goto end;
229 }
230 reloc_offset = (uint16_t) reloc_offset_u32;
231
232 /* Append op in bytecode. */
233 ret = bytecode_push(bytecode, insn, 1, insn_len);
234 if (ret) {
235 goto end;
236 }
237
238 /* Append reloc offset. */
239 ret = bytecode_push(bytecode_reloc, &reloc_offset,
240 1, sizeof(reloc_offset));
241 if (ret) {
242 goto end;
243 }
244
245 /* Append symbol name. */
246 ret = bytecode_push(bytecode_reloc, symbol, 1, strlen(symbol) + 1);
247
248end:
249 free(insn);
250 return ret;
251}
252
763f0d4c
SM
253/*
254 * Allocate an lttng_bytecode object and copy the given original bytecode.
255 *
256 * Return allocated bytecode or NULL on error.
257 */
258LTTNG_HIDDEN
2b00d462
SM
259struct lttng_bytecode *lttng_bytecode_copy(
260 const struct lttng_bytecode *orig_f)
763f0d4c 261{
2b00d462 262 struct lttng_bytecode *bytecode = NULL;
763f0d4c
SM
263
264 bytecode = zmalloc(sizeof(*bytecode) + orig_f->len);
265 if (!bytecode) {
266 goto error;
267 }
268
269 memcpy(bytecode, orig_f, sizeof(*bytecode) + orig_f->len);
270
271error:
272 return bytecode;
273}
This page took 0.033471 seconds and 4 git commands to generate.