Commit | Line | Data |
---|---|---|
54012638 | 1 | /* |
21cf9b6b | 2 | * Copyright (C) 2011 EfficiOS Inc. |
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> | |
352b58f5 | 16 | #include <lttng/kernel-probe.h> |
dcabc190 | 17 | #include <lttng/userspace-probe.h> |
c9e313bc | 18 | #include <lttng/userspace-probe-internal.hpp> |
352b58f5 | 19 | #include <lttng/event-rule/event-rule.h> |
c9e313bc | 20 | #include <lttng/event-rule/event-rule-internal.hpp> |
85522de5 | 21 | #include <lttng/event-rule/kernel-kprobe.h> |
c9e313bc | 22 | #include <lttng/event-rule/kernel-kprobe-internal.hpp> |
4f7da553 | 23 | #include <lttng/event-rule/kernel-syscall.h> |
c9e313bc | 24 | #include <lttng/event-rule/kernel-syscall-internal.hpp> |
695f7044 | 25 | #include <lttng/event-rule/kernel-tracepoint.h> |
c9e313bc | 26 | #include <lttng/event-rule/kernel-tracepoint-internal.hpp> |
695f7044 | 27 | #include <lttng/event-rule/kernel-uprobe.h> |
c9e313bc SM |
28 | #include <lttng/event-rule/kernel-uprobe-internal.hpp> |
29 | #include <common/common.hpp> | |
30 | #include <common/defaults.hpp> | |
31 | #include <common/trace-chunk.hpp> | |
32 | #include <common/macros.hpp> | |
1e307fab | 33 | |
c9e313bc SM |
34 | #include "consumer.hpp" |
35 | #include "trace-kernel.hpp" | |
36 | #include "lttng-sessiond.hpp" | |
37 | #include "notification-thread-commands.hpp" | |
54012638 | 38 | |
19e70852 | 39 | /* |
050349bb | 40 | * Find the channel name for the given kernel session. |
19e70852 | 41 | */ |
62499ad6 | 42 | struct ltt_kernel_channel *trace_kernel_get_channel_by_name( |
df4f5a87 | 43 | const char *name, struct ltt_kernel_session *session) |
19e70852 DG |
44 | { |
45 | struct ltt_kernel_channel *chan; | |
46 | ||
a0377dfe FD |
47 | LTTNG_ASSERT(session); |
48 | LTTNG_ASSERT(name); | |
19e70852 | 49 | |
85076754 MD |
50 | /* |
51 | * If we receive an empty string for channel name, it means the | |
52 | * default channel name is requested. | |
53 | */ | |
54 | if (name[0] == '\0') | |
55 | name = DEFAULT_CHANNEL_NAME; | |
56 | ||
54d01ffb DG |
57 | DBG("Trying to find channel %s", name); |
58 | ||
19e70852 DG |
59 | cds_list_for_each_entry(chan, &session->channel_list.head, list) { |
60 | if (strcmp(name, chan->channel->name) == 0) { | |
61 | DBG("Found channel by name %s", name); | |
62 | return chan; | |
63 | } | |
64 | } | |
65 | ||
19e70852 DG |
66 | return NULL; |
67 | } | |
68 | ||
00a62084 MD |
69 | /* |
70 | * Find the event for the given channel. | |
71 | */ | |
72 | struct ltt_kernel_event *trace_kernel_find_event( | |
73 | char *name, struct ltt_kernel_channel *channel, | |
74 | enum lttng_event_type type, | |
2b00d462 | 75 | struct lttng_bytecode *filter) |
00a62084 MD |
76 | { |
77 | struct ltt_kernel_event *ev; | |
78 | int found = 0; | |
79 | ||
a0377dfe FD |
80 | LTTNG_ASSERT(name); |
81 | LTTNG_ASSERT(channel); | |
00a62084 MD |
82 | |
83 | cds_list_for_each_entry(ev, &channel->events_list.head, list) { | |
84 | if (type != LTTNG_EVENT_ALL && ev->type != type) { | |
85 | continue; | |
86 | } | |
87 | if (strcmp(name, ev->event->name)) { | |
88 | continue; | |
89 | } | |
90 | if ((ev->filter && !filter) || (!ev->filter && filter)) { | |
91 | continue; | |
92 | } | |
93 | if (ev->filter && filter) { | |
94 | if (ev->filter->len != filter->len || | |
95 | memcmp(ev->filter->data, filter->data, | |
96 | filter->len) != 0) { | |
97 | continue; | |
98 | } | |
99 | } | |
100 | found = 1; | |
101 | break; | |
102 | } | |
103 | if (found) { | |
104 | DBG("Found event %s for channel %s", name, | |
105 | channel->channel->name); | |
106 | return ev; | |
107 | } else { | |
108 | return NULL; | |
109 | } | |
110 | } | |
111 | ||
19e70852 | 112 | /* |
050349bb | 113 | * Find the event name for the given channel. |
19e70852 | 114 | */ |
62499ad6 | 115 | struct ltt_kernel_event *trace_kernel_get_event_by_name( |
d0ae4ea8 MD |
116 | char *name, struct ltt_kernel_channel *channel, |
117 | enum lttng_event_type type) | |
19e70852 DG |
118 | { |
119 | struct ltt_kernel_event *ev; | |
00a62084 | 120 | int found = 0; |
19e70852 | 121 | |
a0377dfe FD |
122 | LTTNG_ASSERT(name); |
123 | LTTNG_ASSERT(channel); | |
19e70852 DG |
124 | |
125 | cds_list_for_each_entry(ev, &channel->events_list.head, list) { | |
00a62084 | 126 | if (type != LTTNG_EVENT_ALL && ev->type != type) { |
d0ae4ea8 | 127 | continue; |
19e70852 | 128 | } |
00a62084 MD |
129 | if (strcmp(name, ev->event->name)) { |
130 | continue; | |
131 | } | |
132 | found = 1; | |
133 | break; | |
134 | } | |
135 | if (found) { | |
136 | DBG("Found event %s for channel %s", name, | |
137 | channel->channel->name); | |
138 | return ev; | |
139 | } else { | |
140 | return NULL; | |
19e70852 | 141 | } |
19e70852 DG |
142 | } |
143 | ||
54012638 | 144 | /* |
050349bb | 145 | * Allocate and initialize a kernel session data structure. |
54012638 | 146 | * |
050349bb | 147 | * Return pointer to structure or NULL. |
54012638 | 148 | */ |
dec56f6c | 149 | struct ltt_kernel_session *trace_kernel_create_session(void) |
54012638 | 150 | { |
a4b92340 | 151 | struct ltt_kernel_session *lks = NULL; |
54012638 DG |
152 | |
153 | /* Allocate a new ltt kernel session */ | |
dd7cc721 | 154 | lks = new ltt_kernel_session; |
54012638 | 155 | if (lks == NULL) { |
df0f840b | 156 | PERROR("create kernel session zmalloc"); |
a4b92340 | 157 | goto alloc_error; |
54012638 DG |
158 | } |
159 | ||
dd7cc721 JR |
160 | lks->active = 0; |
161 | ||
54012638 | 162 | /* Init data structure */ |
54012638 DG |
163 | CDS_INIT_LIST_HEAD(&lks->channel_list.head); |
164 | ||
159b042f JG |
165 | lks->tracker_pid = process_attr_tracker_create(); |
166 | if (!lks->tracker_pid) { | |
55c9e7ca JR |
167 | goto error; |
168 | } | |
159b042f JG |
169 | lks->tracker_vpid = process_attr_tracker_create(); |
170 | if (!lks->tracker_vpid) { | |
55c9e7ca JR |
171 | goto error; |
172 | } | |
159b042f JG |
173 | lks->tracker_uid = process_attr_tracker_create(); |
174 | if (!lks->tracker_uid) { | |
55c9e7ca JR |
175 | goto error; |
176 | } | |
159b042f JG |
177 | lks->tracker_vuid = process_attr_tracker_create(); |
178 | if (!lks->tracker_vuid) { | |
55c9e7ca JR |
179 | goto error; |
180 | } | |
159b042f JG |
181 | lks->tracker_gid = process_attr_tracker_create(); |
182 | if (!lks->tracker_gid) { | |
55c9e7ca JR |
183 | goto error; |
184 | } | |
159b042f JG |
185 | lks->tracker_vgid = process_attr_tracker_create(); |
186 | if (!lks->tracker_vgid) { | |
55c9e7ca JR |
187 | goto error; |
188 | } | |
00e2e675 DG |
189 | lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); |
190 | if (lks->consumer == NULL) { | |
191 | goto error; | |
192 | } | |
193 | ||
54012638 DG |
194 | return lks; |
195 | ||
196 | error: | |
159b042f JG |
197 | process_attr_tracker_destroy(lks->tracker_pid); |
198 | process_attr_tracker_destroy(lks->tracker_vpid); | |
199 | process_attr_tracker_destroy(lks->tracker_uid); | |
200 | process_attr_tracker_destroy(lks->tracker_vuid); | |
201 | process_attr_tracker_destroy(lks->tracker_gid); | |
202 | process_attr_tracker_destroy(lks->tracker_vgid); | |
dd7cc721 | 203 | delete (lks); |
a4b92340 DG |
204 | |
205 | alloc_error: | |
54012638 DG |
206 | return NULL; |
207 | } | |
208 | ||
209 | /* | |
050349bb | 210 | * Allocate and initialize a kernel channel data structure. |
54012638 | 211 | * |
050349bb | 212 | * Return pointer to structure or NULL. |
54012638 | 213 | */ |
00e2e675 | 214 | struct ltt_kernel_channel *trace_kernel_create_channel( |
fdd9eb17 | 215 | struct lttng_channel *chan) |
54012638 | 216 | { |
54012638 | 217 | struct ltt_kernel_channel *lkc; |
61a5b6b1 | 218 | struct lttng_channel_extended *extended = NULL; |
54012638 | 219 | |
a0377dfe | 220 | LTTNG_ASSERT(chan); |
0525e9ae | 221 | |
64803277 | 222 | lkc = zmalloc<ltt_kernel_channel>(); |
f3ed775e | 223 | if (lkc == NULL) { |
df0f840b | 224 | PERROR("ltt_kernel_channel zmalloc"); |
54012638 DG |
225 | goto error; |
226 | } | |
227 | ||
64803277 | 228 | lkc->channel = zmalloc<lttng_channel>(); |
f3ed775e | 229 | if (lkc->channel == NULL) { |
df0f840b | 230 | PERROR("lttng_channel zmalloc"); |
e9404c27 JG |
231 | goto error; |
232 | } | |
233 | ||
64803277 | 234 | extended = zmalloc<lttng_channel_extended>(); |
e9404c27 JG |
235 | if (!extended) { |
236 | PERROR("lttng_channel_channel zmalloc"); | |
f3ed775e DG |
237 | goto error; |
238 | } | |
239 | memcpy(lkc->channel, chan, sizeof(struct lttng_channel)); | |
e9404c27 JG |
240 | memcpy(extended, chan->attr.extended.ptr, sizeof(struct lttng_channel_extended)); |
241 | lkc->channel->attr.extended.ptr = extended; | |
242 | extended = NULL; | |
54012638 | 243 | |
85076754 MD |
244 | /* |
245 | * If we receive an empty string for channel name, it means the | |
246 | * default channel name is requested. | |
247 | */ | |
248 | if (chan->name[0] == '\0') { | |
249 | strncpy(lkc->channel->name, DEFAULT_CHANNEL_NAME, | |
250 | sizeof(lkc->channel->name)); | |
251 | } | |
b8e2fb80 | 252 | lkc->channel->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; |
85076754 | 253 | |
03550b58 | 254 | lkc->fd = -1; |
54012638 | 255 | lkc->stream_count = 0; |
cbbbb275 | 256 | lkc->event_count = 0; |
d36b8583 | 257 | lkc->enabled = 1; |
753873bf | 258 | lkc->published_to_notification_thread = false; |
54012638 DG |
259 | /* Init linked list */ |
260 | CDS_INIT_LIST_HEAD(&lkc->events_list.head); | |
261 | CDS_INIT_LIST_HEAD(&lkc->stream_list.head); | |
645328ae | 262 | CDS_INIT_LIST_HEAD(&lkc->ctx_list); |
54012638 DG |
263 | |
264 | return lkc; | |
265 | ||
266 | error: | |
e9404c27 JG |
267 | if (lkc) { |
268 | free(lkc->channel); | |
269 | } | |
270 | free(extended); | |
271 | free(lkc); | |
54012638 DG |
272 | return NULL; |
273 | } | |
274 | ||
645328ae DG |
275 | /* |
276 | * Allocate and init a kernel context object. | |
277 | * | |
278 | * Return the allocated object or NULL on error. | |
279 | */ | |
280 | struct ltt_kernel_context *trace_kernel_create_context( | |
b8e2fb80 | 281 | struct lttng_kernel_abi_context *ctx) |
645328ae DG |
282 | { |
283 | struct ltt_kernel_context *kctx; | |
284 | ||
64803277 | 285 | kctx = zmalloc<ltt_kernel_context>(); |
645328ae DG |
286 | if (!kctx) { |
287 | PERROR("zmalloc kernel context"); | |
288 | goto error; | |
289 | } | |
290 | ||
291 | if (ctx) { | |
292 | memcpy(&kctx->ctx, ctx, sizeof(kctx->ctx)); | |
293 | } | |
df3c77c8 JG |
294 | error: |
295 | return kctx; | |
296 | } | |
645328ae | 297 | |
df3c77c8 JG |
298 | /* |
299 | * Allocate and init a kernel context object from an existing kernel context | |
300 | * object. | |
301 | * | |
302 | * Return the allocated object or NULL on error. | |
303 | */ | |
304 | struct ltt_kernel_context *trace_kernel_copy_context( | |
305 | struct ltt_kernel_context *kctx) | |
306 | { | |
307 | struct ltt_kernel_context *kctx_copy; | |
308 | ||
a0377dfe | 309 | LTTNG_ASSERT(kctx); |
64803277 | 310 | kctx_copy = zmalloc<ltt_kernel_context>(); |
df3c77c8 JG |
311 | if (!kctx_copy) { |
312 | PERROR("zmalloc ltt_kernel_context"); | |
313 | goto error; | |
314 | } | |
315 | ||
316 | memcpy(kctx_copy, kctx, sizeof(*kctx_copy)); | |
317 | memset(&kctx_copy->list, 0, sizeof(kctx_copy->list)); | |
7b9445b3 | 318 | |
645328ae | 319 | error: |
df3c77c8 | 320 | return kctx_copy; |
645328ae DG |
321 | } |
322 | ||
54012638 | 323 | /* |
050349bb | 324 | * Allocate and initialize a kernel event. Set name and event type. |
a969e101 | 325 | * We own filter_expression, and filter. |
54012638 | 326 | * |
050349bb | 327 | * Return pointer to structure or NULL. |
54012638 | 328 | */ |
71a3bb01 FD |
329 | enum lttng_error_code trace_kernel_create_event( |
330 | struct lttng_event *ev, char *filter_expression, | |
2b00d462 | 331 | struct lttng_bytecode *filter, |
71a3bb01 | 332 | struct ltt_kernel_event **kernel_event) |
54012638 | 333 | { |
71a3bb01 | 334 | enum lttng_error_code ret; |
b8e2fb80 | 335 | struct lttng_kernel_abi_event *attr; |
71a3bb01 | 336 | struct ltt_kernel_event *local_kernel_event; |
dcabc190 | 337 | struct lttng_userspace_probe_location *userspace_probe_location = NULL; |
54012638 | 338 | |
a0377dfe | 339 | LTTNG_ASSERT(ev); |
0525e9ae | 340 | |
64803277 SM |
341 | local_kernel_event = zmalloc<ltt_kernel_event>(); |
342 | attr = zmalloc<lttng_kernel_abi_event>(); | |
71a3bb01 | 343 | if (local_kernel_event == NULL || attr == NULL) { |
df0f840b | 344 | PERROR("kernel event zmalloc"); |
71a3bb01 | 345 | ret = LTTNG_ERR_NOMEM; |
54012638 DG |
346 | goto error; |
347 | } | |
348 | ||
f3ed775e | 349 | switch (ev->type) { |
7d29a247 | 350 | case LTTNG_EVENT_PROBE: |
b8e2fb80 | 351 | attr->instrumentation = LTTNG_KERNEL_ABI_KPROBE; |
7d29a247 DG |
352 | attr->u.kprobe.addr = ev->attr.probe.addr; |
353 | attr->u.kprobe.offset = ev->attr.probe.offset; | |
f3ed775e | 354 | strncpy(attr->u.kprobe.symbol_name, |
b8e2fb80 FD |
355 | ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
356 | attr->u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 357 | break; |
dcabc190 FD |
358 | case LTTNG_EVENT_USERSPACE_PROBE: |
359 | { | |
87597c2c JG |
360 | const struct lttng_userspace_probe_location* location = NULL; |
361 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
dcabc190 FD |
362 | |
363 | location = lttng_event_get_userspace_probe_location(ev); | |
364 | if (!location) { | |
365 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
366 | goto error; | |
367 | } | |
368 | ||
369 | /* | |
370 | * From this point on, the specific term 'uprobe' is used | |
371 | * instead of the generic 'userspace probe' because it's the | |
372 | * technology used at the moment for this instrumentation. | |
373 | * LTTng currently implements userspace probes using uprobes. | |
374 | * In the interactions with the kernel tracer, we use the | |
375 | * uprobe term. | |
376 | */ | |
b8e2fb80 | 377 | attr->instrumentation = LTTNG_KERNEL_ABI_UPROBE; |
dcabc190 | 378 | |
dcabc190 FD |
379 | lookup = lttng_userspace_probe_location_get_lookup_method( |
380 | location); | |
381 | if (!lookup) { | |
382 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
383 | goto error; | |
384 | } | |
385 | ||
386 | /* | |
387 | * From the kernel tracer's perspective, all userspace probe | |
388 | * event types are all the same: a file and an offset. | |
389 | */ | |
390 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
391 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
392 | /* Get the file descriptor on the target binary. */ | |
393 | attr->u.uprobe.fd = | |
394 | lttng_userspace_probe_location_function_get_binary_fd(location); | |
395 | ||
396 | /* | |
397 | * Save a reference to the probe location used during | |
e368fb43 | 398 | * the listing of events. |
dcabc190 FD |
399 | */ |
400 | userspace_probe_location = | |
401 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
402 | break; |
403 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
404 | /* Get the file descriptor on the target binary. */ | |
405 | attr->u.uprobe.fd = | |
406 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); | |
407 | ||
408 | /* | |
409 | * Save a reference to the probe location used during the listing of | |
e368fb43 | 410 | * events. |
dcabc190 FD |
411 | */ |
412 | userspace_probe_location = | |
413 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
414 | break; |
415 | default: | |
416 | DBG("Unsupported lookup method type"); | |
417 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
418 | goto error; | |
419 | } | |
420 | break; | |
421 | } | |
f3ed775e | 422 | case LTTNG_EVENT_FUNCTION: |
b8e2fb80 | 423 | attr->instrumentation = LTTNG_KERNEL_ABI_KRETPROBE; |
8f0d098b MD |
424 | attr->u.kretprobe.addr = ev->attr.probe.addr; |
425 | attr->u.kretprobe.offset = ev->attr.probe.offset; | |
8f0d098b | 426 | strncpy(attr->u.kretprobe.symbol_name, |
b8e2fb80 FD |
427 | ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
428 | attr->u.kretprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
8f0d098b MD |
429 | break; |
430 | case LTTNG_EVENT_FUNCTION_ENTRY: | |
b8e2fb80 | 431 | attr->instrumentation = LTTNG_KERNEL_ABI_FUNCTION; |
f3ed775e | 432 | strncpy(attr->u.ftrace.symbol_name, |
b8e2fb80 FD |
433 | ev->attr.ftrace.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
434 | attr->u.ftrace.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 435 | break; |
e6ddca71 | 436 | case LTTNG_EVENT_TRACEPOINT: |
b8e2fb80 | 437 | attr->instrumentation = LTTNG_KERNEL_ABI_TRACEPOINT; |
f3ed775e | 438 | break; |
a54bd42d | 439 | case LTTNG_EVENT_SYSCALL: |
b8e2fb80 FD |
440 | attr->instrumentation = LTTNG_KERNEL_ABI_SYSCALL; |
441 | attr->u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; | |
442 | attr->u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; | |
443 | attr->u.syscall.match = LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; | |
0133c199 | 444 | break; |
7a3d1328 | 445 | case LTTNG_EVENT_ALL: |
b8e2fb80 | 446 | attr->instrumentation = LTTNG_KERNEL_ABI_ALL; |
7a3d1328 | 447 | break; |
f3ed775e DG |
448 | default: |
449 | ERR("Unknown kernel instrumentation type (%d)", ev->type); | |
71a3bb01 | 450 | ret = LTTNG_ERR_INVALID; |
f3ed775e DG |
451 | goto error; |
452 | } | |
453 | ||
454 | /* Copy event name */ | |
b8e2fb80 FD |
455 | strncpy(attr->name, ev->name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
456 | attr->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 457 | |
54012638 | 458 | /* Setting up a kernel event */ |
71a3bb01 FD |
459 | local_kernel_event->fd = -1; |
460 | local_kernel_event->event = attr; | |
461 | local_kernel_event->enabled = 1; | |
462 | local_kernel_event->filter_expression = filter_expression; | |
463 | local_kernel_event->filter = filter; | |
dcabc190 | 464 | local_kernel_event->userspace_probe_location = userspace_probe_location; |
54012638 | 465 | |
71a3bb01 FD |
466 | *kernel_event = local_kernel_event; |
467 | ||
468 | return LTTNG_OK; | |
54012638 DG |
469 | |
470 | error: | |
a969e101 MD |
471 | free(filter_expression); |
472 | free(filter); | |
71a3bb01 | 473 | free(local_kernel_event); |
a2c0da86 | 474 | free(attr); |
71a3bb01 | 475 | return ret; |
54012638 DG |
476 | } |
477 | ||
352b58f5 JR |
478 | /* |
479 | * Allocate and initialize a kernel token event rule. | |
480 | * | |
481 | * Return pointer to structure or NULL. | |
482 | */ | |
483 | enum lttng_error_code trace_kernel_create_event_notifier_rule( | |
484 | struct lttng_trigger *trigger, | |
485 | uint64_t token, | |
90aa04a1 | 486 | uint64_t error_counter_index, |
352b58f5 JR |
487 | struct ltt_kernel_event_notifier_rule **event_notifier_rule) |
488 | { | |
489 | enum lttng_error_code ret = LTTNG_OK; | |
490 | enum lttng_condition_type condition_type; | |
491 | enum lttng_event_rule_type event_rule_type; | |
492 | enum lttng_condition_status condition_status; | |
493 | struct ltt_kernel_event_notifier_rule *local_kernel_token_event_rule; | |
494 | const struct lttng_condition *condition = NULL; | |
495 | const struct lttng_event_rule *event_rule = NULL; | |
496 | ||
a0377dfe | 497 | LTTNG_ASSERT(event_notifier_rule); |
352b58f5 | 498 | |
7c1f6da2 | 499 | condition = lttng_trigger_get_const_condition(trigger); |
a0377dfe | 500 | LTTNG_ASSERT(condition); |
352b58f5 JR |
501 | |
502 | condition_type = lttng_condition_get_type(condition); | |
a0377dfe | 503 | LTTNG_ASSERT(condition_type == LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES); |
352b58f5 | 504 | |
8dbb86b8 | 505 | condition_status = lttng_condition_event_rule_matches_get_rule( |
352b58f5 | 506 | condition, &event_rule); |
a0377dfe FD |
507 | LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK); |
508 | LTTNG_ASSERT(event_rule); | |
352b58f5 JR |
509 | |
510 | event_rule_type = lttng_event_rule_get_type(event_rule); | |
a0377dfe | 511 | LTTNG_ASSERT(event_rule_type != LTTNG_EVENT_RULE_TYPE_UNKNOWN); |
352b58f5 JR |
512 | |
513 | local_kernel_token_event_rule = | |
64803277 | 514 | zmalloc<ltt_kernel_event_notifier_rule>(); |
352b58f5 JR |
515 | if (local_kernel_token_event_rule == NULL) { |
516 | PERROR("Failed to allocate ltt_kernel_token_event_rule structure"); | |
517 | ret = LTTNG_ERR_NOMEM; | |
518 | goto error; | |
519 | } | |
520 | ||
521 | local_kernel_token_event_rule->fd = -1; | |
522 | local_kernel_token_event_rule->enabled = 1; | |
523 | local_kernel_token_event_rule->token = token; | |
90aa04a1 | 524 | local_kernel_token_event_rule->error_counter_index = error_counter_index; |
352b58f5 JR |
525 | |
526 | /* Get the reference of the event rule. */ | |
527 | lttng_trigger_get(trigger); | |
528 | ||
529 | local_kernel_token_event_rule->trigger = trigger; | |
530 | /* The event rule still owns the filter and bytecode. */ | |
531 | local_kernel_token_event_rule->filter = | |
532 | lttng_event_rule_get_filter_bytecode(event_rule); | |
533 | ||
534 | DBG3("Created kernel event notifier rule: token = %" PRIu64, | |
535 | local_kernel_token_event_rule->token); | |
536 | error: | |
537 | *event_notifier_rule = local_kernel_token_event_rule; | |
538 | return ret; | |
539 | } | |
540 | ||
541 | /* | |
542 | * Initialize a kernel trigger from an event rule. | |
543 | */ | |
544 | enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule( | |
545 | const struct lttng_event_rule *rule, | |
b8e2fb80 | 546 | struct lttng_kernel_abi_event_notifier *kernel_event_notifier) |
352b58f5 | 547 | { |
366a83b3 | 548 | enum lttng_error_code ret_code; |
352b58f5 | 549 | const char *name; |
366a83b3 | 550 | int strncpy_ret; |
352b58f5 JR |
551 | |
552 | switch (lttng_event_rule_get_type(rule)) { | |
85522de5 | 553 | case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE: |
352b58f5 JR |
554 | { |
555 | uint64_t address = 0, offset = 0; | |
556 | const char *symbol_name = NULL; | |
557 | const struct lttng_kernel_probe_location *location = NULL; | |
558 | enum lttng_kernel_probe_location_status k_status; | |
559 | enum lttng_event_rule_status status; | |
560 | ||
85522de5 | 561 | status = lttng_event_rule_kernel_kprobe_get_location(rule, &location); |
352b58f5 | 562 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 563 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
564 | goto error; |
565 | } | |
566 | ||
567 | switch (lttng_kernel_probe_location_get_type(location)) { | |
568 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
569 | { | |
570 | k_status = lttng_kernel_probe_location_address_get_address( | |
571 | location, &address); | |
a0377dfe | 572 | LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
352b58f5 JR |
573 | break; |
574 | } | |
575 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
576 | { | |
577 | k_status = lttng_kernel_probe_location_symbol_get_offset( | |
578 | location, &offset); | |
a0377dfe | 579 | LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
352b58f5 JR |
580 | symbol_name = lttng_kernel_probe_location_symbol_get_name( |
581 | location); | |
582 | break; | |
583 | } | |
584 | default: | |
585 | abort(); | |
586 | } | |
587 | ||
b8e2fb80 | 588 | kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_KPROBE; |
352b58f5 JR |
589 | kernel_event_notifier->event.u.kprobe.addr = address; |
590 | kernel_event_notifier->event.u.kprobe.offset = offset; | |
591 | if (symbol_name) { | |
366a83b3 | 592 | strncpy_ret = lttng_strncpy( |
352b58f5 | 593 | kernel_event_notifier->event.u.kprobe.symbol_name, |
2d6df81a JG |
594 | symbol_name, |
595 | sizeof(kernel_event_notifier->event.u.kprobe.symbol_name)); | |
352b58f5 | 596 | |
366a83b3 JG |
597 | if (strncpy_ret) { |
598 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
599 | goto error; |
600 | } | |
601 | } | |
602 | ||
b8e2fb80 | 603 | kernel_event_notifier->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; |
f2791161 | 604 | |
85522de5 | 605 | status = lttng_event_rule_kernel_kprobe_get_event_name(rule, &name); |
a0377dfe | 606 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 607 | ret_code = LTTNG_OK; |
352b58f5 JR |
608 | break; |
609 | } | |
46fd07ac | 610 | case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE: |
352b58f5 JR |
611 | { |
612 | const struct lttng_userspace_probe_location* location = NULL; | |
613 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
614 | enum lttng_event_rule_status status; | |
615 | ||
46fd07ac | 616 | status = lttng_event_rule_kernel_uprobe_get_location(rule, &location); |
352b58f5 | 617 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 618 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
619 | goto error; |
620 | } | |
621 | ||
b8e2fb80 | 622 | kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_UPROBE; |
352b58f5 JR |
623 | |
624 | lookup = lttng_userspace_probe_location_get_lookup_method( | |
625 | location); | |
626 | if (!lookup) { | |
366a83b3 | 627 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
628 | goto error; |
629 | } | |
630 | ||
631 | /* | |
632 | * From the kernel tracer's perspective, all userspace probe | |
633 | * event types are all the same: a file and an offset. | |
634 | */ | |
635 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
636 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
637 | /* Get the file descriptor on the target binary. */ | |
638 | kernel_event_notifier->event.u.uprobe.fd = | |
639 | lttng_userspace_probe_location_function_get_binary_fd(location); | |
640 | ||
641 | break; | |
642 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
643 | /* Get the file descriptor on the target binary. */ | |
644 | kernel_event_notifier->event.u.uprobe.fd = | |
645 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); | |
646 | break; | |
647 | default: | |
648 | abort(); | |
649 | } | |
650 | ||
46fd07ac | 651 | status = lttng_event_rule_kernel_uprobe_get_event_name( |
405f9e7d | 652 | rule, &name); |
a0377dfe | 653 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 654 | ret_code = LTTNG_OK; |
352b58f5 JR |
655 | break; |
656 | } | |
695f7044 | 657 | case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT: |
352b58f5 | 658 | { |
352b58f5 | 659 | const enum lttng_event_rule_status status = |
695f7044 | 660 | lttng_event_rule_kernel_tracepoint_get_name_pattern( |
352b58f5 JR |
661 | rule, &name); |
662 | ||
a0377dfe | 663 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
352b58f5 | 664 | kernel_event_notifier->event.instrumentation = |
b8e2fb80 | 665 | LTTNG_KERNEL_ABI_TRACEPOINT; |
352b58f5 | 666 | |
366a83b3 | 667 | ret_code = LTTNG_OK; |
352b58f5 JR |
668 | break; |
669 | } | |
4f7da553 | 670 | case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL: |
352b58f5 JR |
671 | { |
672 | const enum lttng_event_rule_status status = | |
4f7da553 | 673 | lttng_event_rule_kernel_syscall_get_name_pattern( |
352b58f5 | 674 | rule, &name); |
4f7da553 | 675 | const enum lttng_event_rule_kernel_syscall_emission_site |
f6a5af19 | 676 | emission_site = |
4f7da553 | 677 | lttng_event_rule_kernel_syscall_get_emission_site(rule); |
b8e2fb80 | 678 | enum lttng_kernel_abi_syscall_entryexit entryexit; |
352b58f5 | 679 | |
a0377dfe FD |
680 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
681 | LTTNG_ASSERT(emission_site != LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN); | |
57739a6b | 682 | |
f6a5af19 | 683 | switch(emission_site) { |
4f7da553 | 684 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: |
b8e2fb80 | 685 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY; |
57739a6b | 686 | break; |
4f7da553 | 687 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: |
b8e2fb80 | 688 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT; |
57739a6b | 689 | break; |
4f7da553 | 690 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: |
b8e2fb80 | 691 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; |
57739a6b JR |
692 | break; |
693 | default: | |
694 | abort(); | |
695 | break; | |
696 | } | |
352b58f5 JR |
697 | |
698 | kernel_event_notifier->event.instrumentation = | |
b8e2fb80 | 699 | LTTNG_KERNEL_ABI_SYSCALL; |
352b58f5 | 700 | kernel_event_notifier->event.u.syscall.abi = |
b8e2fb80 | 701 | LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; |
352b58f5 | 702 | kernel_event_notifier->event.u.syscall.entryexit = |
57739a6b | 703 | entryexit; |
352b58f5 | 704 | kernel_event_notifier->event.u.syscall.match = |
b8e2fb80 | 705 | LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; |
366a83b3 | 706 | ret_code = LTTNG_OK; |
352b58f5 JR |
707 | break; |
708 | } | |
352b58f5 JR |
709 | default: |
710 | abort(); | |
711 | break; | |
712 | } | |
713 | ||
366a83b3 | 714 | strncpy_ret = lttng_strncpy(kernel_event_notifier->event.name, name, |
b8e2fb80 | 715 | LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
366a83b3 JG |
716 | if (strncpy_ret) { |
717 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
718 | goto error; |
719 | } | |
720 | ||
721 | error: | |
366a83b3 | 722 | return ret_code; |
352b58f5 | 723 | } |
54012638 | 724 | /* |
050349bb | 725 | * Allocate and initialize a kernel metadata. |
54012638 | 726 | * |
050349bb | 727 | * Return pointer to structure or NULL. |
54012638 | 728 | */ |
a4b92340 | 729 | struct ltt_kernel_metadata *trace_kernel_create_metadata(void) |
54012638 | 730 | { |
d42266a4 | 731 | int ret; |
54012638 | 732 | struct ltt_kernel_metadata *lkm; |
f3ed775e | 733 | struct lttng_channel *chan; |
54012638 | 734 | |
64803277 SM |
735 | lkm = zmalloc<ltt_kernel_metadata>(); |
736 | chan = zmalloc<lttng_channel>(); | |
f3ed775e | 737 | if (lkm == NULL || chan == NULL) { |
df0f840b | 738 | PERROR("kernel metadata zmalloc"); |
54012638 DG |
739 | goto error; |
740 | } | |
741 | ||
d42266a4 JG |
742 | ret = lttng_strncpy( |
743 | chan->name, DEFAULT_METADATA_NAME, sizeof(chan->name)); | |
744 | if (ret) { | |
745 | ERR("Failed to initialize metadata channel name to `%s`", | |
746 | DEFAULT_METADATA_NAME); | |
747 | goto error; | |
748 | } | |
749 | ||
54012638 | 750 | /* Set default attributes */ |
d42266a4 | 751 | chan->attr.overwrite = DEFAULT_METADATA_OVERWRITE; |
3e230f92 | 752 | chan->attr.subbuf_size = default_get_metadata_subbuf_size(); |
b389abbe | 753 | chan->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; |
d42266a4 JG |
754 | chan->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; |
755 | chan->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER;; | |
756 | ||
757 | ||
758 | /* | |
759 | * The metadata channel of kernel sessions must use the "mmap" | |
760 | * back-end since the consumer daemon accumulates complete | |
761 | * metadata units before sending them to the relay daemon in | |
762 | * live mode. The consumer daemon also needs to extract the contents | |
763 | * of the metadata cache when computing a rotation position. | |
764 | * | |
765 | * In both cases, it is not possible to rely on the splice | |
766 | * back-end as the consumer daemon may need to accumulate more | |
767 | * content than can be backed by the ring buffer's underlying | |
768 | * pages. | |
769 | */ | |
770 | chan->attr.output = LTTNG_EVENT_MMAP; | |
771 | chan->attr.tracefile_size = 0; | |
772 | chan->attr.tracefile_count = 0; | |
773 | chan->attr.live_timer_interval = 0; | |
54012638 DG |
774 | |
775 | /* Init metadata */ | |
03550b58 | 776 | lkm->fd = -1; |
f3ed775e | 777 | lkm->conf = chan; |
54012638 DG |
778 | |
779 | return lkm; | |
780 | ||
781 | error: | |
a2c0da86 MD |
782 | free(lkm); |
783 | free(chan); | |
54012638 DG |
784 | return NULL; |
785 | } | |
786 | ||
787 | /* | |
050349bb DG |
788 | * Allocate and initialize a kernel stream. The stream is set to ACTIVE_FD by |
789 | * default. | |
54012638 | 790 | * |
050349bb | 791 | * Return pointer to structure or NULL. |
54012638 | 792 | */ |
00e2e675 DG |
793 | struct ltt_kernel_stream *trace_kernel_create_stream(const char *name, |
794 | unsigned int count) | |
54012638 | 795 | { |
00e2e675 | 796 | int ret; |
54012638 DG |
797 | struct ltt_kernel_stream *lks; |
798 | ||
a0377dfe | 799 | LTTNG_ASSERT(name); |
0525e9ae | 800 | |
64803277 | 801 | lks = zmalloc<ltt_kernel_stream>(); |
54012638 | 802 | if (lks == NULL) { |
df0f840b | 803 | PERROR("kernel stream zmalloc"); |
54012638 DG |
804 | goto error; |
805 | } | |
806 | ||
00e2e675 | 807 | /* Set name */ |
535b8ff4 | 808 | ret = snprintf(lks->name, sizeof(lks->name), "%s_%u", name, count); |
00e2e675 DG |
809 | if (ret < 0) { |
810 | PERROR("snprintf stream name"); | |
811 | goto error; | |
812 | } | |
813 | lks->name[sizeof(lks->name) - 1] = '\0'; | |
814 | ||
54012638 | 815 | /* Init stream */ |
03550b58 | 816 | lks->fd = -1; |
54012638 | 817 | lks->state = 0; |
ffe60014 | 818 | lks->cpu = count; |
54012638 DG |
819 | |
820 | return lks; | |
821 | ||
822 | error: | |
823 | return NULL; | |
824 | } | |
c363b55d | 825 | |
050349bb DG |
826 | /* |
827 | * Cleanup kernel stream structure. | |
828 | */ | |
62499ad6 | 829 | void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream) |
c363b55d | 830 | { |
a0377dfe | 831 | LTTNG_ASSERT(stream); |
0525e9ae | 832 | |
33a2b854 | 833 | DBG("[trace] Closing stream fd %d", stream->fd); |
c363b55d | 834 | /* Close kernel fd */ |
03550b58 | 835 | if (stream->fd >= 0) { |
c617c0c6 MD |
836 | int ret; |
837 | ||
03550b58 MD |
838 | ret = close(stream->fd); |
839 | if (ret) { | |
840 | PERROR("close"); | |
841 | } | |
799e2c4f | 842 | } |
c363b55d DG |
843 | /* Remove from stream list */ |
844 | cds_list_del(&stream->list); | |
f9815039 | 845 | |
c363b55d DG |
846 | free(stream); |
847 | } | |
848 | ||
050349bb DG |
849 | /* |
850 | * Cleanup kernel event structure. | |
851 | */ | |
62499ad6 | 852 | void trace_kernel_destroy_event(struct ltt_kernel_event *event) |
c363b55d | 853 | { |
a0377dfe | 854 | LTTNG_ASSERT(event); |
0525e9ae | 855 | |
87eb4ab8 | 856 | if (event->fd >= 0) { |
c617c0c6 MD |
857 | int ret; |
858 | ||
87eb4ab8 MD |
859 | DBG("[trace] Closing event fd %d", event->fd); |
860 | /* Close kernel fd */ | |
799e2c4f MD |
861 | ret = close(event->fd); |
862 | if (ret) { | |
863 | PERROR("close"); | |
864 | } | |
87eb4ab8 | 865 | } else { |
352b58f5 | 866 | DBG("[trace] Tearing down event (no associated file descriptor)"); |
87eb4ab8 | 867 | } |
c363b55d DG |
868 | |
869 | /* Remove from event list */ | |
870 | cds_list_del(&event->list); | |
f9815039 | 871 | |
00a62084 MD |
872 | free(event->filter_expression); |
873 | free(event->filter); | |
874 | ||
f9815039 | 875 | free(event->event); |
c363b55d DG |
876 | free(event); |
877 | } | |
878 | ||
352b58f5 JR |
879 | /* |
880 | * Cleanup kernel event structure. | |
881 | */ | |
882 | static void free_token_event_rule_rcu(struct rcu_head *rcu_node) | |
883 | { | |
884 | struct ltt_kernel_event_notifier_rule *rule = caa_container_of(rcu_node, | |
885 | struct ltt_kernel_event_notifier_rule, rcu_node); | |
886 | ||
887 | free(rule); | |
888 | } | |
889 | ||
890 | void trace_kernel_destroy_event_notifier_rule( | |
891 | struct ltt_kernel_event_notifier_rule *event) | |
892 | { | |
a0377dfe | 893 | LTTNG_ASSERT(event); |
352b58f5 JR |
894 | |
895 | if (event->fd >= 0) { | |
896 | const int ret = close(event->fd); | |
897 | ||
898 | DBG("Closing kernel event notifier rule file descriptor: fd = %d", | |
899 | event->fd); | |
900 | if (ret) { | |
901 | PERROR("Failed to close kernel event notifier file descriptor: fd = %d", | |
902 | event->fd); | |
903 | } | |
904 | } else { | |
905 | DBG("Destroying kernel event notifier rule (no associated file descriptor)"); | |
906 | } | |
907 | ||
908 | lttng_trigger_put(event->trigger); | |
909 | call_rcu(&event->rcu_node, free_token_event_rule_rcu); | |
910 | } | |
645328ae DG |
911 | /* |
912 | * Cleanup kernel context structure. | |
913 | */ | |
914 | void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) | |
915 | { | |
a0377dfe | 916 | LTTNG_ASSERT(ctx); |
645328ae | 917 | |
ba985c3a JG |
918 | if (ctx->in_list) { |
919 | cds_list_del(&ctx->list); | |
920 | } | |
645328ae DG |
921 | free(ctx); |
922 | } | |
923 | ||
050349bb DG |
924 | /* |
925 | * Cleanup kernel channel structure. | |
926 | */ | |
62499ad6 | 927 | void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) |
c363b55d | 928 | { |
af9737e9 DG |
929 | struct ltt_kernel_stream *stream, *stmp; |
930 | struct ltt_kernel_event *event, *etmp; | |
645328ae | 931 | struct ltt_kernel_context *ctx, *ctmp; |
799e2c4f | 932 | int ret; |
e9404c27 | 933 | enum lttng_error_code status; |
c363b55d | 934 | |
a0377dfe | 935 | LTTNG_ASSERT(channel); |
0525e9ae | 936 | |
33a2b854 | 937 | DBG("[trace] Closing channel fd %d", channel->fd); |
c363b55d | 938 | /* Close kernel fd */ |
03550b58 MD |
939 | if (channel->fd >= 0) { |
940 | ret = close(channel->fd); | |
941 | if (ret) { | |
942 | PERROR("close"); | |
943 | } | |
799e2c4f | 944 | } |
c363b55d DG |
945 | |
946 | /* For each stream in the channel list */ | |
af9737e9 | 947 | cds_list_for_each_entry_safe(stream, stmp, &channel->stream_list.head, list) { |
62499ad6 | 948 | trace_kernel_destroy_stream(stream); |
c363b55d DG |
949 | } |
950 | ||
951 | /* For each event in the channel list */ | |
af9737e9 | 952 | cds_list_for_each_entry_safe(event, etmp, &channel->events_list.head, list) { |
62499ad6 | 953 | trace_kernel_destroy_event(event); |
c363b55d DG |
954 | } |
955 | ||
645328ae DG |
956 | /* For each context in the channel list */ |
957 | cds_list_for_each_entry_safe(ctx, ctmp, &channel->ctx_list, list) { | |
958 | trace_kernel_destroy_context(ctx); | |
959 | } | |
960 | ||
c363b55d DG |
961 | /* Remove from channel list */ |
962 | cds_list_del(&channel->list); | |
f9815039 | 963 | |
412d7227 SM |
964 | if (the_notification_thread_handle && |
965 | channel->published_to_notification_thread) { | |
63aaa3dc | 966 | status = notification_thread_command_remove_channel( |
412d7227 SM |
967 | the_notification_thread_handle, channel->key, |
968 | LTTNG_DOMAIN_KERNEL); | |
a0377dfe | 969 | LTTNG_ASSERT(status == LTTNG_OK); |
63aaa3dc | 970 | } |
e9404c27 | 971 | free(channel->channel->attr.extended.ptr); |
f9815039 | 972 | free(channel->channel); |
c363b55d DG |
973 | free(channel); |
974 | } | |
975 | ||
050349bb DG |
976 | /* |
977 | * Cleanup kernel metadata structure. | |
978 | */ | |
62499ad6 | 979 | void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata) |
c363b55d | 980 | { |
a0377dfe | 981 | LTTNG_ASSERT(metadata); |
0525e9ae | 982 | |
33a2b854 | 983 | DBG("[trace] Closing metadata fd %d", metadata->fd); |
c363b55d | 984 | /* Close kernel fd */ |
03550b58 | 985 | if (metadata->fd >= 0) { |
c617c0c6 MD |
986 | int ret; |
987 | ||
03550b58 MD |
988 | ret = close(metadata->fd); |
989 | if (ret) { | |
990 | PERROR("close"); | |
991 | } | |
799e2c4f | 992 | } |
c363b55d | 993 | |
f9815039 | 994 | free(metadata->conf); |
c363b55d DG |
995 | free(metadata); |
996 | } | |
997 | ||
050349bb | 998 | /* |
62499ad6 | 999 | * Cleanup kernel session structure |
050349bb | 1000 | */ |
62499ad6 | 1001 | void trace_kernel_destroy_session(struct ltt_kernel_session *session) |
c363b55d | 1002 | { |
af9737e9 | 1003 | struct ltt_kernel_channel *channel, *ctmp; |
799e2c4f | 1004 | int ret; |
c363b55d | 1005 | |
a0377dfe | 1006 | LTTNG_ASSERT(session); |
0525e9ae | 1007 | |
33a2b854 | 1008 | DBG("[trace] Closing session fd %d", session->fd); |
c363b55d | 1009 | /* Close kernel fds */ |
03550b58 MD |
1010 | if (session->fd >= 0) { |
1011 | ret = close(session->fd); | |
1012 | if (ret) { | |
1013 | PERROR("close"); | |
1014 | } | |
799e2c4f | 1015 | } |
f9815039 | 1016 | |
03550b58 | 1017 | if (session->metadata_stream_fd >= 0) { |
70dc1c34 | 1018 | DBG("[trace] Closing metadata stream fd %d", session->metadata_stream_fd); |
799e2c4f MD |
1019 | ret = close(session->metadata_stream_fd); |
1020 | if (ret) { | |
1021 | PERROR("close"); | |
1022 | } | |
70dc1c34 | 1023 | } |
c363b55d | 1024 | |
d36b8583 | 1025 | if (session->metadata != NULL) { |
62499ad6 | 1026 | trace_kernel_destroy_metadata(session->metadata); |
d36b8583 | 1027 | } |
c363b55d | 1028 | |
af9737e9 | 1029 | cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) { |
62499ad6 | 1030 | trace_kernel_destroy_channel(channel); |
c363b55d | 1031 | } |
d070c424 | 1032 | } |
c363b55d | 1033 | |
d070c424 MD |
1034 | /* Free elements needed by destroy notifiers. */ |
1035 | void trace_kernel_free_session(struct ltt_kernel_session *session) | |
1036 | { | |
00e2e675 | 1037 | /* Wipe consumer output object */ |
6addfa37 | 1038 | consumer_output_put(session->consumer); |
00e2e675 | 1039 | |
159b042f JG |
1040 | process_attr_tracker_destroy(session->tracker_pid); |
1041 | process_attr_tracker_destroy(session->tracker_vpid); | |
1042 | process_attr_tracker_destroy(session->tracker_uid); | |
1043 | process_attr_tracker_destroy(session->tracker_vuid); | |
1044 | process_attr_tracker_destroy(session->tracker_gid); | |
1045 | process_attr_tracker_destroy(session->tracker_vgid); | |
55c9e7ca | 1046 | |
dd7cc721 | 1047 | delete (session); |
c363b55d | 1048 | } |