Commit | Line | Data |
---|---|---|
54012638 | 1 | /* |
ab5be9fa | 2 | * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca> |
54012638 | 3 | * |
ab5be9fa | 4 | * SPDX-License-Identifier: GPL-2.0-only |
54012638 | 5 | * |
54012638 DG |
6 | */ |
7 | ||
6c1c0768 | 8 | #define _LGPL_SOURCE |
54012638 DG |
9 | #include <stdio.h> |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
c363b55d | 12 | #include <unistd.h> |
54012638 | 13 | |
dcabc190 FD |
14 | #include <lttng/event.h> |
15 | #include <lttng/lttng-error.h> | |
c3e68e71 | 16 | #include <lttng/kernel-function.h> |
352b58f5 | 17 | #include <lttng/kernel-probe.h> |
dcabc190 FD |
18 | #include <lttng/userspace-probe.h> |
19 | #include <lttng/userspace-probe-internal.h> | |
352b58f5 JR |
20 | #include <lttng/event-rule/event-rule.h> |
21 | #include <lttng/event-rule/event-rule-internal.h> | |
c3e68e71 JR |
22 | #include <lttng/event-rule/kernel-function.h> |
23 | #include <lttng/event-rule/kernel-function-internal.h> | |
24 | #include <lttng/event-rule/kernel-probe.h> | |
25 | #include <lttng/event-rule/kernel-probe-internal.h> | |
352b58f5 JR |
26 | #include <lttng/event-rule/syscall.h> |
27 | #include <lttng/event-rule/syscall-internal.h> | |
28 | #include <lttng/event-rule/tracepoint.h> | |
29 | #include <lttng/event-rule/tracepoint-internal.h> | |
c3e68e71 JR |
30 | #include <lttng/event-rule/userspace-probe-internal.h> |
31 | #include <lttng/map/map.h> | |
32 | #include <lttng/map-key-internal.h> | |
990570ed DG |
33 | #include <common/common.h> |
34 | #include <common/defaults.h> | |
82b69413 | 35 | #include <common/trace-chunk.h> |
d42266a4 | 36 | #include <common/macros.h> |
1e307fab | 37 | |
00e2e675 | 38 | #include "consumer.h" |
62499ad6 | 39 | #include "trace-kernel.h" |
e9404c27 JG |
40 | #include "lttng-sessiond.h" |
41 | #include "notification-thread-commands.h" | |
54012638 | 42 | |
c3e68e71 JR |
43 | /* Next available map key. Access under next_map_key_lock. */ |
44 | static uint64_t _next_map_key; | |
45 | static pthread_mutex_t next_map_key_lock = PTHREAD_MUTEX_INITIALIZER; | |
46 | ||
47 | /* | |
48 | * Return the incremented value of next_map_key. | |
49 | */ | |
50 | static uint64_t get_next_map_key(void) | |
51 | { | |
52 | uint64_t ret; | |
53 | ||
54 | pthread_mutex_lock(&next_map_key_lock); | |
55 | ret = ++_next_map_key; | |
56 | pthread_mutex_unlock(&next_map_key_lock); | |
57 | return ret; | |
58 | } | |
59 | ||
19e70852 | 60 | /* |
050349bb | 61 | * Find the channel name for the given kernel session. |
19e70852 | 62 | */ |
62499ad6 | 63 | struct ltt_kernel_channel *trace_kernel_get_channel_by_name( |
df4f5a87 | 64 | const char *name, struct ltt_kernel_session *session) |
19e70852 DG |
65 | { |
66 | struct ltt_kernel_channel *chan; | |
67 | ||
0525e9ae DG |
68 | assert(session); |
69 | assert(name); | |
19e70852 | 70 | |
85076754 MD |
71 | /* |
72 | * If we receive an empty string for channel name, it means the | |
73 | * default channel name is requested. | |
74 | */ | |
75 | if (name[0] == '\0') | |
76 | name = DEFAULT_CHANNEL_NAME; | |
77 | ||
54d01ffb DG |
78 | DBG("Trying to find channel %s", name); |
79 | ||
19e70852 DG |
80 | cds_list_for_each_entry(chan, &session->channel_list.head, list) { |
81 | if (strcmp(name, chan->channel->name) == 0) { | |
82 | DBG("Found channel by name %s", name); | |
83 | return chan; | |
84 | } | |
85 | } | |
86 | ||
19e70852 DG |
87 | return NULL; |
88 | } | |
89 | ||
00a62084 | 90 | /* |
c3e68e71 JR |
91 | * Find the map name for the given kernel session. |
92 | */ | |
93 | struct ltt_kernel_map *trace_kernel_get_map_by_name( | |
94 | const char *name, struct ltt_kernel_session *session) | |
95 | { | |
96 | struct ltt_kernel_map *map; | |
97 | ||
98 | assert(session); | |
99 | assert(name); | |
100 | ||
101 | DBG("Trying to find map %s", name); | |
102 | ||
103 | cds_list_for_each_entry(map, &session->map_list.head, list) { | |
104 | enum lttng_map_status status; | |
105 | const char *cur_map_name; | |
106 | ||
107 | status = lttng_map_get_name(map->map, &cur_map_name); | |
108 | assert(status == LTTNG_MAP_STATUS_OK); | |
109 | ||
110 | if (strcmp(name, cur_map_name) == 0) { | |
111 | DBG("Found map by name %s", name); | |
112 | return map; | |
113 | } | |
114 | } | |
115 | ||
116 | return NULL; | |
117 | } | |
118 | ||
119 | /* | |
120 | * Find the event for the given channel or map. | |
00a62084 MD |
121 | */ |
122 | struct ltt_kernel_event *trace_kernel_find_event( | |
c3e68e71 JR |
123 | struct ltt_kernel_event_list *events_list, |
124 | uint64_t tracer_token, char *name, | |
00a62084 | 125 | enum lttng_event_type type, |
2b00d462 | 126 | struct lttng_bytecode *filter) |
00a62084 MD |
127 | { |
128 | struct ltt_kernel_event *ev; | |
129 | int found = 0; | |
130 | ||
131 | assert(name); | |
00a62084 | 132 | |
c3e68e71 JR |
133 | cds_list_for_each_entry(ev, &events_list->head, list) { |
134 | if (ev->event->token != tracer_token) { | |
135 | continue; | |
136 | } | |
00a62084 MD |
137 | if (type != LTTNG_EVENT_ALL && ev->type != type) { |
138 | continue; | |
139 | } | |
140 | if (strcmp(name, ev->event->name)) { | |
141 | continue; | |
142 | } | |
143 | if ((ev->filter && !filter) || (!ev->filter && filter)) { | |
144 | continue; | |
145 | } | |
146 | if (ev->filter && filter) { | |
147 | if (ev->filter->len != filter->len || | |
148 | memcmp(ev->filter->data, filter->data, | |
149 | filter->len) != 0) { | |
150 | continue; | |
151 | } | |
152 | } | |
153 | found = 1; | |
154 | break; | |
155 | } | |
156 | if (found) { | |
c3e68e71 | 157 | DBG("Kernel event %s found", name); |
00a62084 MD |
158 | return ev; |
159 | } else { | |
c3e68e71 | 160 | DBG("Kernel event %s not found", name); |
00a62084 MD |
161 | return NULL; |
162 | } | |
163 | } | |
164 | ||
19e70852 | 165 | /* |
050349bb | 166 | * Find the event name for the given channel. |
19e70852 | 167 | */ |
62499ad6 | 168 | struct ltt_kernel_event *trace_kernel_get_event_by_name( |
d0ae4ea8 MD |
169 | char *name, struct ltt_kernel_channel *channel, |
170 | enum lttng_event_type type) | |
19e70852 DG |
171 | { |
172 | struct ltt_kernel_event *ev; | |
00a62084 | 173 | int found = 0; |
19e70852 | 174 | |
0525e9ae DG |
175 | assert(name); |
176 | assert(channel); | |
19e70852 DG |
177 | |
178 | cds_list_for_each_entry(ev, &channel->events_list.head, list) { | |
00a62084 | 179 | if (type != LTTNG_EVENT_ALL && ev->type != type) { |
d0ae4ea8 | 180 | continue; |
19e70852 | 181 | } |
00a62084 MD |
182 | if (strcmp(name, ev->event->name)) { |
183 | continue; | |
184 | } | |
185 | found = 1; | |
186 | break; | |
187 | } | |
188 | if (found) { | |
189 | DBG("Found event %s for channel %s", name, | |
190 | channel->channel->name); | |
191 | return ev; | |
192 | } else { | |
193 | return NULL; | |
19e70852 | 194 | } |
19e70852 DG |
195 | } |
196 | ||
54012638 | 197 | /* |
050349bb | 198 | * Allocate and initialize a kernel session data structure. |
54012638 | 199 | * |
050349bb | 200 | * Return pointer to structure or NULL. |
54012638 | 201 | */ |
dec56f6c | 202 | struct ltt_kernel_session *trace_kernel_create_session(void) |
54012638 | 203 | { |
a4b92340 | 204 | struct ltt_kernel_session *lks = NULL; |
54012638 DG |
205 | |
206 | /* Allocate a new ltt kernel session */ | |
ba7f0ae5 | 207 | lks = zmalloc(sizeof(struct ltt_kernel_session)); |
54012638 | 208 | if (lks == NULL) { |
df0f840b | 209 | PERROR("create kernel session zmalloc"); |
a4b92340 | 210 | goto alloc_error; |
54012638 DG |
211 | } |
212 | ||
213 | /* Init data structure */ | |
03550b58 MD |
214 | lks->fd = -1; |
215 | lks->metadata_stream_fd = -1; | |
54012638 | 216 | lks->channel_count = 0; |
c3e68e71 | 217 | lks->map_count = 0; |
54012638 DG |
218 | lks->stream_count_global = 0; |
219 | lks->metadata = NULL; | |
220 | CDS_INIT_LIST_HEAD(&lks->channel_list.head); | |
c3e68e71 | 221 | CDS_INIT_LIST_HEAD(&lks->map_list.head); |
54012638 | 222 | |
159b042f JG |
223 | lks->tracker_pid = process_attr_tracker_create(); |
224 | if (!lks->tracker_pid) { | |
55c9e7ca JR |
225 | goto error; |
226 | } | |
159b042f JG |
227 | lks->tracker_vpid = process_attr_tracker_create(); |
228 | if (!lks->tracker_vpid) { | |
55c9e7ca JR |
229 | goto error; |
230 | } | |
159b042f JG |
231 | lks->tracker_uid = process_attr_tracker_create(); |
232 | if (!lks->tracker_uid) { | |
55c9e7ca JR |
233 | goto error; |
234 | } | |
159b042f JG |
235 | lks->tracker_vuid = process_attr_tracker_create(); |
236 | if (!lks->tracker_vuid) { | |
55c9e7ca JR |
237 | goto error; |
238 | } | |
159b042f JG |
239 | lks->tracker_gid = process_attr_tracker_create(); |
240 | if (!lks->tracker_gid) { | |
55c9e7ca JR |
241 | goto error; |
242 | } | |
159b042f JG |
243 | lks->tracker_vgid = process_attr_tracker_create(); |
244 | if (!lks->tracker_vgid) { | |
55c9e7ca JR |
245 | goto error; |
246 | } | |
00e2e675 DG |
247 | lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); |
248 | if (lks->consumer == NULL) { | |
249 | goto error; | |
250 | } | |
251 | ||
54012638 DG |
252 | return lks; |
253 | ||
254 | error: | |
159b042f JG |
255 | process_attr_tracker_destroy(lks->tracker_pid); |
256 | process_attr_tracker_destroy(lks->tracker_vpid); | |
257 | process_attr_tracker_destroy(lks->tracker_uid); | |
258 | process_attr_tracker_destroy(lks->tracker_vuid); | |
259 | process_attr_tracker_destroy(lks->tracker_gid); | |
260 | process_attr_tracker_destroy(lks->tracker_vgid); | |
a4b92340 DG |
261 | free(lks); |
262 | ||
263 | alloc_error: | |
54012638 DG |
264 | return NULL; |
265 | } | |
266 | ||
267 | /* | |
050349bb | 268 | * Allocate and initialize a kernel channel data structure. |
54012638 | 269 | * |
050349bb | 270 | * Return pointer to structure or NULL. |
54012638 | 271 | */ |
00e2e675 | 272 | struct ltt_kernel_channel *trace_kernel_create_channel( |
fdd9eb17 | 273 | struct lttng_channel *chan) |
54012638 | 274 | { |
54012638 | 275 | struct ltt_kernel_channel *lkc; |
61a5b6b1 | 276 | struct lttng_channel_extended *extended = NULL; |
54012638 | 277 | |
0525e9ae DG |
278 | assert(chan); |
279 | ||
ba7f0ae5 | 280 | lkc = zmalloc(sizeof(struct ltt_kernel_channel)); |
f3ed775e | 281 | if (lkc == NULL) { |
df0f840b | 282 | PERROR("ltt_kernel_channel zmalloc"); |
54012638 DG |
283 | goto error; |
284 | } | |
285 | ||
ba7f0ae5 | 286 | lkc->channel = zmalloc(sizeof(struct lttng_channel)); |
f3ed775e | 287 | if (lkc->channel == NULL) { |
df0f840b | 288 | PERROR("lttng_channel zmalloc"); |
e9404c27 JG |
289 | goto error; |
290 | } | |
291 | ||
292 | extended = zmalloc(sizeof(struct lttng_channel_extended)); | |
293 | if (!extended) { | |
294 | PERROR("lttng_channel_channel zmalloc"); | |
f3ed775e DG |
295 | goto error; |
296 | } | |
297 | memcpy(lkc->channel, chan, sizeof(struct lttng_channel)); | |
e9404c27 JG |
298 | memcpy(extended, chan->attr.extended.ptr, sizeof(struct lttng_channel_extended)); |
299 | lkc->channel->attr.extended.ptr = extended; | |
300 | extended = NULL; | |
54012638 | 301 | |
85076754 MD |
302 | /* |
303 | * If we receive an empty string for channel name, it means the | |
304 | * default channel name is requested. | |
305 | */ | |
306 | if (chan->name[0] == '\0') { | |
307 | strncpy(lkc->channel->name, DEFAULT_CHANNEL_NAME, | |
308 | sizeof(lkc->channel->name)); | |
309 | } | |
bd722d76 | 310 | lkc->channel->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
85076754 | 311 | |
03550b58 | 312 | lkc->fd = -1; |
54012638 | 313 | lkc->stream_count = 0; |
cbbbb275 | 314 | lkc->event_count = 0; |
d36b8583 | 315 | lkc->enabled = 1; |
753873bf | 316 | lkc->published_to_notification_thread = false; |
54012638 DG |
317 | /* Init linked list */ |
318 | CDS_INIT_LIST_HEAD(&lkc->events_list.head); | |
319 | CDS_INIT_LIST_HEAD(&lkc->stream_list.head); | |
645328ae | 320 | CDS_INIT_LIST_HEAD(&lkc->ctx_list); |
54012638 DG |
321 | |
322 | return lkc; | |
323 | ||
324 | error: | |
e9404c27 JG |
325 | if (lkc) { |
326 | free(lkc->channel); | |
327 | } | |
328 | free(extended); | |
329 | free(lkc); | |
54012638 DG |
330 | return NULL; |
331 | } | |
332 | ||
c3e68e71 JR |
333 | struct ltt_kernel_map *trace_kernel_create_map( |
334 | const struct lttng_map *map) | |
335 | { | |
336 | struct ltt_kernel_map *kernel_map = NULL; | |
337 | unsigned int i, number_dimensions; | |
338 | ||
339 | kernel_map = zmalloc(sizeof(*kernel_map)); | |
340 | if (!kernel_map) { | |
341 | PERROR("ltt_kernel_map zmalloc"); | |
342 | goto end; | |
343 | } | |
344 | ||
345 | switch (lttng_map_get_boundary_policy(map)) { | |
346 | case LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW: | |
347 | kernel_map->counter_conf.arithmetic = LTTNG_KERNEL_COUNTER_ARITHMETIC_MODULAR; | |
348 | break; | |
349 | default: | |
350 | abort(); | |
351 | } | |
352 | ||
353 | switch (lttng_map_get_bitness(map)) { | |
354 | case LTTNG_MAP_BITNESS_32BITS: | |
355 | kernel_map->counter_conf.bitness = LTTNG_KERNEL_COUNTER_BITNESS_32; | |
356 | break; | |
357 | case LTTNG_MAP_BITNESS_64BITS: | |
358 | kernel_map->counter_conf.bitness = LTTNG_KERNEL_COUNTER_BITNESS_64; | |
359 | break; | |
360 | default: | |
361 | abort(); | |
362 | } | |
363 | ||
364 | kernel_map->counter_conf.coalesce_hits = lttng_map_get_coalesce_hits(map); | |
365 | ||
366 | number_dimensions = lttng_map_get_dimension_count(map); | |
367 | assert(number_dimensions <= LTTNG_KERNEL_COUNTER_DIMENSION_MAX); | |
368 | ||
369 | kernel_map->counter_conf.number_dimensions = number_dimensions; | |
370 | ||
371 | for (i = 0; i < kernel_map->counter_conf.number_dimensions; i++) { | |
372 | enum lttng_map_status map_status; | |
373 | uint64_t dimension_length; | |
374 | ||
375 | map_status = lttng_map_get_dimension_length(map, i, | |
376 | &dimension_length); | |
377 | assert(map_status == LTTNG_MAP_STATUS_OK); | |
378 | ||
379 | kernel_map->counter_conf.dimensions[i].size = dimension_length; | |
380 | ||
381 | //FIXME: We need to turn on overflow and underflow | |
382 | kernel_map->counter_conf.dimensions[i].has_overflow = false; | |
383 | kernel_map->counter_conf.dimensions[i].has_underflow = false; | |
384 | } | |
385 | ||
386 | kernel_map->fd = -1; | |
387 | kernel_map->enabled = 1; | |
388 | kernel_map->key = get_next_map_key(); | |
389 | ||
390 | kernel_map->event_counters_ht = lttng_ht_new(0, LTTNG_HT_TYPE_U64); | |
391 | end: | |
392 | return kernel_map; | |
393 | } | |
394 | ||
645328ae DG |
395 | /* |
396 | * Allocate and init a kernel context object. | |
397 | * | |
398 | * Return the allocated object or NULL on error. | |
399 | */ | |
400 | struct ltt_kernel_context *trace_kernel_create_context( | |
401 | struct lttng_kernel_context *ctx) | |
402 | { | |
403 | struct ltt_kernel_context *kctx; | |
404 | ||
405 | kctx = zmalloc(sizeof(*kctx)); | |
406 | if (!kctx) { | |
407 | PERROR("zmalloc kernel context"); | |
408 | goto error; | |
409 | } | |
410 | ||
411 | if (ctx) { | |
412 | memcpy(&kctx->ctx, ctx, sizeof(kctx->ctx)); | |
413 | } | |
df3c77c8 JG |
414 | error: |
415 | return kctx; | |
416 | } | |
645328ae | 417 | |
df3c77c8 JG |
418 | /* |
419 | * Allocate and init a kernel context object from an existing kernel context | |
420 | * object. | |
421 | * | |
422 | * Return the allocated object or NULL on error. | |
423 | */ | |
424 | struct ltt_kernel_context *trace_kernel_copy_context( | |
425 | struct ltt_kernel_context *kctx) | |
426 | { | |
427 | struct ltt_kernel_context *kctx_copy; | |
428 | ||
429 | assert(kctx); | |
430 | kctx_copy = zmalloc(sizeof(*kctx_copy)); | |
431 | if (!kctx_copy) { | |
432 | PERROR("zmalloc ltt_kernel_context"); | |
433 | goto error; | |
434 | } | |
435 | ||
436 | memcpy(kctx_copy, kctx, sizeof(*kctx_copy)); | |
437 | memset(&kctx_copy->list, 0, sizeof(kctx_copy->list)); | |
7b9445b3 | 438 | |
645328ae | 439 | error: |
df3c77c8 | 440 | return kctx_copy; |
645328ae DG |
441 | } |
442 | ||
54012638 | 443 | /* |
050349bb | 444 | * Allocate and initialize a kernel event. Set name and event type. |
a969e101 | 445 | * We own filter_expression, and filter. |
54012638 | 446 | * |
050349bb | 447 | * Return pointer to structure or NULL. |
54012638 | 448 | */ |
71a3bb01 FD |
449 | enum lttng_error_code trace_kernel_create_event( |
450 | struct lttng_event *ev, char *filter_expression, | |
2b00d462 | 451 | struct lttng_bytecode *filter, |
71a3bb01 | 452 | struct ltt_kernel_event **kernel_event) |
54012638 | 453 | { |
71a3bb01 | 454 | enum lttng_error_code ret; |
54012638 | 455 | struct lttng_kernel_event *attr; |
71a3bb01 | 456 | struct ltt_kernel_event *local_kernel_event; |
dcabc190 | 457 | struct lttng_userspace_probe_location *userspace_probe_location = NULL; |
54012638 | 458 | |
0525e9ae DG |
459 | assert(ev); |
460 | ||
71a3bb01 | 461 | local_kernel_event = zmalloc(sizeof(struct ltt_kernel_event)); |
ba7f0ae5 | 462 | attr = zmalloc(sizeof(struct lttng_kernel_event)); |
71a3bb01 | 463 | if (local_kernel_event == NULL || attr == NULL) { |
df0f840b | 464 | PERROR("kernel event zmalloc"); |
71a3bb01 | 465 | ret = LTTNG_ERR_NOMEM; |
54012638 DG |
466 | goto error; |
467 | } | |
468 | ||
f3ed775e | 469 | switch (ev->type) { |
7d29a247 | 470 | case LTTNG_EVENT_PROBE: |
e6ddca71 | 471 | attr->instrumentation = LTTNG_KERNEL_KPROBE; |
7d29a247 DG |
472 | attr->u.kprobe.addr = ev->attr.probe.addr; |
473 | attr->u.kprobe.offset = ev->attr.probe.offset; | |
f3ed775e | 474 | strncpy(attr->u.kprobe.symbol_name, |
dbbb3ec5 DG |
475 | ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); |
476 | attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 477 | break; |
dcabc190 FD |
478 | case LTTNG_EVENT_USERSPACE_PROBE: |
479 | { | |
87597c2c JG |
480 | const struct lttng_userspace_probe_location* location = NULL; |
481 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
dcabc190 FD |
482 | |
483 | location = lttng_event_get_userspace_probe_location(ev); | |
484 | if (!location) { | |
485 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
486 | goto error; | |
487 | } | |
488 | ||
489 | /* | |
490 | * From this point on, the specific term 'uprobe' is used | |
491 | * instead of the generic 'userspace probe' because it's the | |
492 | * technology used at the moment for this instrumentation. | |
493 | * LTTng currently implements userspace probes using uprobes. | |
494 | * In the interactions with the kernel tracer, we use the | |
495 | * uprobe term. | |
496 | */ | |
497 | attr->instrumentation = LTTNG_KERNEL_UPROBE; | |
498 | ||
dcabc190 FD |
499 | lookup = lttng_userspace_probe_location_get_lookup_method( |
500 | location); | |
501 | if (!lookup) { | |
502 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
503 | goto error; | |
504 | } | |
505 | ||
506 | /* | |
507 | * From the kernel tracer's perspective, all userspace probe | |
508 | * event types are all the same: a file and an offset. | |
509 | */ | |
510 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
511 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
512 | /* Get the file descriptor on the target binary. */ | |
513 | attr->u.uprobe.fd = | |
514 | lttng_userspace_probe_location_function_get_binary_fd(location); | |
515 | ||
516 | /* | |
517 | * Save a reference to the probe location used during | |
e368fb43 | 518 | * the listing of events. |
dcabc190 FD |
519 | */ |
520 | userspace_probe_location = | |
521 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
522 | break; |
523 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
524 | /* Get the file descriptor on the target binary. */ | |
525 | attr->u.uprobe.fd = | |
526 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); | |
527 | ||
528 | /* | |
529 | * Save a reference to the probe location used during the listing of | |
e368fb43 | 530 | * events. |
dcabc190 FD |
531 | */ |
532 | userspace_probe_location = | |
533 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
534 | break; |
535 | default: | |
536 | DBG("Unsupported lookup method type"); | |
537 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
538 | goto error; | |
539 | } | |
540 | break; | |
541 | } | |
f3ed775e | 542 | case LTTNG_EVENT_FUNCTION: |
8f0d098b MD |
543 | attr->instrumentation = LTTNG_KERNEL_KRETPROBE; |
544 | attr->u.kretprobe.addr = ev->attr.probe.addr; | |
545 | attr->u.kretprobe.offset = ev->attr.probe.offset; | |
8f0d098b | 546 | strncpy(attr->u.kretprobe.symbol_name, |
dbbb3ec5 DG |
547 | ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); |
548 | attr->u.kretprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; | |
8f0d098b MD |
549 | break; |
550 | case LTTNG_EVENT_FUNCTION_ENTRY: | |
f3ed775e DG |
551 | attr->instrumentation = LTTNG_KERNEL_FUNCTION; |
552 | strncpy(attr->u.ftrace.symbol_name, | |
dbbb3ec5 DG |
553 | ev->attr.ftrace.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); |
554 | attr->u.ftrace.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 555 | break; |
e6ddca71 DG |
556 | case LTTNG_EVENT_TRACEPOINT: |
557 | attr->instrumentation = LTTNG_KERNEL_TRACEPOINT; | |
f3ed775e | 558 | break; |
a54bd42d MD |
559 | case LTTNG_EVENT_SYSCALL: |
560 | attr->instrumentation = LTTNG_KERNEL_SYSCALL; | |
c863e5a6 FD |
561 | attr->u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_ALL; |
562 | attr->u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRYEXIT; | |
563 | attr->u.syscall.match = LTTNG_KERNEL_SYSCALL_MATCH_NAME; | |
0133c199 | 564 | break; |
7a3d1328 MD |
565 | case LTTNG_EVENT_ALL: |
566 | attr->instrumentation = LTTNG_KERNEL_ALL; | |
567 | break; | |
f3ed775e DG |
568 | default: |
569 | ERR("Unknown kernel instrumentation type (%d)", ev->type); | |
71a3bb01 | 570 | ret = LTTNG_ERR_INVALID; |
f3ed775e DG |
571 | goto error; |
572 | } | |
573 | ||
574 | /* Copy event name */ | |
dbbb3ec5 DG |
575 | strncpy(attr->name, ev->name, LTTNG_KERNEL_SYM_NAME_LEN); |
576 | attr->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 577 | |
54012638 | 578 | /* Setting up a kernel event */ |
71a3bb01 FD |
579 | local_kernel_event->fd = -1; |
580 | local_kernel_event->event = attr; | |
581 | local_kernel_event->enabled = 1; | |
582 | local_kernel_event->filter_expression = filter_expression; | |
583 | local_kernel_event->filter = filter; | |
dcabc190 | 584 | local_kernel_event->userspace_probe_location = userspace_probe_location; |
54012638 | 585 | |
71a3bb01 FD |
586 | *kernel_event = local_kernel_event; |
587 | ||
588 | return LTTNG_OK; | |
54012638 DG |
589 | |
590 | error: | |
a969e101 MD |
591 | free(filter_expression); |
592 | free(filter); | |
71a3bb01 | 593 | free(local_kernel_event); |
a2c0da86 | 594 | free(attr); |
71a3bb01 | 595 | return ret; |
54012638 DG |
596 | } |
597 | ||
352b58f5 JR |
598 | /* |
599 | * Allocate and initialize a kernel token event rule. | |
600 | * | |
601 | * Return pointer to structure or NULL. | |
602 | */ | |
603 | enum lttng_error_code trace_kernel_create_event_notifier_rule( | |
604 | struct lttng_trigger *trigger, | |
605 | uint64_t token, | |
c3e68e71 | 606 | uint64_t error_counter_index, |
352b58f5 JR |
607 | struct ltt_kernel_event_notifier_rule **event_notifier_rule) |
608 | { | |
609 | enum lttng_error_code ret = LTTNG_OK; | |
610 | enum lttng_condition_type condition_type; | |
611 | enum lttng_event_rule_type event_rule_type; | |
612 | enum lttng_condition_status condition_status; | |
613 | struct ltt_kernel_event_notifier_rule *local_kernel_token_event_rule; | |
614 | const struct lttng_condition *condition = NULL; | |
615 | const struct lttng_event_rule *event_rule = NULL; | |
616 | ||
617 | assert(event_notifier_rule); | |
618 | ||
619 | condition = lttng_trigger_get_condition(trigger); | |
620 | assert(condition); | |
621 | ||
622 | condition_type = lttng_condition_get_type(condition); | |
c3e68e71 | 623 | assert(condition_type == LTTNG_CONDITION_TYPE_ON_EVENT); |
352b58f5 | 624 | |
c3e68e71 | 625 | condition_status = lttng_condition_on_event_get_rule( |
352b58f5 JR |
626 | condition, &event_rule); |
627 | assert(condition_status == LTTNG_CONDITION_STATUS_OK); | |
628 | assert(event_rule); | |
629 | ||
630 | event_rule_type = lttng_event_rule_get_type(event_rule); | |
631 | assert(event_rule_type != LTTNG_EVENT_RULE_TYPE_UNKNOWN); | |
632 | ||
633 | local_kernel_token_event_rule = | |
634 | zmalloc(sizeof(struct ltt_kernel_event_notifier_rule)); | |
635 | if (local_kernel_token_event_rule == NULL) { | |
636 | PERROR("Failed to allocate ltt_kernel_token_event_rule structure"); | |
637 | ret = LTTNG_ERR_NOMEM; | |
638 | goto error; | |
639 | } | |
640 | ||
641 | local_kernel_token_event_rule->fd = -1; | |
642 | local_kernel_token_event_rule->enabled = 1; | |
643 | local_kernel_token_event_rule->token = token; | |
c3e68e71 | 644 | local_kernel_token_event_rule->error_counter_index = error_counter_index; |
352b58f5 JR |
645 | |
646 | /* Get the reference of the event rule. */ | |
647 | lttng_trigger_get(trigger); | |
648 | ||
649 | local_kernel_token_event_rule->trigger = trigger; | |
650 | /* The event rule still owns the filter and bytecode. */ | |
651 | local_kernel_token_event_rule->filter = | |
652 | lttng_event_rule_get_filter_bytecode(event_rule); | |
653 | ||
654 | DBG3("Created kernel event notifier rule: token = %" PRIu64, | |
655 | local_kernel_token_event_rule->token); | |
656 | error: | |
657 | *event_notifier_rule = local_kernel_token_event_rule; | |
658 | return ret; | |
659 | } | |
660 | ||
c3e68e71 JR |
661 | enum trace_kernel_event_type { |
662 | TRACE_KERNEL_EVENT_TYPE_NOTIFIER, | |
663 | TRACE_KERNEL_EVENT_TYPE_COUNTER, | |
664 | }; | |
665 | ||
352b58f5 | 666 | /* |
c3e68e71 | 667 | * Initialize a kernel event from an event rule. |
352b58f5 | 668 | */ |
c3e68e71 JR |
669 | static |
670 | enum lttng_error_code trace_kernel_init_event_from_event_rule( | |
352b58f5 | 671 | const struct lttng_event_rule *rule, |
c3e68e71 JR |
672 | struct lttng_kernel_event *kernel_event, |
673 | enum trace_kernel_event_type event_type) | |
352b58f5 | 674 | { |
366a83b3 | 675 | enum lttng_error_code ret_code; |
352b58f5 | 676 | const char *name; |
366a83b3 | 677 | int strncpy_ret; |
352b58f5 JR |
678 | |
679 | switch (lttng_event_rule_get_type(rule)) { | |
c3e68e71 | 680 | case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE: |
352b58f5 JR |
681 | { |
682 | uint64_t address = 0, offset = 0; | |
683 | const char *symbol_name = NULL; | |
684 | const struct lttng_kernel_probe_location *location = NULL; | |
685 | enum lttng_kernel_probe_location_status k_status; | |
686 | enum lttng_event_rule_status status; | |
687 | ||
c3e68e71 | 688 | status = lttng_event_rule_kernel_probe_get_location(rule, &location); |
352b58f5 | 689 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 690 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
691 | goto error; |
692 | } | |
693 | ||
694 | switch (lttng_kernel_probe_location_get_type(location)) { | |
695 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
696 | { | |
697 | k_status = lttng_kernel_probe_location_address_get_address( | |
698 | location, &address); | |
699 | assert(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); | |
700 | break; | |
701 | } | |
702 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
703 | { | |
704 | k_status = lttng_kernel_probe_location_symbol_get_offset( | |
705 | location, &offset); | |
706 | assert(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); | |
707 | symbol_name = lttng_kernel_probe_location_symbol_get_name( | |
708 | location); | |
709 | break; | |
710 | } | |
711 | default: | |
712 | abort(); | |
713 | } | |
714 | ||
c3e68e71 JR |
715 | kernel_event->instrumentation = LTTNG_KERNEL_KPROBE; |
716 | kernel_event->u.kprobe.addr = address; | |
717 | kernel_event->u.kprobe.offset = offset; | |
718 | if (symbol_name) { | |
719 | strncpy_ret = lttng_strncpy( | |
720 | kernel_event->u.kprobe.symbol_name, | |
721 | symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); | |
722 | ||
723 | if (strncpy_ret) { | |
724 | ret_code = LTTNG_ERR_INVALID; | |
725 | goto error; | |
726 | } | |
727 | } | |
728 | ||
729 | kernel_event->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; | |
730 | ||
731 | status = lttng_event_rule_kernel_probe_get_event_name(rule, &name); | |
732 | assert(status == LTTNG_EVENT_RULE_STATUS_OK); | |
733 | ret_code = LTTNG_OK; | |
734 | break; | |
735 | } | |
736 | case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION: | |
737 | { | |
738 | uint64_t address = 0, offset = 0; | |
739 | const char *symbol_name = NULL; | |
740 | const struct lttng_kernel_function_location *location = NULL; | |
741 | enum lttng_kernel_function_location_status k_status; | |
742 | enum lttng_event_rule_status status; | |
743 | ||
744 | status = lttng_event_rule_kernel_function_get_location(rule, &location); | |
745 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { | |
746 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
747 | goto error; | |
748 | } | |
749 | ||
750 | switch (lttng_kernel_function_location_get_type(location)) { | |
751 | case LTTNG_KERNEL_FUNCTION_LOCATION_TYPE_ADDRESS: | |
752 | { | |
753 | k_status = lttng_kernel_function_location_address_get_address( | |
754 | location, &address); | |
755 | assert(k_status == LTTNG_KERNEL_FUNCTION_LOCATION_STATUS_OK); | |
756 | break; | |
757 | } | |
758 | case LTTNG_KERNEL_FUNCTION_LOCATION_TYPE_SYMBOL_OFFSET: | |
759 | { | |
760 | k_status = lttng_kernel_function_location_symbol_get_offset( | |
761 | location, &offset); | |
762 | assert(k_status == LTTNG_KERNEL_FUNCTION_LOCATION_STATUS_OK); | |
763 | symbol_name = lttng_kernel_function_location_symbol_get_name( | |
764 | location); | |
765 | break; | |
766 | } | |
767 | default: | |
768 | abort(); | |
769 | } | |
770 | ||
771 | kernel_event->instrumentation = LTTNG_KERNEL_KRETPROBE; | |
772 | kernel_event->u.kretprobe.addr = address; | |
773 | kernel_event->u.kretprobe.offset = offset; | |
352b58f5 | 774 | if (symbol_name) { |
366a83b3 | 775 | strncpy_ret = lttng_strncpy( |
c3e68e71 | 776 | kernel_event->u.kretprobe.symbol_name, |
352b58f5 JR |
777 | symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); |
778 | ||
366a83b3 JG |
779 | if (strncpy_ret) { |
780 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
781 | goto error; |
782 | } | |
783 | } | |
784 | ||
c3e68e71 JR |
785 | kernel_event->u.kretprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
786 | ||
787 | status = lttng_event_rule_kernel_function_get_event_name(rule, &name); | |
352b58f5 | 788 | assert(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 789 | ret_code = LTTNG_OK; |
352b58f5 JR |
790 | break; |
791 | } | |
c3e68e71 | 792 | case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE: |
352b58f5 JR |
793 | { |
794 | const struct lttng_userspace_probe_location* location = NULL; | |
795 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
796 | enum lttng_event_rule_status status; | |
797 | ||
c3e68e71 | 798 | status = lttng_event_rule_userspace_probe_get_location(rule, &location); |
352b58f5 | 799 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 800 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
801 | goto error; |
802 | } | |
803 | ||
c3e68e71 | 804 | kernel_event->instrumentation = LTTNG_KERNEL_UPROBE; |
352b58f5 JR |
805 | |
806 | lookup = lttng_userspace_probe_location_get_lookup_method( | |
807 | location); | |
808 | if (!lookup) { | |
366a83b3 | 809 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
810 | goto error; |
811 | } | |
812 | ||
813 | /* | |
814 | * From the kernel tracer's perspective, all userspace probe | |
815 | * event types are all the same: a file and an offset. | |
816 | */ | |
817 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
818 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
819 | /* Get the file descriptor on the target binary. */ | |
c3e68e71 | 820 | kernel_event->u.uprobe.fd = |
352b58f5 JR |
821 | lttng_userspace_probe_location_function_get_binary_fd(location); |
822 | ||
823 | break; | |
824 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
825 | /* Get the file descriptor on the target binary. */ | |
c3e68e71 | 826 | kernel_event->u.uprobe.fd = |
352b58f5 JR |
827 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); |
828 | break; | |
829 | default: | |
830 | abort(); | |
831 | } | |
832 | ||
c3e68e71 | 833 | status = lttng_event_rule_userspace_probe_get_event_name(rule, &name); |
352b58f5 | 834 | assert(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 835 | ret_code = LTTNG_OK; |
352b58f5 JR |
836 | break; |
837 | } | |
838 | case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: | |
839 | { | |
840 | const enum lttng_domain_type domain = | |
841 | lttng_event_rule_get_domain_type(rule); | |
842 | const enum lttng_event_rule_status status = | |
843 | lttng_event_rule_tracepoint_get_pattern( | |
844 | rule, &name); | |
845 | ||
846 | assert(domain == LTTNG_DOMAIN_KERNEL); | |
847 | assert(status == LTTNG_EVENT_RULE_STATUS_OK); | |
c3e68e71 | 848 | kernel_event->instrumentation = |
352b58f5 JR |
849 | LTTNG_KERNEL_TRACEPOINT; |
850 | ||
366a83b3 | 851 | ret_code = LTTNG_OK; |
352b58f5 JR |
852 | break; |
853 | } | |
854 | case LTTNG_EVENT_RULE_TYPE_SYSCALL: | |
855 | { | |
856 | const enum lttng_event_rule_status status = | |
857 | lttng_event_rule_syscall_get_pattern( | |
858 | rule, &name); | |
859 | ||
860 | assert(status == LTTNG_EVENT_RULE_STATUS_OK); | |
861 | ||
c3e68e71 | 862 | kernel_event->instrumentation = |
352b58f5 | 863 | LTTNG_KERNEL_SYSCALL; |
c3e68e71 | 864 | kernel_event->u.syscall.abi = |
352b58f5 | 865 | LTTNG_KERNEL_SYSCALL_ABI_ALL; |
c3e68e71 | 866 | kernel_event->u.syscall.match = |
352b58f5 | 867 | LTTNG_KERNEL_SYSCALL_MATCH_NAME; |
c3e68e71 JR |
868 | switch (event_type) { |
869 | case TRACE_KERNEL_EVENT_TYPE_COUNTER: | |
870 | kernel_event->u.syscall.entryexit = | |
871 | LTTNG_KERNEL_SYSCALL_ENTRYEXIT; | |
872 | break; | |
873 | case TRACE_KERNEL_EVENT_TYPE_NOTIFIER: | |
874 | kernel_event->u.syscall.entryexit = | |
875 | LTTNG_KERNEL_SYSCALL_ENTRY; | |
876 | break; | |
877 | } | |
366a83b3 | 878 | ret_code = LTTNG_OK; |
352b58f5 JR |
879 | break; |
880 | } | |
352b58f5 JR |
881 | default: |
882 | abort(); | |
883 | break; | |
884 | } | |
885 | ||
c3e68e71 | 886 | strncpy_ret = lttng_strncpy(kernel_event->name, name, |
352b58f5 | 887 | LTTNG_KERNEL_SYM_NAME_LEN); |
366a83b3 JG |
888 | if (strncpy_ret) { |
889 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
890 | goto error; |
891 | } | |
892 | ||
893 | error: | |
366a83b3 | 894 | return ret_code; |
352b58f5 | 895 | } |
c3e68e71 JR |
896 | |
897 | enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule( | |
898 | const struct lttng_event_rule *rule, | |
899 | struct lttng_kernel_event_notifier *kernel_event_notifier) | |
900 | { | |
901 | return trace_kernel_init_event_from_event_rule(rule, | |
902 | &kernel_event_notifier->event, | |
903 | TRACE_KERNEL_EVENT_TYPE_NOTIFIER); | |
904 | } | |
905 | ||
906 | enum lttng_error_code trace_kernel_init_event_counter_from_event_rule( | |
907 | const struct lttng_event_rule *rule, | |
908 | struct lttng_kernel_counter_event *kernel_counter_event) | |
909 | { | |
910 | return trace_kernel_init_event_from_event_rule(rule, | |
911 | &kernel_counter_event->event, | |
912 | TRACE_KERNEL_EVENT_TYPE_COUNTER); | |
913 | } | |
914 | ||
54012638 | 915 | /* |
050349bb | 916 | * Allocate and initialize a kernel metadata. |
54012638 | 917 | * |
050349bb | 918 | * Return pointer to structure or NULL. |
54012638 | 919 | */ |
a4b92340 | 920 | struct ltt_kernel_metadata *trace_kernel_create_metadata(void) |
54012638 | 921 | { |
d42266a4 | 922 | int ret; |
54012638 | 923 | struct ltt_kernel_metadata *lkm; |
f3ed775e | 924 | struct lttng_channel *chan; |
54012638 | 925 | |
ba7f0ae5 DG |
926 | lkm = zmalloc(sizeof(struct ltt_kernel_metadata)); |
927 | chan = zmalloc(sizeof(struct lttng_channel)); | |
f3ed775e | 928 | if (lkm == NULL || chan == NULL) { |
df0f840b | 929 | PERROR("kernel metadata zmalloc"); |
54012638 DG |
930 | goto error; |
931 | } | |
932 | ||
d42266a4 JG |
933 | ret = lttng_strncpy( |
934 | chan->name, DEFAULT_METADATA_NAME, sizeof(chan->name)); | |
935 | if (ret) { | |
936 | ERR("Failed to initialize metadata channel name to `%s`", | |
937 | DEFAULT_METADATA_NAME); | |
938 | goto error; | |
939 | } | |
940 | ||
54012638 | 941 | /* Set default attributes */ |
d42266a4 | 942 | chan->attr.overwrite = DEFAULT_METADATA_OVERWRITE; |
3e230f92 | 943 | chan->attr.subbuf_size = default_get_metadata_subbuf_size(); |
b389abbe | 944 | chan->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; |
d42266a4 JG |
945 | chan->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; |
946 | chan->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER;; | |
947 | ||
948 | ||
949 | /* | |
950 | * The metadata channel of kernel sessions must use the "mmap" | |
951 | * back-end since the consumer daemon accumulates complete | |
952 | * metadata units before sending them to the relay daemon in | |
953 | * live mode. The consumer daemon also needs to extract the contents | |
954 | * of the metadata cache when computing a rotation position. | |
955 | * | |
956 | * In both cases, it is not possible to rely on the splice | |
957 | * back-end as the consumer daemon may need to accumulate more | |
958 | * content than can be backed by the ring buffer's underlying | |
959 | * pages. | |
960 | */ | |
961 | chan->attr.output = LTTNG_EVENT_MMAP; | |
962 | chan->attr.tracefile_size = 0; | |
963 | chan->attr.tracefile_count = 0; | |
964 | chan->attr.live_timer_interval = 0; | |
54012638 DG |
965 | |
966 | /* Init metadata */ | |
03550b58 | 967 | lkm->fd = -1; |
f3ed775e | 968 | lkm->conf = chan; |
54012638 DG |
969 | |
970 | return lkm; | |
971 | ||
972 | error: | |
a2c0da86 MD |
973 | free(lkm); |
974 | free(chan); | |
54012638 DG |
975 | return NULL; |
976 | } | |
977 | ||
978 | /* | |
050349bb DG |
979 | * Allocate and initialize a kernel stream. The stream is set to ACTIVE_FD by |
980 | * default. | |
54012638 | 981 | * |
050349bb | 982 | * Return pointer to structure or NULL. |
54012638 | 983 | */ |
00e2e675 DG |
984 | struct ltt_kernel_stream *trace_kernel_create_stream(const char *name, |
985 | unsigned int count) | |
54012638 | 986 | { |
00e2e675 | 987 | int ret; |
54012638 DG |
988 | struct ltt_kernel_stream *lks; |
989 | ||
0525e9ae DG |
990 | assert(name); |
991 | ||
ba7f0ae5 | 992 | lks = zmalloc(sizeof(struct ltt_kernel_stream)); |
54012638 | 993 | if (lks == NULL) { |
df0f840b | 994 | PERROR("kernel stream zmalloc"); |
54012638 DG |
995 | goto error; |
996 | } | |
997 | ||
00e2e675 | 998 | /* Set name */ |
535b8ff4 | 999 | ret = snprintf(lks->name, sizeof(lks->name), "%s_%u", name, count); |
00e2e675 DG |
1000 | if (ret < 0) { |
1001 | PERROR("snprintf stream name"); | |
1002 | goto error; | |
1003 | } | |
1004 | lks->name[sizeof(lks->name) - 1] = '\0'; | |
1005 | ||
54012638 | 1006 | /* Init stream */ |
03550b58 | 1007 | lks->fd = -1; |
54012638 | 1008 | lks->state = 0; |
ffe60014 | 1009 | lks->cpu = count; |
54012638 DG |
1010 | |
1011 | return lks; | |
1012 | ||
1013 | error: | |
1014 | return NULL; | |
1015 | } | |
c363b55d | 1016 | |
050349bb DG |
1017 | /* |
1018 | * Cleanup kernel stream structure. | |
1019 | */ | |
62499ad6 | 1020 | void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream) |
c363b55d | 1021 | { |
0525e9ae DG |
1022 | assert(stream); |
1023 | ||
33a2b854 | 1024 | DBG("[trace] Closing stream fd %d", stream->fd); |
c363b55d | 1025 | /* Close kernel fd */ |
03550b58 | 1026 | if (stream->fd >= 0) { |
c617c0c6 MD |
1027 | int ret; |
1028 | ||
03550b58 MD |
1029 | ret = close(stream->fd); |
1030 | if (ret) { | |
1031 | PERROR("close"); | |
1032 | } | |
799e2c4f | 1033 | } |
c363b55d DG |
1034 | /* Remove from stream list */ |
1035 | cds_list_del(&stream->list); | |
f9815039 | 1036 | |
c363b55d DG |
1037 | free(stream); |
1038 | } | |
1039 | ||
050349bb DG |
1040 | /* |
1041 | * Cleanup kernel event structure. | |
1042 | */ | |
62499ad6 | 1043 | void trace_kernel_destroy_event(struct ltt_kernel_event *event) |
c363b55d | 1044 | { |
0525e9ae DG |
1045 | assert(event); |
1046 | ||
87eb4ab8 | 1047 | if (event->fd >= 0) { |
c617c0c6 MD |
1048 | int ret; |
1049 | ||
87eb4ab8 MD |
1050 | DBG("[trace] Closing event fd %d", event->fd); |
1051 | /* Close kernel fd */ | |
799e2c4f MD |
1052 | ret = close(event->fd); |
1053 | if (ret) { | |
1054 | PERROR("close"); | |
1055 | } | |
87eb4ab8 | 1056 | } else { |
352b58f5 | 1057 | DBG("[trace] Tearing down event (no associated file descriptor)"); |
87eb4ab8 | 1058 | } |
c363b55d DG |
1059 | |
1060 | /* Remove from event list */ | |
1061 | cds_list_del(&event->list); | |
f9815039 | 1062 | |
00a62084 MD |
1063 | free(event->filter_expression); |
1064 | free(event->filter); | |
1065 | ||
f9815039 | 1066 | free(event->event); |
c363b55d DG |
1067 | free(event); |
1068 | } | |
1069 | ||
c3e68e71 JR |
1070 | /* |
1071 | * Free kernel event counter structure from RCU context | |
1072 | */ | |
1073 | static void free_event_counter_rcu(struct rcu_head *rcu_node) | |
1074 | { | |
1075 | struct ltt_kernel_event_counter *event_counter = caa_container_of(rcu_node, | |
1076 | struct ltt_kernel_event_counter, rcu_node); | |
1077 | ||
1078 | free(event_counter); | |
1079 | } | |
1080 | /* | |
1081 | * Cleanup kernel event counter structure. | |
1082 | */ | |
1083 | void trace_kernel_destroy_event_counter(struct ltt_kernel_event_counter *event_counter) | |
1084 | { | |
1085 | assert(event_counter); | |
1086 | ||
1087 | if (event_counter->fd >= 0) { | |
1088 | int ret; | |
1089 | ||
1090 | DBG("[trace] Closing event counter fd %d", event_counter->fd); | |
1091 | /* Close kernel fd */ | |
1092 | ret = close(event_counter->fd); | |
1093 | if (ret) { | |
1094 | PERROR("close"); | |
1095 | } | |
1096 | } else { | |
1097 | DBG("[trace] Tearing down event counter (no associated file descriptor)"); | |
1098 | } | |
1099 | ||
1100 | lttng_map_key_put(event_counter->key); | |
1101 | call_rcu(&event_counter->rcu_node, free_event_counter_rcu); | |
1102 | } | |
1103 | ||
1104 | ||
352b58f5 JR |
1105 | /* |
1106 | * Cleanup kernel event structure. | |
1107 | */ | |
1108 | static void free_token_event_rule_rcu(struct rcu_head *rcu_node) | |
1109 | { | |
1110 | struct ltt_kernel_event_notifier_rule *rule = caa_container_of(rcu_node, | |
1111 | struct ltt_kernel_event_notifier_rule, rcu_node); | |
1112 | ||
1113 | free(rule); | |
1114 | } | |
1115 | ||
1116 | void trace_kernel_destroy_event_notifier_rule( | |
1117 | struct ltt_kernel_event_notifier_rule *event) | |
1118 | { | |
1119 | assert(event); | |
1120 | ||
1121 | if (event->fd >= 0) { | |
1122 | const int ret = close(event->fd); | |
1123 | ||
1124 | DBG("Closing kernel event notifier rule file descriptor: fd = %d", | |
1125 | event->fd); | |
1126 | if (ret) { | |
1127 | PERROR("Failed to close kernel event notifier file descriptor: fd = %d", | |
1128 | event->fd); | |
1129 | } | |
1130 | } else { | |
1131 | DBG("Destroying kernel event notifier rule (no associated file descriptor)"); | |
1132 | } | |
1133 | ||
1134 | lttng_trigger_put(event->trigger); | |
1135 | call_rcu(&event->rcu_node, free_token_event_rule_rcu); | |
1136 | } | |
645328ae DG |
1137 | /* |
1138 | * Cleanup kernel context structure. | |
1139 | */ | |
1140 | void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) | |
1141 | { | |
1142 | assert(ctx); | |
1143 | ||
ba985c3a JG |
1144 | if (ctx->in_list) { |
1145 | cds_list_del(&ctx->list); | |
1146 | } | |
645328ae DG |
1147 | free(ctx); |
1148 | } | |
1149 | ||
050349bb DG |
1150 | /* |
1151 | * Cleanup kernel channel structure. | |
1152 | */ | |
62499ad6 | 1153 | void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) |
c363b55d | 1154 | { |
af9737e9 DG |
1155 | struct ltt_kernel_stream *stream, *stmp; |
1156 | struct ltt_kernel_event *event, *etmp; | |
645328ae | 1157 | struct ltt_kernel_context *ctx, *ctmp; |
799e2c4f | 1158 | int ret; |
e9404c27 | 1159 | enum lttng_error_code status; |
c363b55d | 1160 | |
0525e9ae DG |
1161 | assert(channel); |
1162 | ||
33a2b854 | 1163 | DBG("[trace] Closing channel fd %d", channel->fd); |
c363b55d | 1164 | /* Close kernel fd */ |
03550b58 MD |
1165 | if (channel->fd >= 0) { |
1166 | ret = close(channel->fd); | |
1167 | if (ret) { | |
1168 | PERROR("close"); | |
1169 | } | |
799e2c4f | 1170 | } |
c363b55d DG |
1171 | |
1172 | /* For each stream in the channel list */ | |
af9737e9 | 1173 | cds_list_for_each_entry_safe(stream, stmp, &channel->stream_list.head, list) { |
62499ad6 | 1174 | trace_kernel_destroy_stream(stream); |
c363b55d DG |
1175 | } |
1176 | ||
1177 | /* For each event in the channel list */ | |
af9737e9 | 1178 | cds_list_for_each_entry_safe(event, etmp, &channel->events_list.head, list) { |
62499ad6 | 1179 | trace_kernel_destroy_event(event); |
c363b55d DG |
1180 | } |
1181 | ||
645328ae DG |
1182 | /* For each context in the channel list */ |
1183 | cds_list_for_each_entry_safe(ctx, ctmp, &channel->ctx_list, list) { | |
1184 | trace_kernel_destroy_context(ctx); | |
1185 | } | |
1186 | ||
c363b55d DG |
1187 | /* Remove from channel list */ |
1188 | cds_list_del(&channel->list); | |
f9815039 | 1189 | |
753873bf JR |
1190 | if (notification_thread_handle |
1191 | && channel->published_to_notification_thread) { | |
63aaa3dc JG |
1192 | status = notification_thread_command_remove_channel( |
1193 | notification_thread_handle, | |
e1f3997a | 1194 | channel->key, LTTNG_DOMAIN_KERNEL); |
63aaa3dc JG |
1195 | assert(status == LTTNG_OK); |
1196 | } | |
e9404c27 | 1197 | free(channel->channel->attr.extended.ptr); |
f9815039 | 1198 | free(channel->channel); |
c363b55d DG |
1199 | free(channel); |
1200 | } | |
1201 | ||
c3e68e71 JR |
1202 | /* |
1203 | * Cleanup kernel map structure. | |
1204 | */ | |
1205 | void trace_kernel_destroy_map(struct ltt_kernel_map *map) | |
1206 | { | |
1207 | int ret; | |
1208 | struct ltt_kernel_event_counter *event_counter; | |
1209 | struct lttng_ht_iter iter; | |
1210 | ||
1211 | assert(map); | |
1212 | ||
1213 | DBG("[trace] Closing map fd %d", map->fd); | |
1214 | /* Close kernel fd */ | |
1215 | if (map->fd >= 0) { | |
1216 | ret = close(map->fd); | |
1217 | if (ret) { | |
1218 | PERROR("close"); | |
1219 | } | |
1220 | } | |
1221 | ||
1222 | /* For each event counter in the map hashtable */ | |
1223 | cds_lfht_for_each_entry(map->event_counters_ht->ht, &iter.iter, | |
1224 | event_counter, ht_node.node) { | |
1225 | trace_kernel_destroy_event_counter(event_counter); | |
1226 | } | |
1227 | ||
1228 | /* Remove from map list */ | |
1229 | cds_list_del(&map->list); | |
1230 | ||
1231 | free(map); | |
1232 | } | |
1233 | ||
050349bb DG |
1234 | /* |
1235 | * Cleanup kernel metadata structure. | |
1236 | */ | |
62499ad6 | 1237 | void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata) |
c363b55d | 1238 | { |
0525e9ae DG |
1239 | assert(metadata); |
1240 | ||
33a2b854 | 1241 | DBG("[trace] Closing metadata fd %d", metadata->fd); |
c363b55d | 1242 | /* Close kernel fd */ |
03550b58 | 1243 | if (metadata->fd >= 0) { |
c617c0c6 MD |
1244 | int ret; |
1245 | ||
03550b58 MD |
1246 | ret = close(metadata->fd); |
1247 | if (ret) { | |
1248 | PERROR("close"); | |
1249 | } | |
799e2c4f | 1250 | } |
c363b55d | 1251 | |
f9815039 | 1252 | free(metadata->conf); |
c363b55d DG |
1253 | free(metadata); |
1254 | } | |
1255 | ||
050349bb | 1256 | /* |
62499ad6 | 1257 | * Cleanup kernel session structure |
36b588ed MD |
1258 | * |
1259 | * Should *NOT* be called with RCU read-side lock held. | |
050349bb | 1260 | */ |
62499ad6 | 1261 | void trace_kernel_destroy_session(struct ltt_kernel_session *session) |
c363b55d | 1262 | { |
af9737e9 | 1263 | struct ltt_kernel_channel *channel, *ctmp; |
c3e68e71 | 1264 | struct ltt_kernel_map *map, *map_tmp; |
799e2c4f | 1265 | int ret; |
c363b55d | 1266 | |
0525e9ae DG |
1267 | assert(session); |
1268 | ||
33a2b854 | 1269 | DBG("[trace] Closing session fd %d", session->fd); |
c363b55d | 1270 | /* Close kernel fds */ |
03550b58 MD |
1271 | if (session->fd >= 0) { |
1272 | ret = close(session->fd); | |
1273 | if (ret) { | |
1274 | PERROR("close"); | |
1275 | } | |
799e2c4f | 1276 | } |
f9815039 | 1277 | |
03550b58 | 1278 | if (session->metadata_stream_fd >= 0) { |
70dc1c34 | 1279 | DBG("[trace] Closing metadata stream fd %d", session->metadata_stream_fd); |
799e2c4f MD |
1280 | ret = close(session->metadata_stream_fd); |
1281 | if (ret) { | |
1282 | PERROR("close"); | |
1283 | } | |
70dc1c34 | 1284 | } |
c363b55d | 1285 | |
d36b8583 | 1286 | if (session->metadata != NULL) { |
62499ad6 | 1287 | trace_kernel_destroy_metadata(session->metadata); |
d36b8583 | 1288 | } |
c363b55d | 1289 | |
af9737e9 | 1290 | cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) { |
62499ad6 | 1291 | trace_kernel_destroy_channel(channel); |
c363b55d | 1292 | } |
c3e68e71 JR |
1293 | |
1294 | cds_list_for_each_entry_safe(map, map_tmp, &session->map_list.head, list) { | |
1295 | trace_kernel_destroy_map(map); | |
1296 | } | |
d070c424 | 1297 | } |
c363b55d | 1298 | |
d070c424 MD |
1299 | /* Free elements needed by destroy notifiers. */ |
1300 | void trace_kernel_free_session(struct ltt_kernel_session *session) | |
1301 | { | |
00e2e675 | 1302 | /* Wipe consumer output object */ |
6addfa37 | 1303 | consumer_output_put(session->consumer); |
00e2e675 | 1304 | |
159b042f JG |
1305 | process_attr_tracker_destroy(session->tracker_pid); |
1306 | process_attr_tracker_destroy(session->tracker_vpid); | |
1307 | process_attr_tracker_destroy(session->tracker_uid); | |
1308 | process_attr_tracker_destroy(session->tracker_vuid); | |
1309 | process_attr_tracker_destroy(session->tracker_gid); | |
1310 | process_attr_tracker_destroy(session->tracker_vgid); | |
55c9e7ca | 1311 | |
c363b55d DG |
1312 | free(session); |
1313 | } |