Fix: validate that array expression contains constant
[lttng-tools.git] / src / common / event-expr-to-bytecode.c
1 /*
2 * Copyright 2020 EfficiOS, Inc.
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "event-expr-to-bytecode.h"
9
10 #include <stdio.h>
11 #include <lttng/event-expr.h>
12 #include <common/bytecode/bytecode.h>
13 #include <common/error.h>
14
15 static
16 int event_expr_to_bytecode_recursive(const struct lttng_event_expr *expr,
17 struct lttng_bytecode_alloc **bytecode,
18 struct lttng_bytecode_alloc **bytecode_reloc)
19 {
20 int status;
21 enum lttng_event_expr_status event_expr_status;
22
23 switch (lttng_event_expr_get_type(expr)) {
24 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
25 {
26 const char *name;
27
28 status = bytecode_push_get_payload_root(bytecode);
29 if (status) {
30 ERR("Failed to get payload root from bytecode");
31 goto end;
32 }
33
34 name = lttng_event_expr_event_payload_field_get_name(expr);
35 if (!name) {
36 ERR("Failed to get payload field name from event expression");
37 status = -1;
38 goto end;
39 }
40
41 status = bytecode_push_get_symbol(bytecode, bytecode_reloc, name);
42 if (status) {
43 ERR("Failed to push 'get symbol %s' in bytecode", name);
44 goto end;
45 }
46
47 break;
48 }
49 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
50 {
51 const char *name;
52
53 status = bytecode_push_get_context_root(bytecode);
54 if (status) {
55 ERR("Failed to get context root from bytecode");
56 goto end;
57 }
58
59 name = lttng_event_expr_channel_context_field_get_name(expr);
60 if (!name) {
61 ERR("Failed to get channel context field name from event expression");
62 status = -1;
63 goto end;
64 }
65
66 status = bytecode_push_get_symbol(bytecode, bytecode_reloc, name);
67 if (status) {
68 ERR("Failed to push 'get symbol %s' in bytecode", name);
69 goto end;
70 }
71
72 break;
73 }
74 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
75 {
76 int ret;
77 char *name = NULL;
78 const char *provider_name, *type_name;
79
80 status = bytecode_push_get_app_context_root(bytecode);
81 if (status) {
82 ERR("Failed to get application context root from bytecode");
83 goto end;
84 }
85
86 provider_name = lttng_event_expr_app_specific_context_field_get_provider_name(
87 expr);
88 if (!provider_name) {
89 ERR("Failed to get application context provider name from event expression");
90 status = -1;
91 goto end;
92 }
93
94 type_name = lttng_event_expr_app_specific_context_field_get_type_name(
95 expr);
96 if (!type_name) {
97 ERR("Failed to get application context type name from event expression");
98 status = -1;
99 goto end;
100 }
101
102 /*
103 * Reconstitute the app context field name from its two parts.
104 */
105 ret = asprintf(&name, "%s:%s", provider_name, type_name);
106 if (ret < 0) {
107 PERROR("Failed to format application specific context: provider_name = '%s', type_name = '%s'",
108 provider_name, type_name);
109 status = -1;
110 goto end;
111 }
112
113 status = bytecode_push_get_symbol(
114 bytecode, bytecode_reloc, name);
115 free(name);
116 if (status) {
117 ERR("Failed to push 'get symbol %s:%s' in bytecode",
118 provider_name, type_name);
119 goto end;
120 }
121
122 break;
123 }
124 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
125 {
126 unsigned int index;
127 const struct lttng_event_expr *parent;
128
129 parent = lttng_event_expr_array_field_element_get_parent_expr(
130 expr);
131 if (!parent) {
132 ERR("Failed to get parent expression from array event expression");
133 status = -1;
134 goto end;
135 }
136
137 status = event_expr_to_bytecode_recursive(
138 parent, bytecode, bytecode_reloc);
139 if (status) {
140 goto end;
141 }
142
143 event_expr_status = lttng_event_expr_array_field_element_get_index(
144 expr, &index);
145 if (event_expr_status != LTTNG_EVENT_EXPR_STATUS_OK) {
146 ERR("Failed to get array field element index from event expression");
147 status = -1;
148 goto end;
149 }
150
151 status = bytecode_push_get_index_u64(bytecode, index);
152 if (status) {
153 ERR("Failed to push 'get index %u' in bytecode", index);
154 goto end;
155 }
156
157 break;
158 }
159 default:
160 abort();
161 }
162
163 status = 0;
164 end:
165 return status;
166 }
167
168 LTTNG_HIDDEN
169 int lttng_event_expr_to_bytecode(const struct lttng_event_expr *expr,
170 struct lttng_bytecode **bytecode_out)
171 {
172 int status;
173 struct return_op ret_insn;
174 struct lttng_bytecode_alloc *bytecode = NULL;
175 struct lttng_bytecode_alloc *bytecode_reloc = NULL;
176
177 status = bytecode_init(&bytecode);
178 if (status) {
179 ERR("Failed to initialize bytecode");
180 goto end;
181 }
182
183 status = bytecode_init(&bytecode_reloc);
184 if (status) {
185 ERR("Failed to initialize relocation bytecode");
186 goto end;
187 }
188
189 status = event_expr_to_bytecode_recursive(
190 expr, &bytecode, &bytecode_reloc);
191 if (status) {
192 /* Errors already logged. */
193 goto end;
194 }
195
196 ret_insn.op = BYTECODE_OP_RETURN;
197 bytecode_push(&bytecode, &ret_insn, 1, sizeof(ret_insn));
198
199 /* Append symbol table to bytecode. */
200 bytecode->b.reloc_table_offset = bytecode_get_len(&bytecode->b);
201 status = bytecode_push(&bytecode, bytecode_reloc->b.data, 1,
202 bytecode_get_len(&bytecode_reloc->b));
203 if (status) {
204 ERR("Failed to push symbol table to bytecode");
205 goto end;
206 }
207
208 /* Copy the `lttng_bytecode` out of the `lttng_bytecode_alloc`. */
209 *bytecode_out = lttng_bytecode_copy(&bytecode->b);
210 if (!*bytecode_out) {
211 status = -1;
212 goto end;
213 }
214
215 end:
216 if (bytecode) {
217 free(bytecode);
218 }
219
220 if (bytecode_reloc) {
221 free(bytecode_reloc);
222 }
223
224 return status;
225 }
This page took 0.032841 seconds and 4 git commands to generate.