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