Fix: sessiond: previously created channel cannot be enabled
[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
2b00d462 27int bytecode_init(struct lttng_bytecode_alloc **fb)
0ae3cfc6
SM
28{
29 uint32_t alloc_len;
30
2b00d462 31 alloc_len = sizeof(struct lttng_bytecode_alloc) + INIT_ALLOC_SIZE;
0ae3cfc6
SM
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
d0cede25 41static
2b00d462 42int32_t bytecode_reserve(struct lttng_bytecode_alloc **fb, uint32_t align, uint32_t len)
0ae3cfc6
SM
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;
2b00d462 47 uint32_t new_alloc_len = sizeof(struct lttng_bytecode_alloc) + new_len;
0ae3cfc6
SM
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) {
2b00d462 54 struct lttng_bytecode_alloc *newptr;
0ae3cfc6
SM
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
2b00d462 72int bytecode_push(struct lttng_bytecode_alloc **fb, const void *data,
0ae3cfc6
SM
73 uint32_t align, uint32_t len)
74{
75 int32_t offset;
76
77 offset = bytecode_reserve(fb, align, len);
78 if (offset < 0)
79 return offset;
80 memcpy(&(*fb)->b.data[offset], data, len);
81 return 0;
82}
83
2b00d462 84int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
0ae3cfc6
SM
85 struct logical_op *data,
86 uint32_t align, uint32_t len,
87 uint16_t *skip_offset)
88{
89 int32_t offset;
90
91 offset = bytecode_reserve(fb, align, len);
92 if (offset < 0)
93 return offset;
94 memcpy(&(*fb)->b.data[offset], data, len);
95 *skip_offset =
96 (void *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset
97 - (void *) &(*fb)->b.data[0];
98 return 0;
99}
763f0d4c 100
6afbab01
SM
101int bytecode_push_get_payload_root(struct lttng_bytecode_alloc **bytecode)
102{
103 int ret;
104 struct load_op *insn;
105 const uint32_t insn_len = sizeof(struct load_op);
106
107 insn = calloc(insn_len, 1);
108 if (!insn) {
109 ret = -ENOMEM;
110 goto end;
111 }
112
113 insn->op = BYTECODE_OP_GET_PAYLOAD_ROOT;
114 ret = bytecode_push(bytecode, insn, 1, insn_len);
115 free(insn);
116end:
117 return ret;
118}
119
6afbab01
SM
120int bytecode_push_get_context_root(struct lttng_bytecode_alloc **bytecode)
121{
122 int ret;
123 struct load_op *insn;
124 const uint32_t insn_len = sizeof(struct load_op);
125
126 insn = calloc(insn_len, 1);
127 if (!insn) {
128 ret = -ENOMEM;
129 goto end;
130 }
131
132 insn->op = BYTECODE_OP_GET_CONTEXT_ROOT;
133 ret = bytecode_push(bytecode, insn, 1, insn_len);
134 free(insn);
135end:
136 return ret;
137}
138
6afbab01
SM
139int bytecode_push_get_app_context_root(struct lttng_bytecode_alloc **bytecode)
140{
141 int ret;
142 struct load_op *insn;
143 const uint32_t insn_len = sizeof(struct load_op);
144
145 insn = calloc(insn_len, 1);
146 if (!insn) {
147 ret = -ENOMEM;
148 goto end;
149 }
150
151 insn->op = BYTECODE_OP_GET_APP_CONTEXT_ROOT;
152 ret = bytecode_push(bytecode, insn, 1, insn_len);
153 free(insn);
154end:
155 return ret;
156}
157
6afbab01
SM
158int bytecode_push_get_index_u64(struct lttng_bytecode_alloc **bytecode,
159 uint64_t index)
160{
161 int ret;
162 struct load_op *insn;
163 struct get_index_u64 index_op_data;
164 const uint32_t insn_len =
165 sizeof(struct load_op) + sizeof(struct get_index_u64);
166
167 insn = calloc(insn_len, 1);
168 if (!insn) {
169 ret = -ENOMEM;
170 goto end;
171 }
172
173 insn->op = BYTECODE_OP_GET_INDEX_U64;
174 index_op_data.index = index;
175 memcpy(insn->data, &index_op_data, sizeof(index));
176 ret = bytecode_push(bytecode, insn, 1, insn_len);
177
178 free(insn);
179end:
180 return ret;
181}
182
6afbab01
SM
183int bytecode_push_get_symbol(struct lttng_bytecode_alloc **bytecode,
184 struct lttng_bytecode_alloc **bytecode_reloc,
185 const char *symbol)
186{
187 int ret;
188 struct load_op *insn;
189 struct get_symbol symbol_offset;
190 uint32_t reloc_offset_u32;
191 uint16_t reloc_offset;
192 uint32_t bytecode_reloc_offset_u32;
193 const uint32_t insn_len =
194 sizeof(struct load_op) + sizeof(struct get_symbol);
195
196 insn = calloc(insn_len, 1);
197 if (!insn) {
198 ret = -ENOMEM;
199 goto end;
200 }
201
202 insn->op = BYTECODE_OP_GET_SYMBOL;
203
204 /*
205 * Get offset in the reloc portion at which the symbol name
206 * will end up at (GET_SYMBOL's operand points there).
207 */
208 bytecode_reloc_offset_u32 = bytecode_get_len(&(*bytecode_reloc)->b) +
209 sizeof(reloc_offset);
210 symbol_offset.offset = (uint16_t) bytecode_reloc_offset_u32;
211 memcpy(insn->data, &symbol_offset, sizeof(symbol_offset));
212
213 /*
214 * Get offset in the bytecode where the opcode will end up at,
215 * the reloc offset points to it.
216 */
217 reloc_offset_u32 = bytecode_get_len(&(*bytecode)->b);
218 if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
219 ret = -EINVAL;
220 goto end;
221 }
222 reloc_offset = (uint16_t) reloc_offset_u32;
223
224 /* Append op in bytecode. */
225 ret = bytecode_push(bytecode, insn, 1, insn_len);
226 if (ret) {
227 goto end;
228 }
229
230 /* Append reloc offset. */
231 ret = bytecode_push(bytecode_reloc, &reloc_offset,
232 1, sizeof(reloc_offset));
233 if (ret) {
234 goto end;
235 }
236
237 /* Append symbol name. */
238 ret = bytecode_push(bytecode_reloc, symbol, 1, strlen(symbol) + 1);
239
240end:
241 free(insn);
242 return ret;
243}
244
763f0d4c
SM
245/*
246 * Allocate an lttng_bytecode object and copy the given original bytecode.
247 *
248 * Return allocated bytecode or NULL on error.
249 */
2b00d462
SM
250struct lttng_bytecode *lttng_bytecode_copy(
251 const struct lttng_bytecode *orig_f)
763f0d4c 252{
2b00d462 253 struct lttng_bytecode *bytecode = NULL;
763f0d4c
SM
254
255 bytecode = zmalloc(sizeof(*bytecode) + orig_f->len);
256 if (!bytecode) {
257 goto error;
258 }
259
260 memcpy(bytecode, orig_f, sizeof(*bytecode) + orig_f->len);
261
262error:
263 return bytecode;
264}
This page took 0.03439 seconds and 4 git commands to generate.