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