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