Relicence all source and header files included in LGPL code
[lttng-tools.git] / src / common / bytecode / bytecode.cpp
CommitLineData
0ae3cfc6
SM
1/*
2 * Copyright 2020 EfficiOS, Inc.
3 *
c922647d 4 * SPDX-License-Identifier: LGPL-2.1-only
0ae3cfc6
SM
5 *
6 */
7
8#include "bytecode.h"
9
10#include <errno.h>
d5552a4c 11#include <algorithm>
0ae3cfc6
SM
12
13#include "common/align.h"
14
15#define INIT_ALLOC_SIZE 4
16
43a35373
JG
17static inline
18int get_count_order(unsigned int count)
0ae3cfc6
SM
19{
20 int order;
21
22 order = lttng_fls(count) - 1;
23 if (count & (count - 1))
24 order++;
25 return order;
26}
27
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;
d5552a4c 33 *fb = (lttng_bytecode_alloc *) calloc(alloc_len, 1);
0ae3cfc6
SM
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;
1cbd136b 46 uint32_t padding = lttng_offset_align((*fb)->b.len, align);
0ae3cfc6 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 =
d5552a4c
SM
58 std::max(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
59 newptr = (lttng_bytecode_alloc *) realloc(*fb, new_alloc_len);
0ae3cfc6
SM
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
2b00d462 73int bytecode_push(struct lttng_bytecode_alloc **fb, const void *data,
0ae3cfc6
SM
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
2b00d462 85int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
0ae3cfc6
SM
86 struct logical_op *data,
87 uint32_t align, uint32_t len,
88 uint16_t *skip_offset)
89{
90 int32_t offset;
91
92 offset = bytecode_reserve(fb, align, len);
93 if (offset < 0)
94 return offset;
95 memcpy(&(*fb)->b.data[offset], data, len);
96 *skip_offset =
d5552a4c
SM
97 (char *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset
98 - (char *) &(*fb)->b.data[0];
0ae3cfc6
SM
99 return 0;
100}
763f0d4c 101
6afbab01
SM
102int bytecode_push_get_payload_root(struct lttng_bytecode_alloc **bytecode)
103{
104 int ret;
105 struct load_op *insn;
106 const uint32_t insn_len = sizeof(struct load_op);
107
d5552a4c 108 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
109 if (!insn) {
110 ret = -ENOMEM;
111 goto end;
112 }
113
114 insn->op = BYTECODE_OP_GET_PAYLOAD_ROOT;
115 ret = bytecode_push(bytecode, insn, 1, insn_len);
116 free(insn);
117end:
118 return ret;
119}
120
6afbab01
SM
121int bytecode_push_get_context_root(struct lttng_bytecode_alloc **bytecode)
122{
123 int ret;
124 struct load_op *insn;
125 const uint32_t insn_len = sizeof(struct load_op);
126
d5552a4c 127 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
128 if (!insn) {
129 ret = -ENOMEM;
130 goto end;
131 }
132
133 insn->op = BYTECODE_OP_GET_CONTEXT_ROOT;
134 ret = bytecode_push(bytecode, insn, 1, insn_len);
135 free(insn);
136end:
137 return ret;
138}
139
6afbab01
SM
140int bytecode_push_get_app_context_root(struct lttng_bytecode_alloc **bytecode)
141{
142 int ret;
143 struct load_op *insn;
144 const uint32_t insn_len = sizeof(struct load_op);
145
d5552a4c 146 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
147 if (!insn) {
148 ret = -ENOMEM;
149 goto end;
150 }
151
152 insn->op = BYTECODE_OP_GET_APP_CONTEXT_ROOT;
153 ret = bytecode_push(bytecode, insn, 1, insn_len);
154 free(insn);
155end:
156 return ret;
157}
158
6afbab01
SM
159int bytecode_push_get_index_u64(struct lttng_bytecode_alloc **bytecode,
160 uint64_t index)
161{
162 int ret;
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);
167
d5552a4c 168 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
169 if (!insn) {
170 ret = -ENOMEM;
171 goto end;
172 }
173
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);
178
179 free(insn);
180end:
181 return ret;
182}
183
6afbab01
SM
184int bytecode_push_get_symbol(struct lttng_bytecode_alloc **bytecode,
185 struct lttng_bytecode_alloc **bytecode_reloc,
186 const char *symbol)
187{
188 int ret;
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);
196
d5552a4c 197 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
198 if (!insn) {
199 ret = -ENOMEM;
200 goto end;
201 }
202
203 insn->op = BYTECODE_OP_GET_SYMBOL;
204
205 /*
206 * Get offset in the reloc portion at which the symbol name
207 * will end up at (GET_SYMBOL's operand points there).
208 */
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));
213
214 /*
215 * Get offset in the bytecode where the opcode will end up at,
216 * the reloc offset points to it.
217 */
218 reloc_offset_u32 = bytecode_get_len(&(*bytecode)->b);
219 if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
220 ret = -EINVAL;
221 goto end;
222 }
223 reloc_offset = (uint16_t) reloc_offset_u32;
224
225 /* Append op in bytecode. */
226 ret = bytecode_push(bytecode, insn, 1, insn_len);
227 if (ret) {
228 goto end;
229 }
230
231 /* Append reloc offset. */
232 ret = bytecode_push(bytecode_reloc, &reloc_offset,
233 1, sizeof(reloc_offset));
234 if (ret) {
235 goto end;
236 }
237
238 /* Append symbol name. */
239 ret = bytecode_push(bytecode_reloc, symbol, 1, strlen(symbol) + 1);
240
241end:
242 free(insn);
243 return ret;
244}
245
763f0d4c
SM
246/*
247 * Allocate an lttng_bytecode object and copy the given original bytecode.
248 *
249 * Return allocated bytecode or NULL on error.
250 */
2b00d462
SM
251struct lttng_bytecode *lttng_bytecode_copy(
252 const struct lttng_bytecode *orig_f)
763f0d4c 253{
2b00d462 254 struct lttng_bytecode *bytecode = NULL;
763f0d4c 255
d5552a4c 256 bytecode = (lttng_bytecode *) zmalloc(sizeof(*bytecode) + orig_f->len);
763f0d4c
SM
257 if (!bytecode) {
258 goto error;
259 }
260
261 memcpy(bytecode, orig_f, sizeof(*bytecode) + orig_f->len);
262
263error:
264 return bytecode;
265}
This page took 0.037338 seconds and 4 git commands to generate.