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