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