Add hostname to env
[lttng-ust.git] / liblttng-ust / lttng-filter.c
CommitLineData
2d78951a
MD
1/*
2 * lttng-filter.c
3 *
4 * LTTng UST filter code.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
97b58163 23#include "lttng-filter.h"
cd54f6d9
MD
24
25static const char *opnames[] = {
26 [ FILTER_OP_UNKNOWN ] = "UNKNOWN",
27
28 [ FILTER_OP_RETURN ] = "RETURN",
29
30 /* binary */
31 [ FILTER_OP_MUL ] = "MUL",
32 [ FILTER_OP_DIV ] = "DIV",
33 [ FILTER_OP_MOD ] = "MOD",
34 [ FILTER_OP_PLUS ] = "PLUS",
35 [ FILTER_OP_MINUS ] = "MINUS",
36 [ FILTER_OP_RSHIFT ] = "RSHIFT",
37 [ FILTER_OP_LSHIFT ] = "LSHIFT",
38 [ FILTER_OP_BIN_AND ] = "BIN_AND",
39 [ FILTER_OP_BIN_OR ] = "BIN_OR",
40 [ FILTER_OP_BIN_XOR ] = "BIN_XOR",
226106c0
MD
41
42 /* binary comparators */
cd54f6d9
MD
43 [ FILTER_OP_EQ ] = "EQ",
44 [ FILTER_OP_NE ] = "NE",
45 [ FILTER_OP_GT ] = "GT",
46 [ FILTER_OP_LT ] = "LT",
47 [ FILTER_OP_GE ] = "GE",
48 [ FILTER_OP_LE ] = "LE",
49
226106c0
MD
50 /* string binary comparators */
51 [ FILTER_OP_EQ_STRING ] = "EQ_STRING",
52 [ FILTER_OP_NE_STRING ] = "NE_STRING",
53 [ FILTER_OP_GT_STRING ] = "GT_STRING",
54 [ FILTER_OP_LT_STRING ] = "LT_STRING",
55 [ FILTER_OP_GE_STRING ] = "GE_STRING",
56 [ FILTER_OP_LE_STRING ] = "LE_STRING",
57
58 /* s64 binary comparators */
59 [ FILTER_OP_EQ_S64 ] = "EQ_S64",
60 [ FILTER_OP_NE_S64 ] = "NE_S64",
61 [ FILTER_OP_GT_S64 ] = "GT_S64",
62 [ FILTER_OP_LT_S64 ] = "LT_S64",
63 [ FILTER_OP_GE_S64 ] = "GE_S64",
64 [ FILTER_OP_LE_S64 ] = "LE_S64",
65
66 /* double binary comparators */
67 [ FILTER_OP_EQ_DOUBLE ] = "EQ_DOUBLE",
68 [ FILTER_OP_NE_DOUBLE ] = "NE_DOUBLE",
69 [ FILTER_OP_GT_DOUBLE ] = "GT_DOUBLE",
70 [ FILTER_OP_LT_DOUBLE ] = "LT_DOUBLE",
71 [ FILTER_OP_GE_DOUBLE ] = "GE_DOUBLE",
72 [ FILTER_OP_LE_DOUBLE ] = "LE_DOUBLE",
73
1e5f62b4
MD
74 /* Mixed S64-double binary comparators */
75 [ FILTER_OP_EQ_DOUBLE_S64 ] = "EQ_DOUBLE_S64",
76 [ FILTER_OP_NE_DOUBLE_S64 ] = "NE_DOUBLE_S64",
77 [ FILTER_OP_GT_DOUBLE_S64 ] = "GT_DOUBLE_S64",
78 [ FILTER_OP_LT_DOUBLE_S64 ] = "LT_DOUBLE_S64",
79 [ FILTER_OP_GE_DOUBLE_S64 ] = "GE_DOUBLE_S64",
80 [ FILTER_OP_LE_DOUBLE_S64 ] = "LE_DOUBLE_S64",
81
82 [ FILTER_OP_EQ_S64_DOUBLE ] = "EQ_S64_DOUBLE",
83 [ FILTER_OP_NE_S64_DOUBLE ] = "NE_S64_DOUBLE",
84 [ FILTER_OP_GT_S64_DOUBLE ] = "GT_S64_DOUBLE",
85 [ FILTER_OP_LT_S64_DOUBLE ] = "LT_S64_DOUBLE",
86 [ FILTER_OP_GE_S64_DOUBLE ] = "GE_S64_DOUBLE",
87 [ FILTER_OP_LE_S64_DOUBLE ] = "LE_S64_DOUBLE",
226106c0 88
cd54f6d9
MD
89 /* unary */
90 [ FILTER_OP_UNARY_PLUS ] = "UNARY_PLUS",
91 [ FILTER_OP_UNARY_MINUS ] = "UNARY_MINUS",
92 [ FILTER_OP_UNARY_NOT ] = "UNARY_NOT",
226106c0
MD
93 [ FILTER_OP_UNARY_PLUS_S64 ] = "UNARY_PLUS_S64",
94 [ FILTER_OP_UNARY_MINUS_S64 ] = "UNARY_MINUS_S64",
95 [ FILTER_OP_UNARY_NOT_S64 ] = "UNARY_NOT_S64",
96 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = "UNARY_PLUS_DOUBLE",
97 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = "UNARY_MINUS_DOUBLE",
98 [ FILTER_OP_UNARY_NOT_DOUBLE ] = "UNARY_NOT_DOUBLE",
cd54f6d9
MD
99
100 /* logical */
101 [ FILTER_OP_AND ] = "AND",
102 [ FILTER_OP_OR ] = "OR",
103
104 /* load */
105 [ FILTER_OP_LOAD_FIELD_REF ] = "LOAD_FIELD_REF",
2f0145d1
MD
106 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = "LOAD_FIELD_REF_STRING",
107 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = "LOAD_FIELD_REF_SEQUENCE",
108 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = "LOAD_FIELD_REF_S64",
109 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = "LOAD_FIELD_REF_DOUBLE",
110
cd54f6d9
MD
111 [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
112 [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
da6eed25 113 [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
49905038
MD
114
115 /* cast */
116 [ FILTER_OP_CAST_TO_S64 ] = "CAST_TO_S64",
117 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = "CAST_DOUBLE_TO_S64",
118 [ FILTER_OP_CAST_NOP ] = "CAST_NOP",
cd54f6d9
MD
119};
120
cd54f6d9
MD
121const char *print_op(enum filter_op op)
122{
123 if (op >= NR_FILTER_OPS)
124 return "UNKNOWN";
125 else
126 return opnames[op];
127}
128
cd54f6d9
MD
129static
130int apply_field_reloc(struct ltt_event *event,
131 struct bytecode_runtime *runtime,
132 uint32_t runtime_len,
133 uint32_t reloc_offset,
134 const char *field_name)
135{
136 const struct lttng_event_desc *desc;
137 const struct lttng_event_field *fields, *field = NULL;
138 unsigned int nr_fields, i;
139 struct field_ref *field_ref;
2f0145d1 140 struct load_op *op;
cd54f6d9
MD
141 uint32_t field_offset = 0;
142
a8c27c7c 143 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
cd54f6d9
MD
144
145 /* Ensure that the reloc is within the code */
146 if (runtime_len - reloc_offset < sizeof(uint16_t))
147 return -EINVAL;
148
149 /* Lookup event by name */
150 desc = event->desc;
151 if (!desc)
152 return -EINVAL;
153 fields = desc->fields;
154 if (!fields)
155 return -EINVAL;
156 nr_fields = desc->nr_fields;
157 for (i = 0; i < nr_fields; i++) {
158 if (!strcmp(fields[i].name, field_name)) {
159 field = &fields[i];
160 break;
161 }
162 /* compute field offset */
163 switch (fields[i].type.atype) {
164 case atype_integer:
165 case atype_enum:
166 field_offset += sizeof(int64_t);
167 break;
168 case atype_array:
169 case atype_sequence:
170 field_offset += sizeof(unsigned long);
171 field_offset += sizeof(void *);
172 break;
173 case atype_string:
174 field_offset += sizeof(void *);
175 break;
176 case atype_float:
177 field_offset += sizeof(double);
da6eed25 178 break;
cd54f6d9
MD
179 default:
180 return -EINVAL;
181 }
182 }
183 if (!field)
184 return -EINVAL;
185
186 /* Check if field offset is too large for 16-bit offset */
187 if (field_offset > FILTER_BYTECODE_MAX_LEN)
188 return -EINVAL;
189
190 /* set type */
2f0145d1
MD
191 op = (struct load_op *) &runtime->data[reloc_offset];
192 field_ref = (struct field_ref *) op->data;
cd54f6d9
MD
193 switch (field->type.atype) {
194 case atype_integer:
195 case atype_enum:
2f0145d1 196 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
cd54f6d9
MD
197 break;
198 case atype_array:
199 case atype_sequence:
2f0145d1 200 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
cd54f6d9
MD
201 break;
202 case atype_string:
2f0145d1 203 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
cd54f6d9
MD
204 break;
205 case atype_float:
2f0145d1 206 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
da6eed25 207 break;
cd54f6d9
MD
208 default:
209 return -EINVAL;
210 }
211 /* set offset */
212 field_ref->offset = (uint16_t) field_offset;
2d78951a
MD
213 return 0;
214}
215
cd54f6d9
MD
216/*
217 * Take a bytecode with reloc table and link it to an event to create a
218 * bytecode runtime.
219 */
2d78951a
MD
220static
221int _lttng_filter_event_link_bytecode(struct ltt_event *event,
222 struct lttng_ust_filter_bytecode *filter_bytecode)
223{
cd54f6d9
MD
224 int ret, offset, next_offset;
225 struct bytecode_runtime *runtime = NULL;
226 size_t runtime_alloc_len;
227
2d78951a
MD
228 if (!filter_bytecode)
229 return 0;
cd54f6d9
MD
230 /* Even is not connected to any description */
231 if (!event->desc)
232 return 0;
233 /* Bytecode already linked */
234 if (event->filter || event->filter_data)
235 return 0;
2d78951a 236
a8c27c7c 237 dbg_printf("Linking\n");
cd54f6d9
MD
238
239 /* We don't need the reloc table in the runtime */
240 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
241 runtime = zmalloc(runtime_alloc_len);
242 if (!runtime) {
243 ret = -ENOMEM;
244 goto link_error;
245 }
246 runtime->len = filter_bytecode->reloc_offset;
247 /* copy original bytecode */
248 memcpy(runtime->data, filter_bytecode->data, runtime->len);
249 /*
250 * apply relocs. Those are a uint16_t (offset in bytecode)
251 * followed by a string (field name).
252 */
cd54f6d9
MD
253 for (offset = filter_bytecode->reloc_offset;
254 offset < filter_bytecode->len;
255 offset = next_offset) {
256 uint16_t reloc_offset =
257 *(uint16_t *) &filter_bytecode->data[offset];
258 const char *field_name =
259 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
260
261 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
262 if (ret) {
263 goto link_error;
264 }
265 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
266 }
9522a886
MD
267 /* Validate bytecode */
268 ret = lttng_filter_validate_bytecode(runtime);
269 if (ret) {
270 goto link_error;
271 }
08c84b15
MD
272 /* Specialize bytecode */
273 ret = lttng_filter_specialize_bytecode(runtime);
274 if (ret) {
275 goto link_error;
276 }
cd54f6d9 277 event->filter_data = runtime;
2d78951a 278 event->filter = lttng_filter_interpret_bytecode;
2d78951a 279 return 0;
cd54f6d9
MD
280
281link_error:
282 event->filter = lttng_filter_false;
283 free(runtime);
284 return ret;
2d78951a
MD
285}
286
287void lttng_filter_event_link_bytecode(struct ltt_event *event,
288 struct lttng_ust_filter_bytecode *filter_bytecode)
289{
290 int ret;
291
cd54f6d9 292 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
2d78951a 293 if (ret) {
0cbbe1f9 294 dbg_printf("[lttng filter] warning: cannot link event bytecode\n");
2d78951a
MD
295 }
296}
297
298/*
299 * Link bytecode to all events for a wildcard. Skips events that already
300 * have a bytecode linked.
301 * We do not set each event's filter_bytecode field, because they do not
302 * own the filter_bytecode: the wildcard owns it.
303 */
304void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
305{
306 struct ltt_event *event;
307 int ret;
308
309 if (!wildcard->filter_bytecode)
310 return;
311
312 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
313 if (event->filter)
314 continue;
315 ret = _lttng_filter_event_link_bytecode(event,
316 wildcard->filter_bytecode);
317 if (ret) {
318 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
319 }
320
321 }
322 return;
323}
324
325/*
326 * Need to attach filter to an event before starting tracing for the
cd54f6d9 327 * session. We own the filter_bytecode if we return success.
2d78951a
MD
328 */
329int lttng_filter_event_attach_bytecode(struct ltt_event *event,
330 struct lttng_ust_filter_bytecode *filter_bytecode)
331{
2d78951a
MD
332 if (event->chan->session->been_active)
333 return -EPERM;
334 if (event->filter_bytecode)
335 return -EEXIST;
cd54f6d9 336 event->filter_bytecode = filter_bytecode;
2d78951a
MD
337 return 0;
338}
339
340/*
341 * Need to attach filter to a wildcard before starting tracing for the
cd54f6d9 342 * session. We own the filter_bytecode if we return success.
2d78951a
MD
343 */
344int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
345 struct lttng_ust_filter_bytecode *filter_bytecode)
346{
2d78951a
MD
347 if (wildcard->chan->session->been_active)
348 return -EPERM;
349 if (wildcard->filter_bytecode)
350 return -EEXIST;
cd54f6d9 351 wildcard->filter_bytecode = filter_bytecode;
2d78951a
MD
352 return 0;
353}
This page took 0.039344 seconds and 4 git commands to generate.