2 * Copyright (C) 2011 EfficiOS Inc.
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include <common/compat/getenv.hpp>
10 #include <common/compat/string.hpp>
11 #include <common/make-unique-wrapper.hpp>
12 #include <common/sessiond-comm/sessiond-comm.hpp>
13 #include <common/string-utils/string-utils.hpp>
14 #include <common/utils.hpp>
22 #include <sys/types.h>
26 #include "../command.hpp"
27 #include "../loglevel.hpp"
28 #include "../uprobe.hpp"
30 #include <common/mi-lttng.hpp>
32 #include <lttng/domain-internal.hpp>
33 #include <lttng/event-internal.hpp>
35 #if (LTTNG_SYMBOL_NAME_LEN == 256)
36 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
40 void _mi_lttng_writer_deleter_func(mi_writer
*writer
)
42 if (writer
&& mi_lttng_writer_destroy(writer
)) {
43 LTTNG_THROW_ERROR("Failed to destroy mi_writer instance");
47 using mi_writer_uptr
= std::unique_ptr
<
49 lttng::memory::create_deleter_class
<mi_writer
, _mi_lttng_writer_deleter_func
>::deleter
>;
52 const char *opt_loglevel
;
53 int opt_loglevel_type
;
55 char *opt_session_name
;
62 char *opt_userspace_probe
;
64 char *opt_channel_name
;
68 struct lttng_handle
*handle
;
69 mi_writer_uptr writer
;
71 #ifdef LTTNG_EMBED_HELP
72 static const char help_msg
[] =
73 #include <lttng-enable-event.1.h>
92 struct poptOption long_options
[] = {
93 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
94 { "help", 'h', POPT_ARG_NONE
, nullptr, OPT_HELP
, nullptr, nullptr },
95 { "session", 's', POPT_ARG_STRING
, &opt_session_name
, 0, nullptr, nullptr },
96 { "all", 'a', POPT_ARG_VAL
, &opt_enable_all
, 1, nullptr, nullptr },
97 { "channel", 'c', POPT_ARG_STRING
, &opt_channel_name
, 0, nullptr, nullptr },
98 { "kernel", 'k', POPT_ARG_VAL
, &opt_kernel
, 1, nullptr, nullptr },
99 { "userspace", 'u', POPT_ARG_NONE
, nullptr, OPT_USERSPACE
, nullptr, nullptr },
100 { "jul", 'j', POPT_ARG_VAL
, &opt_jul
, 1, nullptr, nullptr },
101 { "log4j", 'l', POPT_ARG_VAL
, &opt_log4j
, 1, nullptr, nullptr },
102 { "python", 'p', POPT_ARG_VAL
, &opt_python
, 1, nullptr, nullptr },
103 { "tracepoint", 0, POPT_ARG_NONE
, nullptr, OPT_TRACEPOINT
, nullptr, nullptr },
104 { "probe", 0, POPT_ARG_STRING
, &opt_probe
, OPT_PROBE
, nullptr, nullptr },
108 &opt_userspace_probe
,
112 { "function", 0, POPT_ARG_STRING
, &opt_function
, OPT_FUNCTION
, nullptr, nullptr },
113 { "syscall", 0, POPT_ARG_NONE
, nullptr, OPT_SYSCALL
, nullptr, nullptr },
114 { "loglevel", 0, POPT_ARG_STRING
, nullptr, OPT_LOGLEVEL
, nullptr, nullptr },
115 { "loglevel-only", 0, POPT_ARG_STRING
, nullptr, OPT_LOGLEVEL_ONLY
, nullptr, nullptr },
116 { "list-options", 0, POPT_ARG_NONE
, nullptr, OPT_LIST_OPTIONS
, nullptr, nullptr },
117 { "filter", 'f', POPT_ARG_STRING
, &opt_filter
, OPT_FILTER
, nullptr, nullptr },
118 { "exclude", 'x', POPT_ARG_STRING
, &opt_exclude
, OPT_EXCLUDE
, nullptr, nullptr },
119 { nullptr, 0, 0, nullptr, 0, nullptr, nullptr }
123 * Parse probe options.
125 int parse_probe_opts(struct lttng_event
*ev
, char *opt
)
127 int ret
= CMD_SUCCESS
;
130 #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */
131 char name
[LTTNG_SYMBOL_NAME_LEN
];
133 if (opt
== nullptr) {
138 /* Check for symbol+offset */
140 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
141 "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API
"s",
145 strncpy(ev
->attr
.probe
.symbol_name
, name
, LTTNG_SYMBOL_NAME_LEN
);
146 ev
->attr
.probe
.symbol_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
147 DBG("probe symbol %s", ev
->attr
.probe
.symbol_name
);
148 if (*s_hex
== '\0') {
149 ERR("Invalid probe offset %s", s_hex
);
153 ev
->attr
.probe
.offset
= strtoull(s_hex
, nullptr, 0);
154 DBG("probe offset %" PRIu64
, ev
->attr
.probe
.offset
);
155 ev
->attr
.probe
.addr
= 0;
159 /* Check for symbol */
160 if (isalpha(name
[0]) || name
[0] == '_') {
161 match
= sscanf(opt
, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
"s", name
);
163 strncpy(ev
->attr
.probe
.symbol_name
, name
, LTTNG_SYMBOL_NAME_LEN
);
164 ev
->attr
.probe
.symbol_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
165 DBG("probe symbol %s", ev
->attr
.probe
.symbol_name
);
166 ev
->attr
.probe
.offset
= 0;
167 DBG("probe offset %" PRIu64
, ev
->attr
.probe
.offset
);
168 ev
->attr
.probe
.addr
= 0;
173 /* Check for address */
174 match
= sscanf(opt
, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API
"s", s_hex
);
177 * Return an error if the first character of the tentative
178 * address is NULL or not a digit. It can be "0" if the address
179 * is in hexadecimal and can be 1 to 9 if it's in decimal.
181 if (*s_hex
== '\0' || !isdigit(*s_hex
)) {
182 ERR("Invalid probe description %s", s_hex
);
186 ev
->attr
.probe
.addr
= strtoull(s_hex
, nullptr, 0);
187 DBG("probe addr %" PRIu64
, ev
->attr
.probe
.addr
);
188 ev
->attr
.probe
.offset
= 0;
189 memset(ev
->attr
.probe
.symbol_name
, 0, LTTNG_SYMBOL_NAME_LEN
);
200 const char *print_channel_name(const char *name
)
202 return name
?: DEFAULT_CHANNEL_NAME
;
205 const char *print_raw_channel_name(const char *name
)
207 return name
?: "<default>";
211 * Mi print exlcusion list
213 int mi_print_exclusion(const struct lttng_dynamic_pointer_array
*exclusions
)
217 const size_t count
= lttng_dynamic_pointer_array_get_count(exclusions
);
219 LTTNG_ASSERT(writer
);
226 ret
= mi_lttng_writer_open_element(writer
.get(), config_element_exclusions
);
231 for (i
= 0; i
< count
; i
++) {
232 const char *exclusion
=
233 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
235 ret
= mi_lttng_writer_write_element_string(
236 writer
.get(), config_element_exclusion
, exclusion
);
242 /* Close exclusions element */
243 ret
= mi_lttng_writer_close_element(writer
.get());
250 * Return allocated string for pretty-printing exclusion names.
252 char *print_exclusions(const struct lttng_dynamic_pointer_array
*exclusions
)
256 const char preamble
[] = " excluding ";
258 const size_t count
= lttng_dynamic_pointer_array_get_count(exclusions
);
264 /* Calculate total required length. */
265 for (i
= 0; i
< count
; i
++) {
266 const char *exclusion
=
267 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
269 length
+= strlen(exclusion
) + 4;
272 length
+= sizeof(preamble
);
273 ret
= calloc
<char>(length
);
278 strncpy(ret
, preamble
, length
);
279 for (i
= 0; i
< count
; i
++) {
280 const char *exclusion
=
281 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
284 strcat(ret
, exclusion
);
286 if (i
!= count
- 1) {
294 int check_exclusion_subsets(const char *event_name
, const char *exclusion
)
298 const char *e
= event_name
;
299 const char *x
= exclusion
;
301 /* Scan both the excluder and the event letter by letter */
315 /* Event is a subset of the excluder */
316 ERR("Event %s: %s excludes all events from %s",
325 * Reached the end of the event name before the
326 * end of the exclusion: this is valid.
348 WARN("Event %s: %s does not exclude any events from %s",
357 int create_exclusion_list_and_validate(const char *event_name
,
358 const char *exclusions_arg
,
359 struct lttng_dynamic_pointer_array
*exclusions
)
363 /* Split exclusions. */
364 ret
= strutils_split(exclusions_arg
, ',', true, exclusions
);
369 if (validate_exclusion_list(event_name
, exclusions
) != 0) {
377 lttng_dynamic_pointer_array_reset(exclusions
);
383 void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array
*exclusions
,
387 const size_t num_exclusions
= lttng_dynamic_pointer_array_get_count(exclusions
);
389 for (i
= 0; i
< num_exclusions
; i
++) {
390 const char *const exclusion
=
391 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
393 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
394 WARN("Event exclusion \"%s\" will be truncated", exclusion
);
401 * Enabling event using the lttng API.
402 * Note: in case of error only the last error code will be return.
404 int enable_events(char *session_name
, char *event_list
)
406 int ret
= CMD_SUCCESS
, command_ret
= CMD_SUCCESS
;
407 int error_holder
= CMD_SUCCESS
, warn
= 0, error
= 0, success
= 1;
408 char *event_name
, *channel_name
= nullptr;
409 struct lttng_event
*ev
;
410 struct lttng_domain dom
= {};
411 struct lttng_dynamic_pointer_array exclusions
;
412 struct lttng_userspace_probe_location
*uprobe_loc
= nullptr;
414 lttng_dynamic_pointer_array_init(&exclusions
, nullptr);
416 ev
= lttng_event_create();
424 WARN("Kernel loglevels are not supported.");
428 /* Create lttng domain */
430 dom
.type
= LTTNG_DOMAIN_KERNEL
;
431 dom
.buf_type
= LTTNG_BUFFER_GLOBAL
;
432 } else if (opt_userspace
) {
433 dom
.type
= LTTNG_DOMAIN_UST
;
435 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
436 } else if (opt_jul
) {
437 dom
.type
= LTTNG_DOMAIN_JUL
;
439 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
440 } else if (opt_log4j
) {
441 dom
.type
= LTTNG_DOMAIN_LOG4J
;
443 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
444 } else if (opt_python
) {
445 dom
.type
= LTTNG_DOMAIN_PYTHON
;
447 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
449 /* Checked by the caller. */
455 case LTTNG_DOMAIN_KERNEL
:
456 case LTTNG_DOMAIN_JUL
:
457 case LTTNG_DOMAIN_LOG4J
:
458 case LTTNG_DOMAIN_PYTHON
:
459 ERR("Event name exclusions are not yet implemented for %s events",
460 lttng_domain_type_str(dom
.type
));
463 case LTTNG_DOMAIN_UST
:
464 /* Exclusions supported */
472 * Adding a filter to a probe, function or userspace-probe would be
473 * denied by the kernel tracer as it's not supported at the moment. We
474 * do an early check here to warn the user.
476 if (opt_filter
&& opt_kernel
) {
477 switch (opt_event_type
) {
478 case LTTNG_EVENT_ALL
:
479 case LTTNG_EVENT_TRACEPOINT
:
480 case LTTNG_EVENT_SYSCALL
:
482 case LTTNG_EVENT_PROBE
:
483 case LTTNG_EVENT_USERSPACE_PROBE
:
484 case LTTNG_EVENT_FUNCTION
:
485 ERR("Filter expressions are not supported for %s events",
486 get_event_type_str((lttng_event_type
) opt_event_type
));
495 channel_name
= opt_channel_name
;
497 handle
= lttng_create_handle(session_name
, &dom
);
498 if (handle
== nullptr) {
505 /* Open a events element */
506 ret
= mi_lttng_writer_open_element(writer
.get(), config_element_events
);
513 if (opt_enable_all
) {
514 /* Default setup for enable all */
516 ev
->type
= (lttng_event_type
) opt_event_type
;
517 strcpy(ev
->name
, "*");
518 /* kernel loglevels not implemented */
519 ev
->loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
521 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
522 strcpy(ev
->name
, "*");
523 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
527 LTTNG_ASSERT(opt_userspace
|| opt_jul
|| opt_log4j
|| opt_python
);
530 enum lttng_loglevel loglevel
;
533 loglevel_name_to_value(opt_loglevel
, &loglevel
);
534 ev
->loglevel
= (int) loglevel
;
535 } else if (opt_jul
) {
536 enum lttng_loglevel_jul loglevel
;
539 loglevel_jul_name_to_value(opt_loglevel
, &loglevel
);
540 ev
->loglevel
= (int) loglevel
;
541 } else if (opt_log4j
) {
542 enum lttng_loglevel_log4j loglevel
;
544 name_search_ret
= loglevel_log4j_name_to_value(opt_loglevel
,
546 ev
->loglevel
= (int) loglevel
;
549 enum lttng_loglevel_python loglevel
;
551 name_search_ret
= loglevel_python_name_to_value(
552 opt_loglevel
, &loglevel
);
553 ev
->loglevel
= (int) loglevel
;
556 if (name_search_ret
== -1) {
557 ERR("Unknown loglevel %s", opt_loglevel
);
558 ret
= -LTTNG_ERR_INVALID
;
562 LTTNG_ASSERT(opt_userspace
|| opt_jul
|| opt_log4j
|| opt_python
);
565 } else if (opt_jul
) {
566 ev
->loglevel
= LTTNG_LOGLEVEL_JUL_ALL
;
567 } else if (opt_log4j
) {
568 ev
->loglevel
= LTTNG_LOGLEVEL_LOG4J_ALL
;
569 } else if (opt_python
) {
570 ev
->loglevel
= LTTNG_LOGLEVEL_PYTHON_DEBUG
;
576 ret
= create_exclusion_list_and_validate("*", opt_exclude
, &exclusions
);
583 warn_on_truncated_exclusion_names(&exclusions
, &warn
);
586 ret
= lttng_enable_event_with_exclusions(
591 lttng_dynamic_pointer_array_get_count(&exclusions
),
592 (char **) exclusions
.array
.buffer
.data
);
595 case LTTNG_ERR_KERN_EVENT_EXIST
:
596 WARN("Kernel events already enabled (channel %s, session %s)",
597 print_channel_name(channel_name
),
601 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
604 "The command tried to enable an event in a new domain for a session that has already been started once.";
605 ERR("Events: %s (channel %s, session %s)",
607 print_channel_name(channel_name
),
613 ERR("Events: %s (channel %s, session %s)",
615 ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
616 print_raw_channel_name(channel_name
) :
617 print_channel_name(channel_name
),
625 switch (opt_event_type
) {
626 case LTTNG_EVENT_TRACEPOINT
:
627 if (opt_loglevel
&& dom
.type
!= LTTNG_DOMAIN_KERNEL
) {
628 char *exclusion_string
= print_exclusions(&exclusions
);
630 if (!exclusion_string
) {
631 PERROR("Cannot allocate exclusion_string");
635 MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
636 lttng_domain_type_str(dom
.type
),
638 print_channel_name(channel_name
),
640 free(exclusion_string
);
642 char *exclusion_string
= print_exclusions(&exclusions
);
644 if (!exclusion_string
) {
645 PERROR("Cannot allocate exclusion_string");
649 MSG("All %s tracepoints%s are enabled in channel %s",
650 lttng_domain_type_str(dom
.type
),
652 print_channel_name(channel_name
));
653 free(exclusion_string
);
656 case LTTNG_EVENT_SYSCALL
:
658 MSG("All %s system calls are enabled in channel %s",
659 lttng_domain_type_str(dom
.type
),
660 print_channel_name(channel_name
));
663 case LTTNG_EVENT_ALL
:
664 if (opt_loglevel
&& dom
.type
!= LTTNG_DOMAIN_KERNEL
) {
665 char *exclusion_string
= print_exclusions(&exclusions
);
667 if (!exclusion_string
) {
668 PERROR("Cannot allocate exclusion_string");
672 MSG("All %s events%s are enabled in channel %s for loglevel %s",
673 lttng_domain_type_str(dom
.type
),
675 print_channel_name(channel_name
),
677 free(exclusion_string
);
679 char *exclusion_string
= print_exclusions(&exclusions
);
681 if (!exclusion_string
) {
682 PERROR("Cannot allocate exclusion_string");
686 MSG("All %s events%s are enabled in channel %s",
687 lttng_domain_type_str(dom
.type
),
689 print_channel_name(channel_name
));
690 free(exclusion_string
);
695 * We should not be here since lttng_enable_event should have
696 * failed on the event type.
703 command_ret
= lttng_enable_event_with_exclusions(
708 lttng_dynamic_pointer_array_get_count(&exclusions
),
709 (char **) exclusions
.array
.buffer
.data
);
710 if (command_ret
< 0) {
711 switch (-command_ret
) {
712 case LTTNG_ERR_FILTER_EXIST
:
713 WARN("Filter on all events is already enabled"
714 " (channel %s, session %s)",
715 print_channel_name(channel_name
),
719 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
722 "The command tried to enable an event in a new domain for a session that has already been started once.";
723 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
725 print_channel_name(channel_name
),
732 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
733 lttng_strerror(command_ret
),
734 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
735 print_raw_channel_name(channel_name
) :
736 print_channel_name(channel_name
),
742 error_holder
= command_ret
;
745 MSG("Filter '%s' successfully set", opt_filter
);
750 /* The wildcard * is used for kernel and ust domain to
751 * represent ALL. We copy * in event name to force the wildcard use
754 * Note: this is strictly for semantic and printing while in
755 * machine interface mode.
757 strcpy(ev
->name
, "*");
759 /* If we reach here the events are enabled */
760 if (!error
&& !warn
) {
766 ret
= mi_lttng_event(writer
.get(), ev
, 1, handle
->domain
.type
);
772 /* print exclusion */
773 ret
= mi_print_exclusion(&exclusions
);
780 ret
= mi_lttng_writer_write_element_bool(
781 writer
.get(), mi_lttng_element_command_success
, success
);
787 /* Close event element */
788 ret
= mi_lttng_writer_close_element(writer
.get());
798 /* Strip event list */
799 event_name
= strtok(event_list
, ",");
800 while (event_name
!= nullptr) {
801 /* Copy name and type of the event */
802 strncpy(ev
->name
, event_name
, LTTNG_SYMBOL_NAME_LEN
);
803 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
804 ev
->type
= (lttng_event_type
) opt_event_type
;
806 /* Kernel tracer action */
808 DBG("Enabling kernel event %s for channel %s",
810 print_channel_name(channel_name
));
812 switch (opt_event_type
) {
813 case LTTNG_EVENT_ALL
: /* Enable tracepoints and syscalls */
814 /* If event name differs from *, select tracepoint. */
815 if (strcmp(ev
->name
, "*") != 0) {
816 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
819 case LTTNG_EVENT_TRACEPOINT
:
821 case LTTNG_EVENT_PROBE
:
822 ret
= parse_probe_opts(ev
, opt_probe
);
824 ERR("Unable to parse probe options");
829 case LTTNG_EVENT_USERSPACE_PROBE
:
830 LTTNG_ASSERT(ev
->type
== LTTNG_EVENT_USERSPACE_PROBE
);
832 ret
= parse_userspace_probe_opts(opt_userspace_probe
, &uprobe_loc
);
835 case CMD_UNSUPPORTED
:
837 * Error message describing
838 * what is not supported was
839 * printed in the function.
844 ERR("Unable to parse userspace probe options");
850 ret
= lttng_event_set_userspace_probe_location(ev
, uprobe_loc
);
852 WARN("Failed to set probe location on event");
857 /* Ownership of the uprobe location was transferred to the event. */
858 uprobe_loc
= nullptr;
860 case LTTNG_EVENT_FUNCTION
:
861 ret
= parse_probe_opts(ev
, opt_function
);
863 ERR("Unable to parse function probe options");
868 case LTTNG_EVENT_SYSCALL
:
869 ev
->type
= LTTNG_EVENT_SYSCALL
;
876 /* kernel loglevels not implemented */
877 ev
->loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
878 } else if (opt_userspace
) { /* User-space tracer action */
879 DBG("Enabling UST event %s for channel %s, loglevel %s",
881 print_channel_name(channel_name
),
882 opt_loglevel
?: "<all>");
884 switch (opt_event_type
) {
885 case LTTNG_EVENT_ALL
: /* Default behavior is tracepoint */
887 case LTTNG_EVENT_TRACEPOINT
:
888 /* Copy name and type of the event */
889 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
890 strncpy(ev
->name
, event_name
, LTTNG_SYMBOL_NAME_LEN
);
891 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
893 case LTTNG_EVENT_PROBE
:
894 case LTTNG_EVENT_FUNCTION
:
895 case LTTNG_EVENT_SYSCALL
:
896 case LTTNG_EVENT_USERSPACE_PROBE
:
898 ERR("Event type not available for user-space tracing");
899 ret
= CMD_UNSUPPORTED
;
905 if (opt_event_type
!= LTTNG_EVENT_ALL
&&
906 opt_event_type
!= LTTNG_EVENT_TRACEPOINT
) {
907 ERR("Exclusion option can only be used with tracepoint events");
911 /* Free previously allocated items. */
912 lttng_dynamic_pointer_array_reset(&exclusions
);
913 ret
= create_exclusion_list_and_validate(
914 event_name
, opt_exclude
, &exclusions
);
920 warn_on_truncated_exclusion_names(&exclusions
, &warn
);
923 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
925 enum lttng_loglevel loglevel
;
926 const int name_search_ret
=
927 loglevel_name_to_value(opt_loglevel
, &loglevel
);
929 if (name_search_ret
== -1) {
930 ERR("Unknown loglevel %s", opt_loglevel
);
931 ret
= -LTTNG_ERR_INVALID
;
935 ev
->loglevel
= (int) loglevel
;
939 } else if (opt_jul
|| opt_log4j
|| opt_python
) {
940 if (opt_event_type
!= LTTNG_EVENT_ALL
&&
941 opt_event_type
!= LTTNG_EVENT_TRACEPOINT
) {
942 ERR("Event type not supported for domain.");
943 ret
= CMD_UNSUPPORTED
;
947 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
952 enum lttng_loglevel_jul loglevel
;
955 loglevel_jul_name_to_value(opt_loglevel
, &loglevel
);
956 ev
->loglevel
= (int) loglevel
;
957 } else if (opt_log4j
) {
958 enum lttng_loglevel_log4j loglevel
;
960 name_search_ret
= loglevel_log4j_name_to_value(opt_loglevel
,
962 ev
->loglevel
= (int) loglevel
;
965 enum lttng_loglevel_python loglevel
;
967 name_search_ret
= loglevel_python_name_to_value(
968 opt_loglevel
, &loglevel
);
969 ev
->loglevel
= (int) loglevel
;
972 if (name_search_ret
) {
973 ERR("Unknown loglevel %s", opt_loglevel
);
974 ret
= -LTTNG_ERR_INVALID
;
979 ev
->loglevel
= LTTNG_LOGLEVEL_JUL_ALL
;
980 } else if (opt_log4j
) {
981 ev
->loglevel
= LTTNG_LOGLEVEL_LOG4J_ALL
;
982 } else if (opt_python
) {
983 ev
->loglevel
= LTTNG_LOGLEVEL_PYTHON_DEBUG
;
986 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
987 strncpy(ev
->name
, event_name
, LTTNG_SYMBOL_NAME_LEN
);
988 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
994 char *exclusion_string
;
996 command_ret
= lttng_enable_event_with_exclusions(
1001 lttng_dynamic_pointer_array_get_count(&exclusions
),
1002 (char **) exclusions
.array
.buffer
.data
);
1003 exclusion_string
= print_exclusions(&exclusions
);
1004 if (!exclusion_string
) {
1005 PERROR("Cannot allocate exclusion_string");
1009 if (command_ret
< 0) {
1010 /* Turn ret to positive value to handle the positive error code */
1011 switch (-command_ret
) {
1012 case LTTNG_ERR_KERN_EVENT_EXIST
:
1013 WARN("Kernel event %s%s already enabled (channel %s, session %s)",
1016 print_channel_name(channel_name
),
1020 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
1023 "The command tried to enable an event in a new domain for a session that has already been started once.";
1024 ERR("Event %s%s: %s (channel %s, session %s)",
1028 print_channel_name(channel_name
),
1033 case LTTNG_ERR_SDT_PROBE_SEMAPHORE
:
1034 ERR("SDT probes %s guarded by semaphores are not supported (channel %s, session %s)",
1036 print_channel_name(channel_name
),
1041 ERR("Event %s%s: %s (channel %s, session %s)",
1044 lttng_strerror(command_ret
),
1045 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
1046 print_raw_channel_name(channel_name
) :
1047 print_channel_name(channel_name
),
1052 error_holder
= command_ret
;
1055 case LTTNG_DOMAIN_KERNEL
:
1056 case LTTNG_DOMAIN_UST
:
1057 MSG("%s event %s%s created in channel %s",
1058 lttng_domain_type_str(dom
.type
),
1061 print_channel_name(channel_name
));
1063 case LTTNG_DOMAIN_JUL
:
1064 case LTTNG_DOMAIN_LOG4J
:
1065 case LTTNG_DOMAIN_PYTHON
:
1067 * Don't print the default channel
1068 * name for agent domains.
1070 MSG("%s event %s%s enabled",
1071 lttng_domain_type_str(dom
.type
),
1079 free(exclusion_string
);
1083 char *exclusion_string
;
1085 /* Filter present */
1088 command_ret
= lttng_enable_event_with_exclusions(
1093 lttng_dynamic_pointer_array_get_count(&exclusions
),
1094 (char **) exclusions
.array
.buffer
.data
);
1095 exclusion_string
= print_exclusions(&exclusions
);
1096 if (!exclusion_string
) {
1097 PERROR("Cannot allocate exclusion_string");
1101 if (command_ret
< 0) {
1102 switch (-command_ret
) {
1103 case LTTNG_ERR_FILTER_EXIST
:
1104 WARN("Filter on event %s%s is already enabled"
1105 " (channel %s, session %s)",
1108 print_channel_name(channel_name
),
1112 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
1115 "The command tried to enable an event in a new domain for a session that has already been started once.";
1116 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1120 print_channel_name(channel_name
),
1127 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1130 lttng_strerror(command_ret
),
1131 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
1132 print_raw_channel_name(channel_name
) :
1133 print_channel_name(channel_name
),
1139 error_holder
= command_ret
;
1142 MSG("Event %s%s: Filter '%s' successfully set",
1147 free(exclusion_string
);
1158 ret
= mi_lttng_event(writer
.get(), ev
, 1, handle
->domain
.type
);
1164 /* print exclusion */
1165 ret
= mi_print_exclusion(&exclusions
);
1172 ret
= mi_lttng_writer_write_element_bool(
1173 writer
.get(), mi_lttng_element_command_success
, success
);
1179 /* Close event element */
1180 ret
= mi_lttng_writer_close_element(writer
.get());
1188 event_name
= strtok(nullptr, ",");
1189 /* Reset warn, error and success */
1196 /* Close events element */
1197 ret
= mi_lttng_writer_close_element(writer
.get());
1210 lttng_destroy_handle(handle
);
1211 lttng_dynamic_pointer_array_reset(&exclusions
);
1212 lttng_userspace_probe_location_destroy(uprobe_loc
);
1214 /* Overwrite ret with error_holder if there was an actual error with
1215 * enabling an event.
1217 ret
= error_holder
? error_holder
: ret
;
1219 lttng_event_destroy(ev
);
1225 int validate_exclusion_list(const char *event_name
,
1226 const struct lttng_dynamic_pointer_array
*exclusions
)
1230 /* Event name must be a valid globbing pattern to allow exclusions. */
1231 if (!strutils_is_star_glob_pattern(event_name
)) {
1232 ERR("Event %s: Exclusions can only be used with a globbing pattern", event_name
);
1237 * If the event name is a star-at-end only globbing pattern,
1238 * then we can validate the individual exclusions. Otherwise
1239 * all exclusions are passed to the session daemon.
1241 if (strutils_is_star_at_the_end_only_glob_pattern(event_name
)) {
1242 size_t i
, num_exclusions
;
1244 num_exclusions
= lttng_dynamic_pointer_array_get_count(exclusions
);
1246 for (i
= 0; i
< num_exclusions
; i
++) {
1247 const char *exclusion
=
1248 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
,
1251 if (!strutils_is_star_glob_pattern(exclusion
) ||
1252 strutils_is_star_at_the_end_only_glob_pattern(exclusion
)) {
1253 ret
= check_exclusion_subsets(event_name
, exclusion
);
1272 * Add event to trace session
1274 int cmd_enable_events(int argc
, const char **argv
)
1276 int opt
, ret
= CMD_SUCCESS
, command_ret
= CMD_SUCCESS
, success
= 1;
1277 static poptContext pc
;
1278 char *session_name
= nullptr;
1279 char *event_list
= nullptr;
1280 const char *arg_event_list
= nullptr;
1281 const char *leftover
= nullptr;
1282 int event_type
= -1;
1284 pc
= poptGetContext(nullptr, argc
, argv
, long_options
, 0);
1285 poptReadDefaultConfig(pc
, 0);
1287 /* Default event type */
1288 opt_event_type
= LTTNG_EVENT_ALL
;
1290 while ((opt
= poptGetNextOpt(pc
)) != -1) {
1295 case OPT_TRACEPOINT
:
1296 opt_event_type
= LTTNG_EVENT_TRACEPOINT
;
1299 opt_event_type
= LTTNG_EVENT_PROBE
;
1301 case OPT_USERSPACE_PROBE
:
1302 opt_event_type
= LTTNG_EVENT_USERSPACE_PROBE
;
1305 opt_event_type
= LTTNG_EVENT_FUNCTION
;
1308 opt_event_type
= LTTNG_EVENT_SYSCALL
;
1314 opt_loglevel_type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1315 opt_loglevel
= poptGetOptArg(pc
);
1317 case OPT_LOGLEVEL_ONLY
:
1318 opt_loglevel_type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
1319 opt_loglevel
= poptGetOptArg(pc
);
1321 case OPT_LIST_OPTIONS
:
1322 list_cmd_options(stdout
, long_options
);
1329 ret
= CMD_UNDEFINED
;
1333 /* Validate event type. Multiple event type are not supported. */
1334 if (event_type
== -1) {
1335 event_type
= opt_event_type
;
1337 if (event_type
!= opt_event_type
) {
1338 ERR("Multiple event type not supported.");
1345 ret
= print_missing_or_multiple_domains(
1346 opt_kernel
+ opt_userspace
+ opt_jul
+ opt_log4j
+ opt_python
, true);
1354 writer
= mi_writer_uptr(mi_lttng_writer_create(fileno(stdout
), lttng_opt_mi
));
1356 ret
= -LTTNG_ERR_NOMEM
;
1360 /* Open command element */
1361 ret
= mi_lttng_writer_command_open(writer
.get(),
1362 mi_lttng_element_command_enable_event
);
1368 /* Open output element */
1369 ret
= mi_lttng_writer_open_element(writer
.get(), mi_lttng_element_command_output
);
1376 arg_event_list
= poptGetArg(pc
);
1377 if (arg_event_list
== nullptr && opt_enable_all
== 0) {
1378 ERR("Missing event name(s).");
1383 if (opt_enable_all
== 0) {
1384 event_list
= strdup(arg_event_list
);
1385 if (event_list
== nullptr) {
1386 PERROR("Failed to copy event name(s)");
1392 leftover
= poptGetArg(pc
);
1394 ERR("Unknown argument: %s", leftover
);
1399 if (!opt_session_name
) {
1400 session_name
= get_session_name();
1401 if (session_name
== nullptr) {
1402 command_ret
= CMD_ERROR
;
1407 session_name
= opt_session_name
;
1410 command_ret
= enable_events(session_name
, event_list
);
1419 /* Close output element */
1420 ret
= mi_lttng_writer_close_element(writer
.get());
1426 ret
= mi_lttng_writer_write_element_bool(
1427 writer
.get(), mi_lttng_element_command_success
, success
);
1433 /* Command element close */
1434 ret
= mi_lttng_writer_command_close(writer
.get());
1442 if (opt_session_name
== nullptr) {
1448 /* Overwrite ret if an error occurred in enable_events */
1449 ret
= command_ret
? command_ret
: ret
;
1451 poptFreeContext(pc
);