Tests: Add test to check shared-memory FD leaks after relayd dies
[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
c9e313bc 8#include "bytecode.hpp"
28ab034a 9#include "common/align.hpp"
0ae3cfc6 10
d5552a4c 11#include <algorithm>
28ab034a 12#include <errno.h>
0ae3cfc6
SM
13
14#define INIT_ALLOC_SIZE 4
15
28ab034a 16static inline int get_count_order(unsigned int count)
0ae3cfc6
SM
17{
18 int order;
19
20 order = lttng_fls(count) - 1;
21 if (count & (count - 1))
22 order++;
23 return order;
24}
25
2b00d462 26int bytecode_init(struct lttng_bytecode_alloc **fb)
0ae3cfc6
SM
27{
28 uint32_t alloc_len;
29
2b00d462 30 alloc_len = sizeof(struct lttng_bytecode_alloc) + INIT_ALLOC_SIZE;
d5552a4c 31 *fb = (lttng_bytecode_alloc *) calloc(alloc_len, 1);
0ae3cfc6
SM
32 if (!*fb) {
33 return -ENOMEM;
34 } else {
35 (*fb)->alloc_len = alloc_len;
36 return 0;
37 }
38}
39
28ab034a 40static int32_t bytecode_reserve(struct lttng_bytecode_alloc **fb, uint32_t align, uint32_t len)
0ae3cfc6
SM
41{
42 int32_t ret;
1cbd136b 43 uint32_t padding = lttng_offset_align((*fb)->b.len, align);
0ae3cfc6 44 uint32_t new_len = (*fb)->b.len + padding + len;
2b00d462 45 uint32_t new_alloc_len = sizeof(struct lttng_bytecode_alloc) + new_len;
0ae3cfc6
SM
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) {
2b00d462 52 struct lttng_bytecode_alloc *newptr;
0ae3cfc6 53
28ab034a 54 new_alloc_len = std::max(1U << get_count_order(new_alloc_len), old_alloc_len << 1);
d5552a4c 55 newptr = (lttng_bytecode_alloc *) realloc(*fb, new_alloc_len);
0ae3cfc6
SM
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
28ab034a 69int bytecode_push(struct lttng_bytecode_alloc **fb, const void *data, uint32_t align, uint32_t len)
0ae3cfc6
SM
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
2b00d462 80int bytecode_push_logical(struct lttng_bytecode_alloc **fb,
28ab034a
JG
81 struct logical_op *data,
82 uint32_t align,
83 uint32_t len,
84 uint16_t *skip_offset)
0ae3cfc6
SM
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);
28ab034a
JG
92 *skip_offset = (char *) &((struct logical_op *) &(*fb)->b.data[offset])->skip_offset -
93 (char *) &(*fb)->b.data[0];
0ae3cfc6
SM
94 return 0;
95}
763f0d4c 96
6afbab01
SM
97int 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
d5552a4c 103 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
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);
112end:
113 return ret;
114}
115
6afbab01
SM
116int 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
d5552a4c 122 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
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);
131end:
132 return ret;
133}
134
6afbab01
SM
135int 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
d5552a4c 141 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
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);
150end:
151 return ret;
152}
153
28ab034a 154int bytecode_push_get_index_u64(struct lttng_bytecode_alloc **bytecode, uint64_t index)
6afbab01
SM
155{
156 int ret;
157 struct load_op *insn;
158 struct get_index_u64 index_op_data;
28ab034a 159 const uint32_t insn_len = sizeof(struct load_op) + sizeof(struct get_index_u64);
6afbab01 160
d5552a4c 161 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
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);
173end:
174 return ret;
175}
176
6afbab01 177int bytecode_push_get_symbol(struct lttng_bytecode_alloc **bytecode,
28ab034a
JG
178 struct lttng_bytecode_alloc **bytecode_reloc,
179 const char *symbol)
6afbab01
SM
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;
28ab034a 187 const uint32_t insn_len = sizeof(struct load_op) + sizeof(struct get_symbol);
6afbab01 188
d5552a4c 189 insn = (load_op *) calloc(insn_len, 1);
6afbab01
SM
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 */
28ab034a 201 bytecode_reloc_offset_u32 = bytecode_get_len(&(*bytecode_reloc)->b) + sizeof(reloc_offset);
6afbab01
SM
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. */
28ab034a 223 ret = bytecode_push(bytecode_reloc, &reloc_offset, 1, sizeof(reloc_offset));
6afbab01
SM
224 if (ret) {
225 goto end;
226 }
227
228 /* Append symbol name. */
229 ret = bytecode_push(bytecode_reloc, symbol, 1, strlen(symbol) + 1);
230
231end:
232 free(insn);
233 return ret;
234}
235
763f0d4c
SM
236/*
237 * Allocate an lttng_bytecode object and copy the given original bytecode.
238 *
239 * Return allocated bytecode or NULL on error.
240 */
28ab034a 241struct lttng_bytecode *lttng_bytecode_copy(const struct lttng_bytecode *orig_f)
763f0d4c 242{
28ab034a 243 lttng_bytecode *bytecode = zmalloc<lttng_bytecode>(sizeof(*bytecode) + orig_f->len);
763f0d4c
SM
244 if (!bytecode) {
245 goto error;
246 }
247
248 memcpy(bytecode, orig_f, sizeof(*bytecode) + orig_f->len);
249
250error:
251 return bytecode;
252}
This page took 0.06033 seconds and 4 git commands to generate.