Run clang-format on the whole tree
[lttng-tools.git] / src / bin / lttng / commands / enable_events.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <common/compat/getenv.hpp>
10 #include <common/compat/string.hpp>
11 #include <common/sessiond-comm/sessiond-comm.hpp>
12 #include <common/string-utils/string-utils.hpp>
13 #include <common/utils.hpp>
14
15 #include <ctype.h>
16 #include <inttypes.h>
17 #include <popt.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 /* Mi dependancy */
25 #include "../command.hpp"
26 #include "../loglevel.hpp"
27 #include "../uprobe.hpp"
28
29 #include <common/mi-lttng.hpp>
30
31 #include <lttng/domain-internal.hpp>
32 #include <lttng/event-internal.hpp>
33
34 #if (LTTNG_SYMBOL_NAME_LEN == 256)
35 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
36 #endif
37
38 static int opt_event_type;
39 static const char *opt_loglevel;
40 static int opt_loglevel_type;
41 static int opt_kernel;
42 static char *opt_session_name;
43 static int opt_userspace;
44 static int opt_jul;
45 static int opt_log4j;
46 static int opt_python;
47 static int opt_enable_all;
48 static char *opt_probe;
49 static char *opt_userspace_probe;
50 static char *opt_function;
51 static char *opt_channel_name;
52 static char *opt_filter;
53 static char *opt_exclude;
54
55 #ifdef LTTNG_EMBED_HELP
56 static const char help_msg[] =
57 #include <lttng-enable-event.1.h>
58 ;
59 #endif
60
61 enum {
62 OPT_HELP = 1,
63 OPT_TRACEPOINT,
64 OPT_PROBE,
65 OPT_USERSPACE_PROBE,
66 OPT_FUNCTION,
67 OPT_SYSCALL,
68 OPT_USERSPACE,
69 OPT_LOGLEVEL,
70 OPT_LOGLEVEL_ONLY,
71 OPT_LIST_OPTIONS,
72 OPT_FILTER,
73 OPT_EXCLUDE,
74 };
75
76 static struct lttng_handle *handle;
77 static struct mi_writer *writer;
78
79 static struct poptOption long_options[] = {
80 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
81 { "help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0 },
82 { "session", 's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0 },
83 { "all", 'a', POPT_ARG_VAL, &opt_enable_all, 1, 0, 0 },
84 { "channel", 'c', POPT_ARG_STRING, &opt_channel_name, 0, 0, 0 },
85 { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0 },
86 { "userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0 },
87 { "jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0 },
88 { "log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0 },
89 { "python", 'p', POPT_ARG_VAL, &opt_python, 1, 0, 0 },
90 { "tracepoint", 0, POPT_ARG_NONE, 0, OPT_TRACEPOINT, 0, 0 },
91 { "probe", 0, POPT_ARG_STRING, &opt_probe, OPT_PROBE, 0, 0 },
92 { "userspace-probe", 0, POPT_ARG_STRING, &opt_userspace_probe, OPT_USERSPACE_PROBE, 0, 0 },
93 { "function", 0, POPT_ARG_STRING, &opt_function, OPT_FUNCTION, 0, 0 },
94 { "syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0 },
95 { "loglevel", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL, 0, 0 },
96 { "loglevel-only", 0, POPT_ARG_STRING, 0, OPT_LOGLEVEL_ONLY, 0, 0 },
97 { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL },
98 { "filter", 'f', POPT_ARG_STRING, &opt_filter, OPT_FILTER, 0, 0 },
99 { "exclude", 'x', POPT_ARG_STRING, &opt_exclude, OPT_EXCLUDE, 0, 0 },
100 { 0, 0, 0, 0, 0, 0, 0 }
101 };
102
103 /*
104 * Parse probe options.
105 */
106 static int parse_probe_opts(struct lttng_event *ev, char *opt)
107 {
108 int ret = CMD_SUCCESS;
109 int match;
110 char s_hex[19];
111 #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */
112 char name[LTTNG_SYMBOL_NAME_LEN];
113
114 if (opt == NULL) {
115 ret = CMD_ERROR;
116 goto end;
117 }
118
119 /* Check for symbol+offset */
120 match = sscanf(opt,
121 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
122 "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s",
123 name,
124 s_hex);
125 if (match == 2) {
126 strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN);
127 ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
128 DBG("probe symbol %s", ev->attr.probe.symbol_name);
129 if (*s_hex == '\0') {
130 ERR("Invalid probe offset %s", s_hex);
131 ret = CMD_ERROR;
132 goto end;
133 }
134 ev->attr.probe.offset = strtoull(s_hex, NULL, 0);
135 DBG("probe offset %" PRIu64, ev->attr.probe.offset);
136 ev->attr.probe.addr = 0;
137 goto end;
138 }
139
140 /* Check for symbol */
141 if (isalpha(name[0]) || name[0] == '_') {
142 match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s", name);
143 if (match == 1) {
144 strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN);
145 ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
146 DBG("probe symbol %s", ev->attr.probe.symbol_name);
147 ev->attr.probe.offset = 0;
148 DBG("probe offset %" PRIu64, ev->attr.probe.offset);
149 ev->attr.probe.addr = 0;
150 goto end;
151 }
152 }
153
154 /* Check for address */
155 match = sscanf(opt, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", s_hex);
156 if (match > 0) {
157 /*
158 * Return an error if the first character of the tentative
159 * address is NULL or not a digit. It can be "0" if the address
160 * is in hexadecimal and can be 1 to 9 if it's in decimal.
161 */
162 if (*s_hex == '\0' || !isdigit(*s_hex)) {
163 ERR("Invalid probe description %s", s_hex);
164 ret = CMD_ERROR;
165 goto end;
166 }
167 ev->attr.probe.addr = strtoull(s_hex, NULL, 0);
168 DBG("probe addr %" PRIu64, ev->attr.probe.addr);
169 ev->attr.probe.offset = 0;
170 memset(ev->attr.probe.symbol_name, 0, LTTNG_SYMBOL_NAME_LEN);
171 goto end;
172 }
173
174 /* No match */
175 ret = CMD_ERROR;
176
177 end:
178 return ret;
179 }
180
181 static const char *print_channel_name(const char *name)
182 {
183 return name ?: DEFAULT_CHANNEL_NAME;
184 }
185
186 static const char *print_raw_channel_name(const char *name)
187 {
188 return name ?: "<default>";
189 }
190
191 /*
192 * Mi print exlcusion list
193 */
194 static int mi_print_exclusion(const struct lttng_dynamic_pointer_array *exclusions)
195 {
196 int ret;
197 size_t i;
198 const size_t count = lttng_dynamic_pointer_array_get_count(exclusions);
199
200 LTTNG_ASSERT(writer);
201
202 if (count == 0) {
203 ret = 0;
204 goto end;
205 }
206
207 ret = mi_lttng_writer_open_element(writer, config_element_exclusions);
208 if (ret) {
209 goto end;
210 }
211
212 for (i = 0; i < count; i++) {
213 const char *exclusion =
214 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, i);
215
216 ret = mi_lttng_writer_write_element_string(
217 writer, config_element_exclusion, exclusion);
218 if (ret) {
219 goto end;
220 }
221 }
222
223 /* Close exclusions element */
224 ret = mi_lttng_writer_close_element(writer);
225
226 end:
227 return ret;
228 }
229
230 /*
231 * Return allocated string for pretty-printing exclusion names.
232 */
233 static char *print_exclusions(const struct lttng_dynamic_pointer_array *exclusions)
234 {
235 int length = 0;
236 size_t i;
237 const char preamble[] = " excluding ";
238 char *ret;
239 const size_t count = lttng_dynamic_pointer_array_get_count(exclusions);
240
241 if (count == 0) {
242 return strdup("");
243 }
244
245 /* Calculate total required length. */
246 for (i = 0; i < count; i++) {
247 const char *exclusion =
248 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, i);
249
250 length += strlen(exclusion) + 4;
251 }
252
253 length += sizeof(preamble);
254 ret = calloc<char>(length);
255 if (!ret) {
256 return NULL;
257 }
258
259 strncpy(ret, preamble, length);
260 for (i = 0; i < count; i++) {
261 const char *exclusion =
262 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, i);
263
264 strcat(ret, "\"");
265 strcat(ret, exclusion);
266 strcat(ret, "\"");
267 if (i != count - 1) {
268 strcat(ret, ", ");
269 }
270 }
271
272 return ret;
273 }
274
275 static int check_exclusion_subsets(const char *event_name, const char *exclusion)
276 {
277 bool warn = false;
278 int ret = 0;
279 const char *e = event_name;
280 const char *x = exclusion;
281
282 /* Scan both the excluder and the event letter by letter */
283 while (true) {
284 if (*e == '\\') {
285 if (*x != *e) {
286 warn = true;
287 goto end;
288 }
289
290 e++;
291 x++;
292 goto cmp_chars;
293 }
294
295 if (*x == '*') {
296 /* Event is a subset of the excluder */
297 ERR("Event %s: %s excludes all events from %s",
298 event_name,
299 exclusion,
300 event_name);
301 goto error;
302 }
303
304 if (*e == '*') {
305 /*
306 * Reached the end of the event name before the
307 * end of the exclusion: this is valid.
308 */
309 goto end;
310 }
311
312 cmp_chars:
313 if (*x != *e) {
314 warn = true;
315 break;
316 }
317
318 x++;
319 e++;
320 }
321
322 goto end;
323
324 error:
325 ret = -1;
326
327 end:
328 if (warn) {
329 WARN("Event %s: %s does not exclude any events from %s",
330 event_name,
331 exclusion,
332 event_name);
333 }
334
335 return ret;
336 }
337
338 int validate_exclusion_list(const char *event_name,
339 const struct lttng_dynamic_pointer_array *exclusions)
340 {
341 int ret;
342
343 /* Event name must be a valid globbing pattern to allow exclusions. */
344 if (!strutils_is_star_glob_pattern(event_name)) {
345 ERR("Event %s: Exclusions can only be used with a globbing pattern", event_name);
346 goto error;
347 }
348
349 /*
350 * If the event name is a star-at-end only globbing pattern,
351 * then we can validate the individual exclusions. Otherwise
352 * all exclusions are passed to the session daemon.
353 */
354 if (strutils_is_star_at_the_end_only_glob_pattern(event_name)) {
355 size_t i, num_exclusions;
356
357 num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions);
358
359 for (i = 0; i < num_exclusions; i++) {
360 const char *exclusion =
361 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions,
362 i);
363
364 if (!strutils_is_star_glob_pattern(exclusion) ||
365 strutils_is_star_at_the_end_only_glob_pattern(exclusion)) {
366 ret = check_exclusion_subsets(event_name, exclusion);
367 if (ret) {
368 goto error;
369 }
370 }
371 }
372 }
373
374 ret = 0;
375 goto end;
376
377 error:
378 ret = -1;
379
380 end:
381 return ret;
382 }
383
384 static int create_exclusion_list_and_validate(const char *event_name,
385 const char *exclusions_arg,
386 struct lttng_dynamic_pointer_array *exclusions)
387 {
388 int ret = 0;
389
390 /* Split exclusions. */
391 ret = strutils_split(exclusions_arg, ',', true, exclusions);
392 if (ret < 0) {
393 goto error;
394 }
395
396 if (validate_exclusion_list(event_name, exclusions) != 0) {
397 goto error;
398 }
399
400 goto end;
401
402 error:
403 ret = -1;
404 lttng_dynamic_pointer_array_reset(exclusions);
405
406 end:
407 return ret;
408 }
409
410 static void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array *exclusions,
411 int *warn)
412 {
413 size_t i;
414 const size_t num_exclusions = lttng_dynamic_pointer_array_get_count(exclusions);
415
416 for (i = 0; i < num_exclusions; i++) {
417 const char *const exclusion =
418 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions, i);
419
420 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
421 WARN("Event exclusion \"%s\" will be truncated", exclusion);
422 *warn = 1;
423 }
424 }
425 }
426
427 /*
428 * Enabling event using the lttng API.
429 * Note: in case of error only the last error code will be return.
430 */
431 static int enable_events(char *session_name, char *event_list)
432 {
433 int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
434 int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1;
435 char *event_name, *channel_name = NULL;
436 struct lttng_event *ev;
437 struct lttng_domain dom = {};
438 struct lttng_dynamic_pointer_array exclusions;
439 struct lttng_userspace_probe_location *uprobe_loc = NULL;
440
441 lttng_dynamic_pointer_array_init(&exclusions, NULL);
442
443 ev = lttng_event_create();
444 if (!ev) {
445 ret = CMD_ERROR;
446 goto error;
447 }
448
449 if (opt_kernel) {
450 if (opt_loglevel) {
451 WARN("Kernel loglevels are not supported.");
452 }
453 }
454
455 /* Create lttng domain */
456 if (opt_kernel) {
457 dom.type = LTTNG_DOMAIN_KERNEL;
458 dom.buf_type = LTTNG_BUFFER_GLOBAL;
459 } else if (opt_userspace) {
460 dom.type = LTTNG_DOMAIN_UST;
461 /* Default. */
462 dom.buf_type = LTTNG_BUFFER_PER_UID;
463 } else if (opt_jul) {
464 dom.type = LTTNG_DOMAIN_JUL;
465 /* Default. */
466 dom.buf_type = LTTNG_BUFFER_PER_UID;
467 } else if (opt_log4j) {
468 dom.type = LTTNG_DOMAIN_LOG4J;
469 /* Default. */
470 dom.buf_type = LTTNG_BUFFER_PER_UID;
471 } else if (opt_python) {
472 dom.type = LTTNG_DOMAIN_PYTHON;
473 /* Default. */
474 dom.buf_type = LTTNG_BUFFER_PER_UID;
475 } else {
476 /* Checked by the caller. */
477 abort();
478 }
479
480 if (opt_exclude) {
481 switch (dom.type) {
482 case LTTNG_DOMAIN_KERNEL:
483 case LTTNG_DOMAIN_JUL:
484 case LTTNG_DOMAIN_LOG4J:
485 case LTTNG_DOMAIN_PYTHON:
486 ERR("Event name exclusions are not yet implemented for %s events",
487 lttng_domain_type_str(dom.type));
488 ret = CMD_ERROR;
489 goto error;
490 case LTTNG_DOMAIN_UST:
491 /* Exclusions supported */
492 break;
493 default:
494 abort();
495 }
496 }
497
498 /*
499 * Adding a filter to a probe, function or userspace-probe would be
500 * denied by the kernel tracer as it's not supported at the moment. We
501 * do an early check here to warn the user.
502 */
503 if (opt_filter && opt_kernel) {
504 switch (opt_event_type) {
505 case LTTNG_EVENT_ALL:
506 case LTTNG_EVENT_TRACEPOINT:
507 case LTTNG_EVENT_SYSCALL:
508 break;
509 case LTTNG_EVENT_PROBE:
510 case LTTNG_EVENT_USERSPACE_PROBE:
511 case LTTNG_EVENT_FUNCTION:
512 ERR("Filter expressions are not supported for %s events",
513 get_event_type_str((lttng_event_type) opt_event_type));
514 ret = CMD_ERROR;
515 goto error;
516 default:
517 ret = CMD_UNDEFINED;
518 goto error;
519 }
520 }
521
522 channel_name = opt_channel_name;
523
524 handle = lttng_create_handle(session_name, &dom);
525 if (handle == NULL) {
526 ret = -1;
527 goto error;
528 }
529
530 /* Prepare Mi */
531 if (lttng_opt_mi) {
532 /* Open a events element */
533 ret = mi_lttng_writer_open_element(writer, config_element_events);
534 if (ret) {
535 ret = CMD_ERROR;
536 goto error;
537 }
538 }
539
540 if (opt_enable_all) {
541 /* Default setup for enable all */
542 if (opt_kernel) {
543 ev->type = (lttng_event_type) opt_event_type;
544 strcpy(ev->name, "*");
545 /* kernel loglevels not implemented */
546 ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
547 } else {
548 ev->type = LTTNG_EVENT_TRACEPOINT;
549 strcpy(ev->name, "*");
550 ev->loglevel_type = (lttng_loglevel_type) opt_loglevel_type;
551 if (opt_loglevel) {
552 int name_search_ret;
553
554 LTTNG_ASSERT(opt_userspace || opt_jul || opt_log4j || opt_python);
555
556 if (opt_userspace) {
557 enum lttng_loglevel loglevel;
558
559 name_search_ret =
560 loglevel_name_to_value(opt_loglevel, &loglevel);
561 ev->loglevel = (int) loglevel;
562 } else if (opt_jul) {
563 enum lttng_loglevel_jul loglevel;
564
565 name_search_ret =
566 loglevel_jul_name_to_value(opt_loglevel, &loglevel);
567 ev->loglevel = (int) loglevel;
568 } else if (opt_log4j) {
569 enum lttng_loglevel_log4j loglevel;
570
571 name_search_ret = loglevel_log4j_name_to_value(opt_loglevel,
572 &loglevel);
573 ev->loglevel = (int) loglevel;
574 } else {
575 /* python domain. */
576 enum lttng_loglevel_python loglevel;
577
578 name_search_ret = loglevel_python_name_to_value(
579 opt_loglevel, &loglevel);
580 ev->loglevel = (int) loglevel;
581 }
582
583 if (name_search_ret == -1) {
584 ERR("Unknown loglevel %s", opt_loglevel);
585 ret = -LTTNG_ERR_INVALID;
586 goto error;
587 }
588 } else {
589 LTTNG_ASSERT(opt_userspace || opt_jul || opt_log4j || opt_python);
590 if (opt_userspace) {
591 ev->loglevel = -1;
592 } else if (opt_jul) {
593 ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
594 } else if (opt_log4j) {
595 ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
596 } else if (opt_python) {
597 ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
598 }
599 }
600 }
601
602 if (opt_exclude) {
603 ret = create_exclusion_list_and_validate("*", opt_exclude, &exclusions);
604 if (ret) {
605 ret = CMD_ERROR;
606 goto error;
607 }
608
609 ev->exclusion = 1;
610 warn_on_truncated_exclusion_names(&exclusions, &warn);
611 }
612 if (!opt_filter) {
613 ret = lttng_enable_event_with_exclusions(
614 handle,
615 ev,
616 channel_name,
617 NULL,
618 lttng_dynamic_pointer_array_get_count(&exclusions),
619 (char **) exclusions.array.buffer.data);
620 if (ret < 0) {
621 switch (-ret) {
622 case LTTNG_ERR_KERN_EVENT_EXIST:
623 WARN("Kernel events already enabled (channel %s, session %s)",
624 print_channel_name(channel_name),
625 session_name);
626 warn = 1;
627 break;
628 case LTTNG_ERR_TRACE_ALREADY_STARTED:
629 {
630 const char *msg =
631 "The command tried to enable an event in a new domain for a session that has already been started once.";
632 ERR("Events: %s (channel %s, session %s)",
633 msg,
634 print_channel_name(channel_name),
635 session_name);
636 error = 1;
637 break;
638 }
639 default:
640 ERR("Events: %s (channel %s, session %s)",
641 lttng_strerror(ret),
642 ret == -LTTNG_ERR_NEED_CHANNEL_NAME ?
643 print_raw_channel_name(channel_name) :
644 print_channel_name(channel_name),
645 session_name);
646 error = 1;
647 break;
648 }
649 goto end;
650 }
651
652 switch (opt_event_type) {
653 case LTTNG_EVENT_TRACEPOINT:
654 if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
655 char *exclusion_string = print_exclusions(&exclusions);
656
657 if (!exclusion_string) {
658 PERROR("Cannot allocate exclusion_string");
659 error = 1;
660 goto end;
661 }
662 MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
663 lttng_domain_type_str(dom.type),
664 exclusion_string,
665 print_channel_name(channel_name),
666 opt_loglevel);
667 free(exclusion_string);
668 } else {
669 char *exclusion_string = print_exclusions(&exclusions);
670
671 if (!exclusion_string) {
672 PERROR("Cannot allocate exclusion_string");
673 error = 1;
674 goto end;
675 }
676 MSG("All %s tracepoints%s are enabled in channel %s",
677 lttng_domain_type_str(dom.type),
678 exclusion_string,
679 print_channel_name(channel_name));
680 free(exclusion_string);
681 }
682 break;
683 case LTTNG_EVENT_SYSCALL:
684 if (opt_kernel) {
685 MSG("All %s system calls are enabled in channel %s",
686 lttng_domain_type_str(dom.type),
687 print_channel_name(channel_name));
688 }
689 break;
690 case LTTNG_EVENT_ALL:
691 if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
692 char *exclusion_string = print_exclusions(&exclusions);
693
694 if (!exclusion_string) {
695 PERROR("Cannot allocate exclusion_string");
696 error = 1;
697 goto end;
698 }
699 MSG("All %s events%s are enabled in channel %s for loglevel %s",
700 lttng_domain_type_str(dom.type),
701 exclusion_string,
702 print_channel_name(channel_name),
703 opt_loglevel);
704 free(exclusion_string);
705 } else {
706 char *exclusion_string = print_exclusions(&exclusions);
707
708 if (!exclusion_string) {
709 PERROR("Cannot allocate exclusion_string");
710 error = 1;
711 goto end;
712 }
713 MSG("All %s events%s are enabled in channel %s",
714 lttng_domain_type_str(dom.type),
715 exclusion_string,
716 print_channel_name(channel_name));
717 free(exclusion_string);
718 }
719 break;
720 default:
721 /*
722 * We should not be here since lttng_enable_event should have
723 * failed on the event type.
724 */
725 goto error;
726 }
727 }
728
729 if (opt_filter) {
730 command_ret = lttng_enable_event_with_exclusions(
731 handle,
732 ev,
733 channel_name,
734 opt_filter,
735 lttng_dynamic_pointer_array_get_count(&exclusions),
736 (char **) exclusions.array.buffer.data);
737 if (command_ret < 0) {
738 switch (-command_ret) {
739 case LTTNG_ERR_FILTER_EXIST:
740 WARN("Filter on all events is already enabled"
741 " (channel %s, session %s)",
742 print_channel_name(channel_name),
743 session_name);
744 warn = 1;
745 break;
746 case LTTNG_ERR_TRACE_ALREADY_STARTED:
747 {
748 const char *msg =
749 "The command tried to enable an event in a new domain for a session that has already been started once.";
750 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
751 msg,
752 print_channel_name(channel_name),
753 session_name,
754 opt_filter);
755 error = 1;
756 break;
757 }
758 default:
759 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
760 lttng_strerror(command_ret),
761 command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ?
762 print_raw_channel_name(channel_name) :
763 print_channel_name(channel_name),
764 session_name,
765 opt_filter);
766 error = 1;
767 break;
768 }
769 error_holder = command_ret;
770 } else {
771 ev->filter = 1;
772 MSG("Filter '%s' successfully set", opt_filter);
773 }
774 }
775
776 if (lttng_opt_mi) {
777 /* The wildcard * is used for kernel and ust domain to
778 * represent ALL. We copy * in event name to force the wildcard use
779 * for kernel domain
780 *
781 * Note: this is strictly for semantic and printing while in
782 * machine interface mode.
783 */
784 strcpy(ev->name, "*");
785
786 /* If we reach here the events are enabled */
787 if (!error && !warn) {
788 ev->enabled = 1;
789 } else {
790 ev->enabled = 0;
791 success = 0;
792 }
793 ret = mi_lttng_event(writer, ev, 1, handle->domain.type);
794 if (ret) {
795 ret = CMD_ERROR;
796 goto error;
797 }
798
799 /* print exclusion */
800 ret = mi_print_exclusion(&exclusions);
801 if (ret) {
802 ret = CMD_ERROR;
803 goto error;
804 }
805
806 /* Success ? */
807 ret = mi_lttng_writer_write_element_bool(
808 writer, mi_lttng_element_command_success, success);
809 if (ret) {
810 ret = CMD_ERROR;
811 goto error;
812 }
813
814 /* Close event element */
815 ret = mi_lttng_writer_close_element(writer);
816 if (ret) {
817 ret = CMD_ERROR;
818 goto error;
819 }
820 }
821
822 goto end;
823 }
824
825 /* Strip event list */
826 event_name = strtok(event_list, ",");
827 while (event_name != NULL) {
828 /* Copy name and type of the event */
829 strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
830 ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
831 ev->type = (lttng_event_type) opt_event_type;
832
833 /* Kernel tracer action */
834 if (opt_kernel) {
835 DBG("Enabling kernel event %s for channel %s",
836 event_name,
837 print_channel_name(channel_name));
838
839 switch (opt_event_type) {
840 case LTTNG_EVENT_ALL: /* Enable tracepoints and syscalls */
841 /* If event name differs from *, select tracepoint. */
842 if (strcmp(ev->name, "*")) {
843 ev->type = LTTNG_EVENT_TRACEPOINT;
844 }
845 break;
846 case LTTNG_EVENT_TRACEPOINT:
847 break;
848 case LTTNG_EVENT_PROBE:
849 ret = parse_probe_opts(ev, opt_probe);
850 if (ret) {
851 ERR("Unable to parse probe options");
852 ret = CMD_ERROR;
853 goto error;
854 }
855 break;
856 case LTTNG_EVENT_USERSPACE_PROBE:
857 LTTNG_ASSERT(ev->type == LTTNG_EVENT_USERSPACE_PROBE);
858
859 ret = parse_userspace_probe_opts(opt_userspace_probe, &uprobe_loc);
860 if (ret) {
861 switch (ret) {
862 case CMD_UNSUPPORTED:
863 /*
864 * Error message describing
865 * what is not supported was
866 * printed in the function.
867 */
868 break;
869 case CMD_ERROR:
870 default:
871 ERR("Unable to parse userspace probe options");
872 break;
873 }
874 goto error;
875 }
876
877 ret = lttng_event_set_userspace_probe_location(ev, uprobe_loc);
878 if (ret) {
879 WARN("Failed to set probe location on event");
880 ret = CMD_ERROR;
881 goto error;
882 }
883
884 /* Ownership of the uprobe location was transferred to the event. */
885 uprobe_loc = NULL;
886 break;
887 case LTTNG_EVENT_FUNCTION:
888 ret = parse_probe_opts(ev, opt_function);
889 if (ret) {
890 ERR("Unable to parse function probe options");
891 ret = CMD_ERROR;
892 goto error;
893 }
894 break;
895 case LTTNG_EVENT_SYSCALL:
896 ev->type = LTTNG_EVENT_SYSCALL;
897 break;
898 default:
899 ret = CMD_UNDEFINED;
900 goto error;
901 }
902
903 /* kernel loglevels not implemented */
904 ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
905 } else if (opt_userspace) { /* User-space tracer action */
906 DBG("Enabling UST event %s for channel %s, loglevel %s",
907 event_name,
908 print_channel_name(channel_name),
909 opt_loglevel ?: "<all>");
910
911 switch (opt_event_type) {
912 case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */
913 /* Fall-through */
914 case LTTNG_EVENT_TRACEPOINT:
915 /* Copy name and type of the event */
916 ev->type = LTTNG_EVENT_TRACEPOINT;
917 strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
918 ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
919 break;
920 case LTTNG_EVENT_PROBE:
921 case LTTNG_EVENT_FUNCTION:
922 case LTTNG_EVENT_SYSCALL:
923 case LTTNG_EVENT_USERSPACE_PROBE:
924 default:
925 ERR("Event type not available for user-space tracing");
926 ret = CMD_UNSUPPORTED;
927 goto error;
928 }
929
930 if (opt_exclude) {
931 ev->exclusion = 1;
932 if (opt_event_type != LTTNG_EVENT_ALL &&
933 opt_event_type != LTTNG_EVENT_TRACEPOINT) {
934 ERR("Exclusion option can only be used with tracepoint events");
935 ret = CMD_ERROR;
936 goto error;
937 }
938 /* Free previously allocated items. */
939 lttng_dynamic_pointer_array_reset(&exclusions);
940 ret = create_exclusion_list_and_validate(
941 event_name, opt_exclude, &exclusions);
942 if (ret) {
943 ret = CMD_ERROR;
944 goto error;
945 }
946
947 warn_on_truncated_exclusion_names(&exclusions, &warn);
948 }
949
950 ev->loglevel_type = (lttng_loglevel_type) opt_loglevel_type;
951 if (opt_loglevel) {
952 enum lttng_loglevel loglevel;
953 const int name_search_ret =
954 loglevel_name_to_value(opt_loglevel, &loglevel);
955
956 if (name_search_ret == -1) {
957 ERR("Unknown loglevel %s", opt_loglevel);
958 ret = -LTTNG_ERR_INVALID;
959 goto error;
960 }
961
962 ev->loglevel = (int) loglevel;
963 } else {
964 ev->loglevel = -1;
965 }
966 } else if (opt_jul || opt_log4j || opt_python) {
967 if (opt_event_type != LTTNG_EVENT_ALL &&
968 opt_event_type != LTTNG_EVENT_TRACEPOINT) {
969 ERR("Event type not supported for domain.");
970 ret = CMD_UNSUPPORTED;
971 goto error;
972 }
973
974 ev->loglevel_type = (lttng_loglevel_type) opt_loglevel_type;
975 if (opt_loglevel) {
976 int name_search_ret;
977
978 if (opt_jul) {
979 enum lttng_loglevel_jul loglevel;
980
981 name_search_ret =
982 loglevel_jul_name_to_value(opt_loglevel, &loglevel);
983 ev->loglevel = (int) loglevel;
984 } else if (opt_log4j) {
985 enum lttng_loglevel_log4j loglevel;
986
987 name_search_ret = loglevel_log4j_name_to_value(opt_loglevel,
988 &loglevel);
989 ev->loglevel = (int) loglevel;
990 } else {
991 /* python domain. */
992 enum lttng_loglevel_python loglevel;
993
994 name_search_ret = loglevel_python_name_to_value(
995 opt_loglevel, &loglevel);
996 ev->loglevel = (int) loglevel;
997 }
998
999 if (name_search_ret) {
1000 ERR("Unknown loglevel %s", opt_loglevel);
1001 ret = -LTTNG_ERR_INVALID;
1002 goto error;
1003 }
1004 } else {
1005 if (opt_jul) {
1006 ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
1007 } else if (opt_log4j) {
1008 ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
1009 } else if (opt_python) {
1010 ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
1011 }
1012 }
1013 ev->type = LTTNG_EVENT_TRACEPOINT;
1014 strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
1015 ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
1016 } else {
1017 abort();
1018 }
1019
1020 if (!opt_filter) {
1021 char *exclusion_string;
1022
1023 command_ret = lttng_enable_event_with_exclusions(
1024 handle,
1025 ev,
1026 channel_name,
1027 NULL,
1028 lttng_dynamic_pointer_array_get_count(&exclusions),
1029 (char **) exclusions.array.buffer.data);
1030 exclusion_string = print_exclusions(&exclusions);
1031 if (!exclusion_string) {
1032 PERROR("Cannot allocate exclusion_string");
1033 error = 1;
1034 goto end;
1035 }
1036 if (command_ret < 0) {
1037 /* Turn ret to positive value to handle the positive error code */
1038 switch (-command_ret) {
1039 case LTTNG_ERR_KERN_EVENT_EXIST:
1040 WARN("Kernel event %s%s already enabled (channel %s, session %s)",
1041 event_name,
1042 exclusion_string,
1043 print_channel_name(channel_name),
1044 session_name);
1045 warn = 1;
1046 break;
1047 case LTTNG_ERR_TRACE_ALREADY_STARTED:
1048 {
1049 const char *msg =
1050 "The command tried to enable an event in a new domain for a session that has already been started once.";
1051 ERR("Event %s%s: %s (channel %s, session %s)",
1052 event_name,
1053 exclusion_string,
1054 msg,
1055 print_channel_name(channel_name),
1056 session_name);
1057 error = 1;
1058 break;
1059 }
1060 case LTTNG_ERR_SDT_PROBE_SEMAPHORE:
1061 ERR("SDT probes %s guarded by semaphores are not supported (channel %s, session %s)",
1062 event_name,
1063 print_channel_name(channel_name),
1064 session_name);
1065 error = 1;
1066 break;
1067 default:
1068 ERR("Event %s%s: %s (channel %s, session %s)",
1069 event_name,
1070 exclusion_string,
1071 lttng_strerror(command_ret),
1072 command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ?
1073 print_raw_channel_name(channel_name) :
1074 print_channel_name(channel_name),
1075 session_name);
1076 error = 1;
1077 break;
1078 }
1079 error_holder = command_ret;
1080 } else {
1081 switch (dom.type) {
1082 case LTTNG_DOMAIN_KERNEL:
1083 case LTTNG_DOMAIN_UST:
1084 MSG("%s event %s%s created in channel %s",
1085 lttng_domain_type_str(dom.type),
1086 event_name,
1087 exclusion_string,
1088 print_channel_name(channel_name));
1089 break;
1090 case LTTNG_DOMAIN_JUL:
1091 case LTTNG_DOMAIN_LOG4J:
1092 case LTTNG_DOMAIN_PYTHON:
1093 /*
1094 * Don't print the default channel
1095 * name for agent domains.
1096 */
1097 MSG("%s event %s%s enabled",
1098 lttng_domain_type_str(dom.type),
1099 event_name,
1100 exclusion_string);
1101 break;
1102 default:
1103 abort();
1104 }
1105 }
1106 free(exclusion_string);
1107 }
1108
1109 if (opt_filter) {
1110 char *exclusion_string;
1111
1112 /* Filter present */
1113 ev->filter = 1;
1114
1115 command_ret = lttng_enable_event_with_exclusions(
1116 handle,
1117 ev,
1118 channel_name,
1119 opt_filter,
1120 lttng_dynamic_pointer_array_get_count(&exclusions),
1121 (char **) exclusions.array.buffer.data);
1122 exclusion_string = print_exclusions(&exclusions);
1123 if (!exclusion_string) {
1124 PERROR("Cannot allocate exclusion_string");
1125 error = 1;
1126 goto end;
1127 }
1128 if (command_ret < 0) {
1129 switch (-command_ret) {
1130 case LTTNG_ERR_FILTER_EXIST:
1131 WARN("Filter on event %s%s is already enabled"
1132 " (channel %s, session %s)",
1133 event_name,
1134 exclusion_string,
1135 print_channel_name(channel_name),
1136 session_name);
1137 warn = 1;
1138 break;
1139 case LTTNG_ERR_TRACE_ALREADY_STARTED:
1140 {
1141 const char *msg =
1142 "The command tried to enable an event in a new domain for a session that has already been started once.";
1143 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1144 ev->name,
1145 exclusion_string,
1146 msg,
1147 print_channel_name(channel_name),
1148 session_name,
1149 opt_filter);
1150 error = 1;
1151 break;
1152 }
1153 default:
1154 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1155 ev->name,
1156 exclusion_string,
1157 lttng_strerror(command_ret),
1158 command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME ?
1159 print_raw_channel_name(channel_name) :
1160 print_channel_name(channel_name),
1161 session_name,
1162 opt_filter);
1163 error = 1;
1164 break;
1165 }
1166 error_holder = command_ret;
1167
1168 } else {
1169 MSG("Event %s%s: Filter '%s' successfully set",
1170 event_name,
1171 exclusion_string,
1172 opt_filter);
1173 }
1174 free(exclusion_string);
1175 }
1176
1177 if (lttng_opt_mi) {
1178 if (command_ret) {
1179 success = 0;
1180 ev->enabled = 0;
1181 } else {
1182 ev->enabled = 1;
1183 }
1184
1185 ret = mi_lttng_event(writer, ev, 1, handle->domain.type);
1186 if (ret) {
1187 ret = CMD_ERROR;
1188 goto error;
1189 }
1190
1191 /* print exclusion */
1192 ret = mi_print_exclusion(&exclusions);
1193 if (ret) {
1194 ret = CMD_ERROR;
1195 goto error;
1196 }
1197
1198 /* Success ? */
1199 ret = mi_lttng_writer_write_element_bool(
1200 writer, mi_lttng_element_command_success, success);
1201 if (ret) {
1202 ret = CMD_ERROR;
1203 goto end;
1204 }
1205
1206 /* Close event element */
1207 ret = mi_lttng_writer_close_element(writer);
1208 if (ret) {
1209 ret = CMD_ERROR;
1210 goto end;
1211 }
1212 }
1213
1214 /* Next event */
1215 event_name = strtok(NULL, ",");
1216 /* Reset warn, error and success */
1217 success = 1;
1218 }
1219
1220 end:
1221 /* Close Mi */
1222 if (lttng_opt_mi) {
1223 /* Close events element */
1224 ret = mi_lttng_writer_close_element(writer);
1225 if (ret) {
1226 ret = CMD_ERROR;
1227 goto error;
1228 }
1229 }
1230 error:
1231 if (warn) {
1232 ret = CMD_WARNING;
1233 }
1234 if (error) {
1235 ret = CMD_ERROR;
1236 }
1237 lttng_destroy_handle(handle);
1238 lttng_dynamic_pointer_array_reset(&exclusions);
1239 lttng_userspace_probe_location_destroy(uprobe_loc);
1240
1241 /* Overwrite ret with error_holder if there was an actual error with
1242 * enabling an event.
1243 */
1244 ret = error_holder ? error_holder : ret;
1245
1246 lttng_event_destroy(ev);
1247 return ret;
1248 }
1249
1250 /*
1251 * Add event to trace session
1252 */
1253 int cmd_enable_events(int argc, const char **argv)
1254 {
1255 int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
1256 static poptContext pc;
1257 char *session_name = NULL;
1258 char *event_list = NULL;
1259 const char *arg_event_list = NULL;
1260 const char *leftover = NULL;
1261 int event_type = -1;
1262
1263 pc = poptGetContext(NULL, argc, argv, long_options, 0);
1264 poptReadDefaultConfig(pc, 0);
1265
1266 /* Default event type */
1267 opt_event_type = LTTNG_EVENT_ALL;
1268
1269 while ((opt = poptGetNextOpt(pc)) != -1) {
1270 switch (opt) {
1271 case OPT_HELP:
1272 SHOW_HELP();
1273 goto end;
1274 case OPT_TRACEPOINT:
1275 opt_event_type = LTTNG_EVENT_TRACEPOINT;
1276 break;
1277 case OPT_PROBE:
1278 opt_event_type = LTTNG_EVENT_PROBE;
1279 break;
1280 case OPT_USERSPACE_PROBE:
1281 opt_event_type = LTTNG_EVENT_USERSPACE_PROBE;
1282 break;
1283 case OPT_FUNCTION:
1284 opt_event_type = LTTNG_EVENT_FUNCTION;
1285 break;
1286 case OPT_SYSCALL:
1287 opt_event_type = LTTNG_EVENT_SYSCALL;
1288 break;
1289 case OPT_USERSPACE:
1290 opt_userspace = 1;
1291 break;
1292 case OPT_LOGLEVEL:
1293 opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
1294 opt_loglevel = poptGetOptArg(pc);
1295 break;
1296 case OPT_LOGLEVEL_ONLY:
1297 opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
1298 opt_loglevel = poptGetOptArg(pc);
1299 break;
1300 case OPT_LIST_OPTIONS:
1301 list_cmd_options(stdout, long_options);
1302 goto end;
1303 case OPT_FILTER:
1304 break;
1305 case OPT_EXCLUDE:
1306 break;
1307 default:
1308 ret = CMD_UNDEFINED;
1309 goto end;
1310 }
1311
1312 /* Validate event type. Multiple event type are not supported. */
1313 if (event_type == -1) {
1314 event_type = opt_event_type;
1315 } else {
1316 if (event_type != opt_event_type) {
1317 ERR("Multiple event type not supported.");
1318 ret = CMD_ERROR;
1319 goto end;
1320 }
1321 }
1322 }
1323
1324 ret = print_missing_or_multiple_domains(
1325 opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python, true);
1326 if (ret) {
1327 ret = CMD_ERROR;
1328 goto end;
1329 }
1330
1331 /* Mi check */
1332 if (lttng_opt_mi) {
1333 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
1334 if (!writer) {
1335 ret = -LTTNG_ERR_NOMEM;
1336 goto end;
1337 }
1338
1339 /* Open command element */
1340 ret = mi_lttng_writer_command_open(writer, mi_lttng_element_command_enable_event);
1341 if (ret) {
1342 ret = CMD_ERROR;
1343 goto end;
1344 }
1345
1346 /* Open output element */
1347 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_command_output);
1348 if (ret) {
1349 ret = CMD_ERROR;
1350 goto end;
1351 }
1352 }
1353
1354 arg_event_list = poptGetArg(pc);
1355 if (arg_event_list == NULL && opt_enable_all == 0) {
1356 ERR("Missing event name(s).");
1357 ret = CMD_ERROR;
1358 goto end;
1359 }
1360
1361 if (opt_enable_all == 0) {
1362 event_list = strdup(arg_event_list);
1363 if (event_list == NULL) {
1364 PERROR("Failed to copy event name(s)");
1365 ret = CMD_ERROR;
1366 goto end;
1367 }
1368 }
1369
1370 leftover = poptGetArg(pc);
1371 if (leftover) {
1372 ERR("Unknown argument: %s", leftover);
1373 ret = CMD_ERROR;
1374 goto end;
1375 }
1376
1377 if (!opt_session_name) {
1378 session_name = get_session_name();
1379 if (session_name == NULL) {
1380 command_ret = CMD_ERROR;
1381 success = 0;
1382 goto mi_closing;
1383 }
1384 } else {
1385 session_name = opt_session_name;
1386 }
1387
1388 command_ret = enable_events(session_name, event_list);
1389 if (command_ret) {
1390 success = 0;
1391 goto mi_closing;
1392 }
1393
1394 mi_closing:
1395 /* Mi closing */
1396 if (lttng_opt_mi) {
1397 /* Close output element */
1398 ret = mi_lttng_writer_close_element(writer);
1399 if (ret) {
1400 ret = CMD_ERROR;
1401 goto end;
1402 }
1403
1404 ret = mi_lttng_writer_write_element_bool(
1405 writer, mi_lttng_element_command_success, success);
1406 if (ret) {
1407 ret = CMD_ERROR;
1408 goto end;
1409 }
1410
1411 /* Command element close */
1412 ret = mi_lttng_writer_command_close(writer);
1413 if (ret) {
1414 ret = CMD_ERROR;
1415 goto end;
1416 }
1417 }
1418
1419 end:
1420 /* Mi clean-up */
1421 if (writer && mi_lttng_writer_destroy(writer)) {
1422 /* Preserve original error code */
1423 ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
1424 }
1425
1426 if (opt_session_name == NULL) {
1427 free(session_name);
1428 }
1429
1430 free(event_list);
1431
1432 /* Overwrite ret if an error occurred in enable_events */
1433 ret = command_ret ? command_ret : ret;
1434
1435 poptFreeContext(pc);
1436 return ret;
1437 }
This page took 0.09169 seconds and 4 git commands to generate.