SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / bin / lttng / commands / list.c
1 /*
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9 #include <stdint.h>
10 #define _LGPL_SOURCE
11 #include <inttypes.h>
12 #include <popt.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <assert.h>
17
18 #include <common/mi-lttng.h>
19 #include <common/time.h>
20 #include <common/tracker.h>
21 #include <lttng/lttng.h>
22 #include <lttng/map/map.h>
23
24 #include "../command.h"
25
26 static int opt_userspace;
27 static int opt_kernel;
28 static int opt_jul;
29 static int opt_log4j;
30 static int opt_python;
31 static char *opt_channel;
32 static char *opt_map;
33 static int opt_domain;
34 static int opt_fields;
35 static int opt_syscall;
36
37 const char *indent4 = " ";
38 const char *indent6 = " ";
39 const char *indent8 = " ";
40
41 #ifdef LTTNG_EMBED_HELP
42 static const char help_msg[] =
43 #include <lttng-list.1.h>
44 ;
45 #endif
46
47 enum {
48 OPT_HELP = 1,
49 OPT_USERSPACE,
50 OPT_LIST_OPTIONS,
51 };
52
53 static struct lttng_handle *handle;
54 static struct mi_writer *writer;
55
56 /* Only set when listing a single session. */
57 static struct lttng_session listed_session;
58
59 static struct poptOption long_options[] = {
60 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
61 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
62 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
63 {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
64 {"log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0},
65 {"python", 'p', POPT_ARG_VAL, &opt_python, 1, 0, 0},
66 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
67 {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0},
68 {"map", 'm', POPT_ARG_STRING, &opt_map, 0, 0, 0},
69 {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0},
70 {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0},
71 {"syscall", 'S', POPT_ARG_VAL, &opt_syscall, 1, 0, 0},
72 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
73 {0, 0, 0, 0, 0, 0, 0}
74 };
75
76 /*
77 * Get command line from /proc for a specific pid.
78 *
79 * On success, return an allocated string pointer to the proc cmdline.
80 * On error, return NULL.
81 */
82 static char *get_cmdline_by_pid(pid_t pid)
83 {
84 int ret;
85 FILE *fp = NULL;
86 char *cmdline = NULL;
87 /* Can't go bigger than /proc/LTTNG_MAX_PID/cmdline */
88 char path[sizeof("/proc//cmdline") + sizeof(LTTNG_MAX_PID_STR) - 1];
89
90 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
91 fp = fopen(path, "r");
92 if (fp == NULL) {
93 goto end;
94 }
95
96 /* Caller must free() *cmdline */
97 cmdline = zmalloc(PATH_MAX);
98 if (!cmdline) {
99 PERROR("malloc cmdline");
100 goto end;
101 }
102 ret = fread(cmdline, 1, PATH_MAX, fp);
103 if (ret < 0) {
104 PERROR("fread proc list");
105 }
106
107 end:
108 if (fp) {
109 fclose(fp);
110 }
111 return cmdline;
112 }
113
114 static
115 const char *active_string(int value)
116 {
117 switch (value) {
118 case 0: return "inactive";
119 case 1: return "active";
120 case -1: return "";
121 default: return NULL;
122 }
123 }
124
125 static const char *snapshot_string(int value)
126 {
127 switch (value) {
128 case 1:
129 return " snapshot";
130 default:
131 return "";
132 }
133 }
134
135 static
136 const char *enabled_string(int value)
137 {
138 switch (value) {
139 case 0: return " [disabled]";
140 case 1: return " [enabled]";
141 case -1: return "";
142 default: return NULL;
143 }
144 }
145
146 static
147 const char *safe_string(const char *str)
148 {
149 return str ? str : "";
150 }
151
152 static const char *logleveltype_string(enum lttng_loglevel_type value)
153 {
154 switch (value) {
155 case LTTNG_EVENT_LOGLEVEL_ALL:
156 return ":";
157 case LTTNG_EVENT_LOGLEVEL_RANGE:
158 return " <=";
159 case LTTNG_EVENT_LOGLEVEL_SINGLE:
160 return " ==";
161 default:
162 return " <<TYPE UNKN>>";
163 }
164 }
165
166 static const char *bitness_event(enum lttng_event_flag flags)
167 {
168 if (flags & LTTNG_EVENT_FLAG_SYSCALL_32) {
169 if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
170 return " [32/64-bit]";
171 } else {
172 return " [32-bit]";
173 }
174 } else if (flags & LTTNG_EVENT_FLAG_SYSCALL_64) {
175 return " [64-bit]";
176 } else {
177 return "";
178 }
179 }
180
181 /*
182 * Get exclusion names message for a single event.
183 *
184 * Returned pointer must be freed by caller. Returns NULL on error.
185 */
186 static char *get_exclusion_names_msg(struct lttng_event *event)
187 {
188 int ret;
189 int exclusion_count;
190 char *exclusion_msg = NULL;
191 char *at;
192 size_t i;
193 const char * const exclusion_fmt = " [exclusions: ";
194 const size_t exclusion_fmt_len = strlen(exclusion_fmt);
195
196 exclusion_count = lttng_event_get_exclusion_name_count(event);
197 if (exclusion_count < 0) {
198 goto end;
199 } else if (exclusion_count == 0) {
200 /*
201 * No exclusions: return copy of empty string so that
202 * it can be freed by caller.
203 */
204 exclusion_msg = strdup("");
205 goto end;
206 }
207
208 /*
209 * exclusion_msg's size is bounded by the exclusion_fmt string,
210 * a comma per entry, the entry count (fixed-size), a closing
211 * bracket, and a trailing \0.
212 */
213 exclusion_msg = malloc(exclusion_count +
214 exclusion_count * LTTNG_SYMBOL_NAME_LEN +
215 exclusion_fmt_len + 1);
216 if (!exclusion_msg) {
217 goto end;
218 }
219
220 at = strcpy(exclusion_msg, exclusion_fmt) + exclusion_fmt_len;
221 for (i = 0; i < exclusion_count; ++i) {
222 const char *name;
223
224 /* Append comma between exclusion names */
225 if (i > 0) {
226 *at = ',';
227 at++;
228 }
229
230 ret = lttng_event_get_exclusion_name(event, i, &name);
231 if (ret) {
232 /* Prints '?' on local error; should never happen */
233 *at = '?';
234 at++;
235 continue;
236 }
237
238 /* Append exclusion name */
239 at += sprintf(at, "%s", name);
240 }
241
242 /* This also puts a final '\0' at the end of exclusion_msg */
243 strcpy(at, "]");
244
245 end:
246 return exclusion_msg;
247 }
248
249 static void print_userspace_probe_location(struct lttng_event *event)
250 {
251 const struct lttng_userspace_probe_location *location;
252 const struct lttng_userspace_probe_location_lookup_method *lookup_method;
253 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
254
255 location = lttng_event_get_userspace_probe_location(event);
256 if (!location) {
257 MSG("Event has no userspace probe location");
258 return;
259 }
260
261 lookup_method = lttng_userspace_probe_location_get_lookup_method(location);
262 if (!lookup_method) {
263 MSG("Event has no userspace probe location lookup method");
264 return;
265 }
266
267 MSG("%s%s (type: userspace-probe)%s", indent6, event->name, enabled_string(event->enabled));
268
269 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
270
271 switch (lttng_userspace_probe_location_get_type(location)) {
272 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
273 MSG("%sType: Unknown", indent8);
274 break;
275 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
276 {
277 const char *function_name;
278 char *binary_path;
279
280 MSG("%sType: Function", indent8);
281 function_name = lttng_userspace_probe_location_function_get_function_name(location);
282 binary_path = realpath(lttng_userspace_probe_location_function_get_binary_path(location), NULL);
283
284 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
285 MSG("%sFunction: %s()", indent8, function_name ? function_name : "NULL");
286 switch (lookup_type) {
287 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
288 MSG("%sLookup method: ELF", indent8);
289 break;
290 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
291 MSG("%sLookup method: default", indent8);
292 break;
293 default:
294 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
295 break;
296 }
297
298 free(binary_path);
299 break;
300 }
301 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
302 {
303 const char *probe_name, *provider_name;
304 char *binary_path;
305
306 MSG("%sType: Tracepoint", indent8);
307 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
308 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
309 binary_path = realpath(lttng_userspace_probe_location_tracepoint_get_binary_path(location), NULL);
310 MSG("%sBinary path: %s", indent8, binary_path ? binary_path : "NULL");
311 MSG("%sTracepoint: %s:%s", indent8, provider_name ? provider_name : "NULL", probe_name ? probe_name : "NULL");
312 switch (lookup_type) {
313 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
314 MSG("%sLookup method: SDT", indent8);
315 break;
316 default:
317 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8);
318 break;
319 }
320
321 free(binary_path);
322 break;
323 }
324 default:
325 ERR("Invalid probe type encountered");
326 }
327 }
328
329 /*
330 * Pretty print single event.
331 */
332 static void print_events(struct lttng_event *event)
333 {
334 int ret;
335 const char *filter_str;
336 char *filter_msg = NULL;
337 char *exclusion_msg = NULL;
338
339 ret = lttng_event_get_filter_expression(event, &filter_str);
340
341 if (ret) {
342 filter_msg = strdup(" [failed to retrieve filter]");
343 } else if (filter_str) {
344 const char * const filter_fmt = " [filter: '%s']";
345
346 filter_msg = malloc(strlen(filter_str) +
347 strlen(filter_fmt) + 1);
348 if (filter_msg) {
349 sprintf(filter_msg, filter_fmt,
350 filter_str);
351 }
352 }
353
354 exclusion_msg = get_exclusion_names_msg(event);
355 if (!exclusion_msg) {
356 exclusion_msg = strdup(" [failed to retrieve exclusions]");
357 }
358
359 switch (event->type) {
360 case LTTNG_EVENT_TRACEPOINT:
361 {
362 if (event->loglevel != -1) {
363 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
364 indent6,
365 event->name,
366 logleveltype_string(event->loglevel_type),
367 mi_lttng_loglevel_string(event->loglevel, handle->domain.type),
368 event->loglevel,
369 enabled_string(event->enabled),
370 safe_string(exclusion_msg),
371 safe_string(filter_msg));
372 } else {
373 MSG("%s%s (type: tracepoint)%s%s%s",
374 indent6,
375 event->name,
376 enabled_string(event->enabled),
377 safe_string(exclusion_msg),
378 safe_string(filter_msg));
379 }
380 break;
381 }
382 case LTTNG_EVENT_FUNCTION:
383 MSG("%s%s (type: function)%s%s", indent6,
384 event->name, enabled_string(event->enabled),
385 safe_string(filter_msg));
386 if (event->attr.probe.addr != 0) {
387 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
388 } else {
389 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
390 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
391 }
392 break;
393 case LTTNG_EVENT_PROBE:
394 MSG("%s%s (type: probe)%s%s", indent6,
395 event->name, enabled_string(event->enabled),
396 safe_string(filter_msg));
397 if (event->attr.probe.addr != 0) {
398 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
399 } else {
400 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
401 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
402 }
403 break;
404 case LTTNG_EVENT_USERSPACE_PROBE:
405 print_userspace_probe_location(event);
406 break;
407 case LTTNG_EVENT_FUNCTION_ENTRY:
408 MSG("%s%s (type: function)%s%s", indent6,
409 event->name, enabled_string(event->enabled),
410 safe_string(filter_msg));
411 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
412 break;
413 case LTTNG_EVENT_SYSCALL:
414 MSG("%s%s%s%s%s%s", indent6, event->name,
415 (opt_syscall ? "" : " (type:syscall)"),
416 enabled_string(event->enabled),
417 bitness_event(event->flags),
418 safe_string(filter_msg));
419 break;
420 case LTTNG_EVENT_NOOP:
421 MSG("%s (type: noop)%s%s", indent6,
422 enabled_string(event->enabled),
423 safe_string(filter_msg));
424 break;
425 case LTTNG_EVENT_ALL:
426 /* Fall-through. */
427 default:
428 /* We should never have "all" events in list. */
429 assert(0);
430 break;
431 }
432
433 free(filter_msg);
434 free(exclusion_msg);
435 }
436
437 static const char *field_type(struct lttng_event_field *field)
438 {
439 switch(field->type) {
440 case LTTNG_EVENT_FIELD_INTEGER:
441 return "integer";
442 case LTTNG_EVENT_FIELD_ENUM:
443 return "enum";
444 case LTTNG_EVENT_FIELD_FLOAT:
445 return "float";
446 case LTTNG_EVENT_FIELD_STRING:
447 return "string";
448 case LTTNG_EVENT_FIELD_OTHER:
449 default: /* fall-through */
450 return "unknown";
451 }
452 }
453
454 /*
455 * Pretty print single event fields.
456 */
457 static void print_event_field(struct lttng_event_field *field)
458 {
459 if (!field->field_name[0]) {
460 return;
461 }
462 MSG("%sfield: %s (%s)%s", indent8, field->field_name,
463 field_type(field), field->nowrite ? " [no write]" : "");
464 }
465
466 /*
467 * Machine interface
468 * Jul and ust event listing
469 */
470 static int mi_list_agent_ust_events(struct lttng_event *events, int count,
471 struct lttng_domain *domain)
472 {
473 int ret, i;
474 pid_t cur_pid = 0;
475 char *cmdline = NULL;
476 int pid_element_open = 0;
477
478 /* Open domains element */
479 ret = mi_lttng_domains_open(writer);
480 if (ret) {
481 goto end;
482 }
483
484 /* Write domain */
485 ret = mi_lttng_domain(writer, domain, 1);
486 if (ret) {
487 goto end;
488 }
489
490 /* Open pids element element */
491 ret = mi_lttng_pids_open(writer);
492 if (ret) {
493 goto end;
494 }
495
496 for (i = 0; i < count; i++) {
497 if (cur_pid != events[i].pid) {
498 if (pid_element_open) {
499 /* Close the previous events and pid element */
500 ret = mi_lttng_close_multi_element(writer, 2);
501 if (ret) {
502 goto end;
503 }
504 pid_element_open = 0;
505 }
506
507 cur_pid = events[i].pid;
508 cmdline = get_cmdline_by_pid(cur_pid);
509 if (!cmdline) {
510 ret = CMD_ERROR;
511 goto end;
512 }
513
514 if (!pid_element_open) {
515 /* Open and write a pid element */
516 ret = mi_lttng_pid(writer, cur_pid, cmdline, 1);
517 if (ret) {
518 goto error;
519 }
520
521 /* Open events element */
522 ret = mi_lttng_events_open(writer);
523 if (ret) {
524 goto error;
525 }
526
527 pid_element_open = 1;
528 }
529 free(cmdline);
530 }
531
532 /* Write an event */
533 ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type);
534 if (ret) {
535 goto end;
536 }
537 }
538
539 /* Close pids */
540 ret = mi_lttng_writer_close_element(writer);
541 if (ret) {
542 goto end;
543 }
544
545 /* Close domain, domains */
546 ret = mi_lttng_close_multi_element(writer, 2);
547 end:
548 return ret;
549 error:
550 free(cmdline);
551 return ret;
552 }
553
554 static int list_agent_events(void)
555 {
556 int i, size, ret = CMD_SUCCESS;
557 struct lttng_domain domain;
558 struct lttng_handle *handle = NULL;
559 struct lttng_event *event_list = NULL;
560 pid_t cur_pid = 0;
561 char *cmdline = NULL;
562 const char *agent_domain_str;
563
564 memset(&domain, 0, sizeof(domain));
565 if (opt_jul) {
566 domain.type = LTTNG_DOMAIN_JUL;
567 } else if (opt_log4j) {
568 domain.type = LTTNG_DOMAIN_LOG4J;
569 } else if (opt_python) {
570 domain.type = LTTNG_DOMAIN_PYTHON;
571 } else {
572 ERR("Invalid agent domain selected.");
573 ret = CMD_ERROR;
574 goto error;
575 }
576
577 agent_domain_str = get_domain_str(domain.type);
578
579 DBG("Getting %s tracing events", agent_domain_str);
580
581 handle = lttng_create_handle(NULL, &domain);
582 if (handle == NULL) {
583 ret = CMD_ERROR;
584 goto end;
585 }
586
587 size = lttng_list_tracepoints(handle, &event_list);
588 if (size < 0) {
589 ERR("Unable to list %s events: %s", agent_domain_str,
590 lttng_strerror(size));
591 ret = CMD_ERROR;
592 goto end;
593 }
594
595 if (lttng_opt_mi) {
596 /* Mi print */
597 ret = mi_list_agent_ust_events(event_list, size, &domain);
598 if (ret) {
599 ret = CMD_ERROR;
600 goto error;
601 }
602 } else {
603 /* Pretty print */
604 MSG("%s events (Logger name):\n-------------------------",
605 agent_domain_str);
606
607 if (size == 0) {
608 MSG("None");
609 }
610
611 for (i = 0; i < size; i++) {
612 if (cur_pid != event_list[i].pid) {
613 cur_pid = event_list[i].pid;
614 cmdline = get_cmdline_by_pid(cur_pid);
615 if (cmdline == NULL) {
616 ret = CMD_ERROR;
617 goto error;
618 }
619 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
620 free(cmdline);
621 }
622 MSG("%s- %s", indent6, event_list[i].name);
623 }
624
625 MSG("");
626 }
627
628 error:
629 free(event_list);
630 end:
631 lttng_destroy_handle(handle);
632 return ret;
633 }
634
635 /*
636 * Ask session daemon for all user space tracepoints available.
637 */
638 static int list_ust_events(void)
639 {
640 int i, size, ret = CMD_SUCCESS;
641 struct lttng_domain domain;
642 struct lttng_handle *handle;
643 struct lttng_event *event_list = NULL;
644 pid_t cur_pid = 0;
645 char *cmdline = NULL;
646
647 memset(&domain, 0, sizeof(domain));
648
649 DBG("Getting UST tracing events");
650
651 domain.type = LTTNG_DOMAIN_UST;
652
653 handle = lttng_create_handle(NULL, &domain);
654 if (handle == NULL) {
655 ret = CMD_ERROR;
656 goto end;
657 }
658
659 size = lttng_list_tracepoints(handle, &event_list);
660 if (size < 0) {
661 ERR("Unable to list UST events: %s", lttng_strerror(size));
662 ret = CMD_ERROR;
663 goto error;
664 }
665
666 if (lttng_opt_mi) {
667 /* Mi print */
668 ret = mi_list_agent_ust_events(event_list, size, &domain);
669 } else {
670 /* Pretty print */
671 MSG("UST events:\n-------------");
672
673 if (size == 0) {
674 MSG("None");
675 }
676
677 for (i = 0; i < size; i++) {
678 if (cur_pid != event_list[i].pid) {
679 cur_pid = event_list[i].pid;
680 cmdline = get_cmdline_by_pid(cur_pid);
681 if (cmdline == NULL) {
682 ret = CMD_ERROR;
683 goto error;
684 }
685 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
686 free(cmdline);
687 }
688 print_events(&event_list[i]);
689 }
690
691 MSG("");
692 }
693
694 error:
695 free(event_list);
696 end:
697 lttng_destroy_handle(handle);
698 return ret;
699 }
700
701 /*
702 * Machine interface
703 * List all ust event with their fields
704 */
705 static int mi_list_ust_event_fields(struct lttng_event_field *fields, int count,
706 struct lttng_domain *domain)
707 {
708 int ret, i;
709 pid_t cur_pid = 0;
710 char *cmdline = NULL;
711 int pid_element_open = 0;
712 int event_element_open = 0;
713 struct lttng_event cur_event;
714
715 memset(&cur_event, 0, sizeof(cur_event));
716
717 /* Open domains element */
718 ret = mi_lttng_domains_open(writer);
719 if (ret) {
720 goto end;
721 }
722
723 /* Write domain */
724 ret = mi_lttng_domain(writer, domain, 1);
725 if (ret) {
726 goto end;
727 }
728
729 /* Open pids element */
730 ret = mi_lttng_pids_open(writer);
731 if (ret) {
732 goto end;
733 }
734
735 for (i = 0; i < count; i++) {
736 if (cur_pid != fields[i].event.pid) {
737 if (pid_element_open) {
738 if (event_element_open) {
739 /* Close the previous field element and event. */
740 ret = mi_lttng_close_multi_element(writer, 2);
741 if (ret) {
742 goto end;
743 }
744 event_element_open = 0;
745 }
746 /* Close the previous events, pid element */
747 ret = mi_lttng_close_multi_element(writer, 2);
748 if (ret) {
749 goto end;
750 }
751 pid_element_open = 0;
752 }
753
754 cur_pid = fields[i].event.pid;
755 cmdline = get_cmdline_by_pid(cur_pid);
756 if (!pid_element_open) {
757 /* Open and write a pid element */
758 ret = mi_lttng_pid(writer, cur_pid, cmdline, 1);
759 if (ret) {
760 goto error;
761 }
762
763 /* Open events element */
764 ret = mi_lttng_events_open(writer);
765 if (ret) {
766 goto error;
767 }
768 pid_element_open = 1;
769 }
770 free(cmdline);
771 /* Wipe current event since we are about to print a new PID. */
772 memset(&cur_event, 0, sizeof(cur_event));
773 }
774
775 if (strcmp(cur_event.name, fields[i].event.name) != 0) {
776 if (event_element_open) {
777 /* Close the previous fields element and the previous event */
778 ret = mi_lttng_close_multi_element(writer, 2);
779 if (ret) {
780 goto end;
781 }
782 event_element_open = 0;
783 }
784
785 memcpy(&cur_event, &fields[i].event,
786 sizeof(cur_event));
787
788 if (!event_element_open) {
789 /* Open and write the event */
790 ret = mi_lttng_event(writer, &cur_event, 1,
791 handle->domain.type);
792 if (ret) {
793 goto end;
794 }
795
796 /* Open a fields element */
797 ret = mi_lttng_event_fields_open(writer);
798 if (ret) {
799 goto end;
800 }
801 event_element_open = 1;
802 }
803 }
804
805 /* Print the event_field */
806 ret = mi_lttng_event_field(writer, &fields[i]);
807 if (ret) {
808 goto end;
809 }
810 }
811
812 /* Close pids, domain, domains */
813 ret = mi_lttng_close_multi_element(writer, 3);
814 end:
815 return ret;
816 error:
817 free(cmdline);
818 return ret;
819 }
820
821 /*
822 * Ask session daemon for all user space tracepoint fields available.
823 */
824 static int list_ust_event_fields(void)
825 {
826 int i, size, ret = CMD_SUCCESS;
827 struct lttng_domain domain;
828 struct lttng_handle *handle;
829 struct lttng_event_field *event_field_list;
830 pid_t cur_pid = 0;
831 char *cmdline = NULL;
832
833 struct lttng_event cur_event;
834
835 memset(&domain, 0, sizeof(domain));
836 memset(&cur_event, 0, sizeof(cur_event));
837
838 DBG("Getting UST tracing event fields");
839
840 domain.type = LTTNG_DOMAIN_UST;
841
842 handle = lttng_create_handle(NULL, &domain);
843 if (handle == NULL) {
844 ret = CMD_ERROR;
845 goto end;
846 }
847
848 size = lttng_list_tracepoint_fields(handle, &event_field_list);
849 if (size < 0) {
850 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
851 ret = CMD_ERROR;
852 goto end;
853 }
854
855 if (lttng_opt_mi) {
856 /* Mi print */
857 ret = mi_list_ust_event_fields(event_field_list, size, &domain);
858 if (ret) {
859 ret = CMD_ERROR;
860 goto error;
861 }
862 } else {
863 /* Pretty print */
864 MSG("UST events:\n-------------");
865
866 if (size == 0) {
867 MSG("None");
868 }
869
870 for (i = 0; i < size; i++) {
871 if (cur_pid != event_field_list[i].event.pid) {
872 cur_pid = event_field_list[i].event.pid;
873 cmdline = get_cmdline_by_pid(cur_pid);
874 if (cmdline == NULL) {
875 ret = CMD_ERROR;
876 goto error;
877 }
878 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
879 free(cmdline);
880 /* Wipe current event since we are about to print a new PID. */
881 memset(&cur_event, 0, sizeof(cur_event));
882 }
883 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
884 print_events(&event_field_list[i].event);
885 memcpy(&cur_event, &event_field_list[i].event,
886 sizeof(cur_event));
887 }
888 print_event_field(&event_field_list[i]);
889 }
890
891 MSG("");
892 }
893
894 error:
895 free(event_field_list);
896 end:
897 lttng_destroy_handle(handle);
898 return ret;
899 }
900
901 /*
902 * Machine interface
903 * Print a list of kernel events
904 */
905 static int mi_list_kernel_events(struct lttng_event *events, int count,
906 struct lttng_domain *domain)
907 {
908 int ret, i;
909
910 /* Open domains element */
911 ret = mi_lttng_domains_open(writer);
912 if (ret) {
913 goto end;
914 }
915
916 /* Write domain */
917 ret = mi_lttng_domain(writer, domain, 1);
918 if (ret) {
919 goto end;
920 }
921
922 /* Open events */
923 ret = mi_lttng_events_open(writer);
924 if (ret) {
925 goto end;
926 }
927
928 for (i = 0; i < count; i++) {
929 ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type);
930 if (ret) {
931 goto end;
932 }
933 }
934
935 /* close events, domain and domains */
936 ret = mi_lttng_close_multi_element(writer, 3);
937 if (ret) {
938 goto end;
939 }
940
941 end:
942 return ret;
943 }
944
945 /*
946 * Ask for all trace events in the kernel
947 */
948 static int list_kernel_events(void)
949 {
950 int i, size, ret = CMD_SUCCESS;
951 struct lttng_domain domain;
952 struct lttng_handle *handle;
953 struct lttng_event *event_list;
954
955 memset(&domain, 0, sizeof(domain));
956
957 DBG("Getting kernel tracing events");
958
959 domain.type = LTTNG_DOMAIN_KERNEL;
960
961 handle = lttng_create_handle(NULL, &domain);
962 if (handle == NULL) {
963 ret = CMD_ERROR;
964 goto error;
965 }
966
967 size = lttng_list_tracepoints(handle, &event_list);
968 if (size < 0) {
969 ERR("Unable to list kernel events: %s", lttng_strerror(size));
970 lttng_destroy_handle(handle);
971 return CMD_ERROR;
972 }
973
974 if (lttng_opt_mi) {
975 /* Mi print */
976 ret = mi_list_kernel_events(event_list, size, &domain);
977 if (ret) {
978 ret = CMD_ERROR;
979 goto end;
980 }
981 } else {
982 MSG("Kernel events:\n-------------");
983
984 for (i = 0; i < size; i++) {
985 print_events(&event_list[i]);
986 }
987
988 MSG("");
989 }
990
991 end:
992 free(event_list);
993
994 lttng_destroy_handle(handle);
995 return ret;
996
997 error:
998 lttng_destroy_handle(handle);
999 return ret;
1000 }
1001
1002 /*
1003 * Machine interface
1004 * Print a list of system calls.
1005 */
1006 static int mi_list_syscalls(struct lttng_event *events, int count)
1007 {
1008 int ret, i;
1009
1010 /* Open events */
1011 ret = mi_lttng_events_open(writer);
1012 if (ret) {
1013 goto end;
1014 }
1015
1016 for (i = 0; i < count; i++) {
1017 ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type);
1018 if (ret) {
1019 goto end;
1020 }
1021 }
1022
1023 /* Close events. */
1024 ret = mi_lttng_writer_close_element(writer);
1025 if (ret) {
1026 goto end;
1027 }
1028
1029 end:
1030 return ret;
1031 }
1032
1033 /*
1034 * Ask for kernel system calls.
1035 */
1036 static int list_syscalls(void)
1037 {
1038 int i, size, ret = CMD_SUCCESS;
1039 struct lttng_event *event_list;
1040
1041 DBG("Getting kernel system call events");
1042
1043 size = lttng_list_syscalls(&event_list);
1044 if (size < 0) {
1045 ERR("Unable to list system calls: %s", lttng_strerror(size));
1046 ret = CMD_ERROR;
1047 goto error;
1048 }
1049
1050 if (lttng_opt_mi) {
1051 /* Mi print */
1052 ret = mi_list_syscalls(event_list, size);
1053 if (ret) {
1054 ret = CMD_ERROR;
1055 goto end;
1056 }
1057 } else {
1058 MSG("System calls:\n-------------");
1059
1060 for (i = 0; i < size; i++) {
1061 print_events(&event_list[i]);
1062 }
1063
1064 MSG("");
1065 }
1066
1067 end:
1068 free(event_list);
1069 return ret;
1070
1071 error:
1072 return ret;
1073 }
1074
1075 /*
1076 * Machine Interface
1077 * Print a list of agent events
1078 */
1079 static int mi_list_session_agent_events(struct lttng_event *events, int count)
1080 {
1081 int ret, i;
1082
1083 /* Open events element */
1084 ret = mi_lttng_events_open(writer);
1085 if (ret) {
1086 goto end;
1087 }
1088
1089 for (i = 0; i < count; i++) {
1090 ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type);
1091 if (ret) {
1092 goto end;
1093 }
1094 }
1095
1096 /* Close events element */
1097 ret = mi_lttng_writer_close_element(writer);
1098
1099 end:
1100 return ret;
1101 }
1102
1103 /*
1104 * List agent events for a specific session using the handle.
1105 *
1106 * Return CMD_SUCCESS on success else a negative value.
1107 */
1108 static int list_session_agent_events(void)
1109 {
1110 int ret = CMD_SUCCESS, count, i;
1111 struct lttng_event *events = NULL;
1112
1113 count = lttng_list_events(handle, "", &events);
1114 if (count < 0) {
1115 ret = CMD_ERROR;
1116 ERR("%s", lttng_strerror(count));
1117 goto error;
1118 }
1119
1120 if (lttng_opt_mi) {
1121 /* Mi print */
1122 ret = mi_list_session_agent_events(events, count);
1123 if (ret) {
1124 ret = CMD_ERROR;
1125 goto end;
1126 }
1127 } else {
1128 /* Pretty print */
1129 MSG("Events (Logger name):\n---------------------");
1130 if (count == 0) {
1131 MSG("%sNone\n", indent6);
1132 goto end;
1133 }
1134
1135 for (i = 0; i < count; i++) {
1136 const char *filter_str;
1137 char *filter_msg = NULL;
1138 struct lttng_event *event = &events[i];
1139
1140 ret = lttng_event_get_filter_expression(event,
1141 &filter_str);
1142 if (ret) {
1143 filter_msg = strdup(" [failed to retrieve filter]");
1144 } else if (filter_str) {
1145 const char * const filter_fmt =
1146 " [filter: '%s']";
1147
1148 filter_msg = malloc(strlen(filter_str) +
1149 strlen(filter_fmt) + 1);
1150 if (filter_msg) {
1151 sprintf(filter_msg, filter_fmt,
1152 filter_str);
1153 }
1154 }
1155
1156 if (event->loglevel_type !=
1157 LTTNG_EVENT_LOGLEVEL_ALL) {
1158 MSG("%s- %s%s (loglevel%s %s)%s", indent4,
1159 event->name,
1160 enabled_string(event->enabled),
1161 logleveltype_string(
1162 event->loglevel_type),
1163 mi_lttng_loglevel_string(
1164 event->loglevel,
1165 handle->domain.type),
1166 safe_string(filter_msg));
1167 } else {
1168 MSG("%s- %s%s%s", indent4, event->name,
1169 enabled_string(event->enabled),
1170 safe_string(filter_msg));
1171 }
1172 free(filter_msg);
1173 }
1174
1175 MSG("");
1176 }
1177
1178 end:
1179 free(events);
1180 error:
1181 return ret;
1182 }
1183
1184 /*
1185 * Machine interface
1186 * print a list of event
1187 */
1188 static int mi_list_events(struct lttng_event *events, int count)
1189 {
1190 int ret, i;
1191
1192 /* Open events element */
1193 ret = mi_lttng_events_open(writer);
1194 if (ret) {
1195 goto end;
1196 }
1197
1198 for (i = 0; i < count; i++) {
1199 ret = mi_lttng_event(writer, &events[i], 0, handle->domain.type);
1200 if (ret) {
1201 goto end;
1202 }
1203 }
1204
1205 /* Close events element */
1206 ret = mi_lttng_writer_close_element(writer);
1207
1208 end:
1209 return ret;
1210 }
1211
1212 /*
1213 * List events of channel of session and domain.
1214 */
1215 static int list_events(const char *channel_name)
1216 {
1217 int ret = CMD_SUCCESS, count, i;
1218 struct lttng_event *events = NULL;
1219
1220 count = lttng_list_events(handle, channel_name, &events);
1221 if (count < 0) {
1222 ret = CMD_ERROR;
1223 ERR("%s", lttng_strerror(count));
1224 goto error;
1225 }
1226
1227 if (lttng_opt_mi) {
1228 /* Mi print */
1229 ret = mi_list_events(events, count);
1230 if (ret) {
1231 ret = CMD_ERROR;
1232 goto end;
1233 }
1234 } else {
1235 /* Pretty print */
1236 MSG("\n%sEvent rules:", indent4);
1237 if (count == 0) {
1238 MSG("%sNone\n", indent6);
1239 goto end;
1240 }
1241
1242 for (i = 0; i < count; i++) {
1243 print_events(&events[i]);
1244 }
1245
1246 MSG("");
1247 }
1248 end:
1249 free(events);
1250 error:
1251 return ret;
1252 }
1253
1254 static
1255 void print_timer(const char *timer_name, uint32_t space_count, int64_t value)
1256 {
1257 uint32_t i;
1258
1259 _MSG("%s%s:", indent6, timer_name);
1260 for (i = 0; i < space_count; i++) {
1261 _MSG(" ");
1262 }
1263
1264 if (value) {
1265 MSG("%" PRId64 " %s", value, USEC_UNIT);
1266 } else {
1267 MSG("inactive");
1268 }
1269 }
1270
1271 /*
1272 * Pretty print channel
1273 */
1274 static void print_channel(struct lttng_channel *channel)
1275 {
1276 int ret;
1277 uint64_t discarded_events, lost_packets, monitor_timer_interval;
1278 int64_t blocking_timeout;
1279
1280 ret = lttng_channel_get_discarded_event_count(channel,
1281 &discarded_events);
1282 if (ret) {
1283 ERR("Failed to retrieve discarded event count of channel");
1284 return;
1285 }
1286
1287 ret = lttng_channel_get_lost_packet_count(channel,
1288 &lost_packets);
1289 if (ret) {
1290 ERR("Failed to retrieve lost packet count of channel");
1291 return;
1292 }
1293
1294 ret = lttng_channel_get_monitor_timer_interval(channel,
1295 &monitor_timer_interval);
1296 if (ret) {
1297 ERR("Failed to retrieve monitor interval of channel");
1298 return;
1299 }
1300
1301 ret = lttng_channel_get_blocking_timeout(channel,
1302 &blocking_timeout);
1303 if (ret) {
1304 ERR("Failed to retrieve blocking timeout of channel");
1305 return;
1306 }
1307
1308 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
1309 MSG("%sAttributes:", indent4);
1310 MSG("%sEvent-loss mode: %s", indent6, channel->attr.overwrite ? "overwrite" : "discard");
1311 MSG("%sSub-buffer size: %" PRIu64 " bytes", indent6, channel->attr.subbuf_size);
1312 MSG("%sSub-buffer count: %" PRIu64, indent6, channel->attr.num_subbuf);
1313
1314 print_timer("Switch timer", 5, channel->attr.switch_timer_interval);
1315 print_timer("Read timer", 7, channel->attr.read_timer_interval);
1316 print_timer("Monitor timer", 4, monitor_timer_interval);
1317
1318 if (!channel->attr.overwrite) {
1319 if (blocking_timeout == -1) {
1320 MSG("%sBlocking timeout: infinite", indent6);
1321 } else {
1322 MSG("%sBlocking timeout: %" PRId64 " %s", indent6,
1323 blocking_timeout, USEC_UNIT);
1324 }
1325 }
1326
1327 MSG("%sTrace file count: %" PRIu64 " per stream", indent6,
1328 channel->attr.tracefile_count == 0 ?
1329 1 : channel->attr.tracefile_count);
1330 if (channel->attr.tracefile_size != 0 ) {
1331 MSG("%sTrace file size: %" PRIu64 " bytes", indent6,
1332 channel->attr.tracefile_size);
1333 } else {
1334 MSG("%sTrace file size: %s", indent6, "unlimited");
1335 }
1336 switch (channel->attr.output) {
1337 case LTTNG_EVENT_SPLICE:
1338 MSG("%sOutput mode: splice", indent6);
1339 break;
1340 case LTTNG_EVENT_MMAP:
1341 MSG("%sOutput mode: mmap", indent6);
1342 break;
1343 }
1344
1345 MSG("\n%sStatistics:", indent4);
1346 if (listed_session.snapshot_mode) {
1347 /*
1348 * The lost packet count is omitted for sessions in snapshot
1349 * mode as it is misleading: it would indicate the number of
1350 * packets that the consumer could not extract during the
1351 * course of recording the snapshot. It does not have the
1352 * same meaning as the "regular" lost packet count that
1353 * would result from the consumer not keeping up with
1354 * event production in an overwrite-mode channel.
1355 *
1356 * A more interesting statistic would be the number of
1357 * packets lost between the first and last extracted
1358 * packets of a given snapshot (which prevents most analyses).
1359 */
1360 MSG("%sNone", indent6);
1361 goto skip_stats_printing;
1362 }
1363
1364 if (!channel->attr.overwrite) {
1365 MSG("%sDiscarded events: %" PRIu64, indent6, discarded_events);
1366 } else {
1367 MSG("%sLost packets: %" PRIu64, indent6, lost_packets);
1368 }
1369 skip_stats_printing:
1370 return;
1371 }
1372
1373 static void print_map(const struct lttng_map *map)
1374 {
1375 const char *map_name;
1376 enum lttng_map_status map_status;
1377 enum lttng_buffer_type buffer_type;
1378 enum lttng_map_bitness bitness;
1379 enum lttng_map_boundary_policy boundary_policy;
1380 uint64_t bucket_count;
1381 bool is_enabled;
1382 bool coalesces_hits;
1383
1384 bitness = lttng_map_get_bitness(map);
1385 is_enabled = lttng_map_get_is_enabled(map);
1386 buffer_type = lttng_map_get_buffer_type(map);
1387 coalesces_hits = lttng_map_get_coalesce_hits(map);
1388 boundary_policy = lttng_map_get_boundary_policy(map);
1389
1390 map_status = lttng_map_get_name(map, &map_name);
1391 if (map_status != LTTNG_MAP_STATUS_OK) {
1392 ERR("Failed to get map name");
1393 goto end;
1394 }
1395
1396 map_status = lttng_map_get_dimension_length(map, 0, &bucket_count);
1397 if (map_status != LTTNG_MAP_STATUS_OK) {
1398 ERR("Failed to bucket count");
1399 goto end;
1400 }
1401
1402 MSG("- %s (%s)", map_name, is_enabled ? "enabled": "disabled");
1403 MSG("%sAttributes:", indent4);
1404 MSG("%sBitness: %s", indent6, bitness == LTTNG_MAP_BITNESS_32BITS ? "32" : "64");
1405 _MSG("%sCounter type: ", indent6);
1406 switch (buffer_type) {
1407 case LTTNG_BUFFER_PER_PID:
1408 MSG("per-pid");
1409 break;
1410 case LTTNG_BUFFER_PER_UID:
1411 MSG("per-uid");
1412 break;
1413 case LTTNG_BUFFER_GLOBAL:
1414 MSG("global");
1415 break;
1416 default:
1417 abort();
1418 }
1419 MSG("%sBoundary policy: %s", indent6,
1420 boundary_policy == LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW ? "OVERFLOW" : "<unknown>");
1421 MSG("%sBucket count: %"PRIu64, indent6, bucket_count);
1422 MSG("%sCoalesces hits: %s", indent6, coalesces_hits ? "TRUE":"FALSE");
1423 end:
1424 return;
1425 }
1426
1427 /*
1428 * Machine interface
1429 * Print a list of channel
1430 *
1431 */
1432 static int mi_list_channels(struct lttng_channel *channels, int count,
1433 const char *channel_name)
1434 {
1435 int i, ret;
1436 unsigned int chan_found = 0;
1437
1438 /* Open channels element */
1439 ret = mi_lttng_channels_open(writer);
1440 if (ret) {
1441 goto error;
1442 }
1443
1444 for (i = 0; i < count; i++) {
1445 if (channel_name != NULL) {
1446 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1447 chan_found = 1;
1448 } else {
1449 continue;
1450 }
1451 }
1452
1453 /* Write channel element and leave it open */
1454 ret = mi_lttng_channel(writer, &channels[i], 1);
1455 if (ret) {
1456 goto error;
1457 }
1458
1459 /* Listing events per channel */
1460 ret = list_events(channels[i].name);
1461 if (ret) {
1462 goto error;
1463 }
1464
1465 /* Closing the channel element we opened earlier */
1466 ret = mi_lttng_writer_close_element(writer);
1467 if (ret) {
1468 goto error;
1469 }
1470
1471 if (chan_found) {
1472 break;
1473 }
1474 }
1475
1476 /* Close channels element */
1477 ret = mi_lttng_writer_close_element(writer);
1478 if (ret) {
1479 goto error;
1480 }
1481
1482 error:
1483 return ret;
1484 }
1485
1486 /*
1487 * List channel(s) of session and domain.
1488 *
1489 * If channel_name is NULL, all channels are listed.
1490 */
1491 static int list_channels(const char *channel_name)
1492 {
1493 int count, i, ret = CMD_SUCCESS;
1494 unsigned int chan_found = 0;
1495 struct lttng_channel *channels = NULL;
1496
1497 DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
1498
1499 count = lttng_list_channels(handle, &channels);
1500 if (count < 0) {
1501 switch (-count) {
1502 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
1503 if (lttng_opt_mi) {
1504 /* When printing mi this is not an error
1505 * but an empty channels element */
1506 count = 0;
1507 } else {
1508 ret = CMD_SUCCESS;
1509 goto error_channels;
1510 }
1511 break;
1512 default:
1513 /* We had a real error */
1514 ret = CMD_ERROR;
1515 ERR("%s", lttng_strerror(count));
1516 goto error_channels;
1517 break;
1518 }
1519 }
1520
1521 if (lttng_opt_mi) {
1522 /* Mi print */
1523 ret = mi_list_channels(channels, count, channel_name);
1524 if (ret) {
1525 ret = CMD_ERROR;
1526 goto error;
1527 }
1528 } else {
1529 /* Pretty print */
1530 if (count) {
1531 MSG("Channels:\n-------------");
1532 }
1533
1534 for (i = 0; i < count; i++) {
1535 if (channel_name != NULL) {
1536 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
1537 chan_found = 1;
1538 } else {
1539 continue;
1540 }
1541 }
1542 print_channel(&channels[i]);
1543
1544 /* Listing events per channel */
1545 ret = list_events(channels[i].name);
1546 if (ret) {
1547 goto error;
1548 }
1549
1550 if (chan_found) {
1551 break;
1552 }
1553 }
1554
1555 if (!chan_found && channel_name != NULL) {
1556 ret = CMD_ERROR;
1557 ERR("Channel %s not found", channel_name);
1558 goto error;
1559 }
1560 }
1561 error:
1562 free(channels);
1563
1564 error_channels:
1565 return ret;
1566 }
1567
1568 /*
1569 * List map(s) of session and domain.
1570 *
1571 * If map_name is NULL, all maps are listed.
1572 */
1573 static int list_maps(const char *desired_map_name)
1574 {
1575 struct lttng_map_list *map_list = NULL;
1576 enum lttng_map_status map_status;
1577 enum lttng_error_code ret_code;
1578 unsigned int i, map_count;
1579 int ret = CMD_SUCCESS;
1580
1581 DBG("Listing map(s) (%s)", desired_map_name ? : "<all>");
1582
1583 ret_code = lttng_list_maps(handle, &map_list);
1584 if (ret_code != LTTNG_OK) {
1585 ERR("Error getting map list");
1586 ret = CMD_ERROR;
1587 goto end;
1588 }
1589
1590 map_status = lttng_map_list_get_count(map_list, &map_count);
1591 if (map_status != LTTNG_MAP_STATUS_OK) {
1592 ERR("Error getting map list element count");
1593 ret = CMD_ERROR;
1594 goto end;
1595 }
1596
1597 MSG("Maps:\n-------------");
1598 for (i = 0; i < map_count; i++) {
1599 const struct lttng_map *map = NULL;
1600 const char *map_name = NULL;
1601 map = lttng_map_list_get_at_index(map_list, i);
1602 if (!map) {
1603 ret = CMD_ERROR;
1604 ERR("Error getting map from list: index = %u", i);
1605 goto end;
1606 }
1607
1608 map_status = lttng_map_get_name(map, &map_name);
1609 if (map_status != LTTNG_MAP_STATUS_OK) {
1610 ERR("Error getting map name");
1611 ret = CMD_ERROR;
1612 goto end;
1613 }
1614
1615 if (desired_map_name != NULL) {
1616 if (strncmp(map_name, desired_map_name, NAME_MAX) == 0) {
1617 print_map(map);
1618 break;
1619 }
1620 } else {
1621 print_map(map);
1622 }
1623 }
1624 end:
1625 lttng_map_list_destroy(map_list);
1626 return ret;
1627 }
1628
1629 static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr)
1630 {
1631 switch (process_attr) {
1632 case LTTNG_PROCESS_ATTR_PROCESS_ID:
1633 return "Process ID";
1634 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID:
1635 return "Virtual process ID";
1636 case LTTNG_PROCESS_ATTR_USER_ID:
1637 return "User ID";
1638 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID:
1639 return "Virtual user ID";
1640 case LTTNG_PROCESS_ATTR_GROUP_ID:
1641 return "Group ID";
1642 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID:
1643 return "Virtual group ID";
1644 default:
1645 return "Unknown";
1646 }
1647 return NULL;
1648 }
1649
1650 static int handle_process_attr_status(enum lttng_process_attr process_attr,
1651 enum lttng_process_attr_tracker_handle_status status)
1652 {
1653 int ret = CMD_SUCCESS;
1654
1655 switch (status) {
1656 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
1657 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
1658 /* Carry on. */
1659 break;
1660 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
1661 ERR("Communication occurred while fetching %s tracker",
1662 lttng_process_attr_to_string(process_attr));
1663 ret = CMD_ERROR;
1664 break;
1665 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
1666 ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists",
1667 lttng_process_attr_to_string(process_attr),
1668 handle->session_name);
1669 ret = CMD_ERROR;
1670 break;
1671 default:
1672 ERR("Unknown error occurred while fetching the inclusion set of the %s tracker",
1673 lttng_process_attr_to_string(process_attr));
1674 ret = CMD_ERROR;
1675 break;
1676 }
1677
1678 return ret;
1679 }
1680
1681 static int mi_output_empty_tracker(enum lttng_process_attr process_attr)
1682 {
1683 int ret;
1684
1685 ret = mi_lttng_process_attribute_tracker_open(writer, process_attr);
1686 if (ret) {
1687 goto end;
1688 }
1689
1690 ret = mi_lttng_close_multi_element(writer, 2);
1691 end:
1692 return ret;
1693 }
1694
1695 static inline bool is_value_type_name(
1696 enum lttng_process_attr_value_type value_type)
1697 {
1698 return value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME ||
1699 value_type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME;
1700 }
1701
1702 /*
1703 * List a process attribute tracker for a session and domain tuple.
1704 */
1705 static int list_process_attr_tracker(enum lttng_process_attr process_attr)
1706 {
1707 int ret = 0;
1708 unsigned int count, i;
1709 enum lttng_tracking_policy policy;
1710 enum lttng_error_code ret_code;
1711 enum lttng_process_attr_tracker_handle_status handle_status;
1712 enum lttng_process_attr_values_status values_status;
1713 const struct lttng_process_attr_values *values;
1714 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
1715
1716 ret_code = lttng_session_get_tracker_handle(handle->session_name,
1717 handle->domain.type, process_attr, &tracker_handle);
1718 if (ret_code != LTTNG_OK) {
1719 ERR("Failed to get process attribute tracker handle: %s",
1720 lttng_strerror(ret_code));
1721 ret = CMD_ERROR;
1722 goto end;
1723 }
1724
1725 handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
1726 tracker_handle, &values);
1727 ret = handle_process_attr_status(process_attr, handle_status);
1728 if (ret != CMD_SUCCESS) {
1729 goto end;
1730 }
1731
1732 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
1733 tracker_handle, &policy);
1734 ret = handle_process_attr_status(process_attr, handle_status);
1735 if (ret != CMD_SUCCESS) {
1736 goto end;
1737 }
1738
1739 {
1740 char *process_attr_name;
1741 const int print_ret = asprintf(&process_attr_name, "%ss:",
1742 get_capitalized_process_attr_str(process_attr));
1743
1744 if (print_ret == -1) {
1745 ret = CMD_FATAL;
1746 goto end;
1747 }
1748 _MSG(" %-22s", process_attr_name);
1749 free(process_attr_name);
1750 }
1751 switch (policy) {
1752 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
1753 break;
1754 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
1755 if (writer) {
1756 mi_output_empty_tracker(process_attr);
1757 }
1758 MSG("none");
1759 ret = CMD_SUCCESS;
1760 goto end;
1761 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
1762 MSG("all");
1763 ret = CMD_SUCCESS;
1764 goto end;
1765 default:
1766 ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`",
1767 lttng_process_attr_to_string(process_attr),
1768 handle->session_name);
1769 ret = CMD_FATAL;
1770 goto end;
1771 }
1772
1773 values_status = lttng_process_attr_values_get_count(values, &count);
1774 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1775 ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`",
1776 lttng_process_attr_to_string(process_attr),
1777 handle->session_name);
1778 ret = CMD_FATAL;
1779 goto end;
1780 }
1781
1782 if (count == 0) {
1783 /* Functionally equivalent to the 'exclude all' policy. */
1784 if (writer) {
1785 mi_output_empty_tracker(process_attr);
1786 }
1787 MSG("none");
1788 ret = CMD_SUCCESS;
1789 goto end;
1790 }
1791
1792 /* Mi tracker_id element */
1793 if (writer) {
1794 /* Open tracker_id and targets elements */
1795 ret = mi_lttng_process_attribute_tracker_open(
1796 writer, process_attr);
1797 if (ret) {
1798 goto end;
1799 }
1800 }
1801
1802 for (i = 0; i < count; i++) {
1803 const enum lttng_process_attr_value_type value_type =
1804 lttng_process_attr_values_get_type_at_index(
1805 values, i);
1806 int64_t integral_value = INT64_MAX;
1807 const char *name = "error";
1808
1809 if (i >= 1) {
1810 _MSG(", ");
1811 }
1812 switch (value_type) {
1813 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID:
1814 {
1815 pid_t pid;
1816
1817 values_status = lttng_process_attr_values_get_pid_at_index(
1818 values, i, &pid);
1819 integral_value = (int64_t) pid;
1820 break;
1821 }
1822 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID:
1823 {
1824 uid_t uid;
1825
1826 values_status = lttng_process_attr_values_get_uid_at_index(
1827 values, i, &uid);
1828 integral_value = (int64_t) uid;
1829 break;
1830 }
1831 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID:
1832 {
1833 gid_t gid;
1834
1835 values_status = lttng_process_attr_values_get_gid_at_index(
1836 values, i, &gid);
1837 integral_value = (int64_t) gid;
1838 break;
1839 }
1840 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME:
1841 values_status = lttng_process_attr_values_get_user_name_at_index(
1842 values, i, &name);
1843 break;
1844 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME:
1845 values_status = lttng_process_attr_values_get_group_name_at_index(
1846 values, i, &name);
1847 break;
1848 default:
1849 ret = CMD_ERROR;
1850 goto end;
1851 }
1852
1853 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
1854 /*
1855 * Not possible given the current liblttng-ctl
1856 * implementation.
1857 */
1858 ERR("Unknown error occurred while fetching process attribute value in inclusion list");
1859 ret = CMD_FATAL;
1860 goto end;
1861 }
1862
1863 if (is_value_type_name(value_type)) {
1864 _MSG("`%s`", name);
1865 } else {
1866 _MSG("%" PRIi64, integral_value);
1867 }
1868
1869 /* Mi */
1870 if (writer) {
1871 ret = is_value_type_name(value_type) ?
1872 mi_lttng_string_process_attribute_value(
1873 writer,
1874 process_attr,
1875 name, false) :
1876 mi_lttng_integral_process_attribute_value(
1877 writer,
1878 process_attr,
1879 integral_value,
1880 false);
1881 if (ret) {
1882 goto end;
1883 }
1884 }
1885 }
1886 MSG("");
1887
1888 /* Mi close tracker_id and targets */
1889 if (writer) {
1890 ret = mi_lttng_close_multi_element(writer, 2);
1891 if (ret) {
1892 goto end;
1893 }
1894 }
1895 end:
1896 lttng_process_attr_tracker_handle_destroy(tracker_handle);
1897 return ret;
1898 }
1899
1900 /*
1901 * List all trackers of a domain
1902 */
1903 static int list_trackers(const struct lttng_domain *domain)
1904 {
1905 int ret = 0;
1906
1907 MSG("Tracked process attributes");
1908 /* Trackers listing */
1909 if (lttng_opt_mi) {
1910 ret = mi_lttng_trackers_open(writer);
1911 if (ret) {
1912 goto end;
1913 }
1914 }
1915
1916 switch (domain->type) {
1917 case LTTNG_DOMAIN_KERNEL:
1918 /* pid tracker */
1919 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID);
1920 if (ret) {
1921 goto end;
1922 }
1923 /* vpid tracker */
1924 ret = list_process_attr_tracker(
1925 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
1926 if (ret) {
1927 goto end;
1928 }
1929 /* uid tracker */
1930 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID);
1931 if (ret) {
1932 goto end;
1933 }
1934 /* vuid tracker */
1935 ret = list_process_attr_tracker(
1936 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
1937 if (ret) {
1938 goto end;
1939 }
1940 /* gid tracker */
1941 ret = list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID);
1942 if (ret) {
1943 goto end;
1944 }
1945 /* vgid tracker */
1946 ret = list_process_attr_tracker(
1947 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
1948 if (ret) {
1949 goto end;
1950 }
1951 break;
1952 case LTTNG_DOMAIN_UST:
1953 /* vpid tracker */
1954 ret = list_process_attr_tracker(
1955 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
1956 if (ret) {
1957 goto end;
1958 }
1959 /* vuid tracker */
1960 ret = list_process_attr_tracker(
1961 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
1962 if (ret) {
1963 goto end;
1964 }
1965 /* vgid tracker */
1966 ret = list_process_attr_tracker(
1967 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
1968 if (ret) {
1969 goto end;
1970 }
1971 break;
1972 default:
1973 break;
1974 }
1975 MSG();
1976 if (lttng_opt_mi) {
1977 /* Close trackers element */
1978 ret = mi_lttng_writer_close_element(writer);
1979 if (ret) {
1980 goto end;
1981 }
1982 }
1983
1984 end:
1985 return ret;
1986 }
1987
1988 static enum cmd_error_code print_periodic_rotation_schedule(
1989 const struct lttng_rotation_schedule *schedule)
1990 {
1991 enum cmd_error_code ret;
1992 enum lttng_rotation_status status;
1993 uint64_t value;
1994
1995 status = lttng_rotation_schedule_periodic_get_period(schedule,
1996 &value);
1997 if (status != LTTNG_ROTATION_STATUS_OK) {
1998 ERR("Failed to retrieve period parameter from periodic rotation schedule.");
1999 ret = CMD_ERROR;
2000 goto end;
2001 }
2002
2003 MSG(" timer period: %" PRIu64" %s", value, USEC_UNIT);
2004 ret = CMD_SUCCESS;
2005 end:
2006 return ret;
2007 }
2008
2009 static enum cmd_error_code print_size_threshold_rotation_schedule(
2010 const struct lttng_rotation_schedule *schedule)
2011 {
2012 enum cmd_error_code ret;
2013 enum lttng_rotation_status status;
2014 uint64_t value;
2015
2016 status = lttng_rotation_schedule_size_threshold_get_threshold(schedule,
2017 &value);
2018 if (status != LTTNG_ROTATION_STATUS_OK) {
2019 ERR("Failed to retrieve size parameter from size-based rotation schedule.");
2020 ret = CMD_ERROR;
2021 goto end;
2022 }
2023
2024 MSG(" size threshold: %" PRIu64" bytes", value);
2025 ret = CMD_SUCCESS;
2026 end:
2027 return ret;
2028 }
2029
2030 static enum cmd_error_code print_rotation_schedule(
2031 const struct lttng_rotation_schedule *schedule)
2032 {
2033 enum cmd_error_code ret;
2034
2035 switch (lttng_rotation_schedule_get_type(schedule)) {
2036 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD:
2037 ret = print_size_threshold_rotation_schedule(schedule);
2038 break;
2039 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC:
2040 ret = print_periodic_rotation_schedule(schedule);
2041 break;
2042 default:
2043 ret = CMD_ERROR;
2044 }
2045 return ret;
2046 }
2047
2048 /*
2049 * List the automatic rotation settings.
2050 */
2051 static enum cmd_error_code list_rotate_settings(const char *session_name)
2052 {
2053 int ret;
2054 enum cmd_error_code cmd_ret = CMD_SUCCESS;
2055 unsigned int count, i;
2056 struct lttng_rotation_schedules *schedules = NULL;
2057 enum lttng_rotation_status status;
2058
2059 ret = lttng_session_list_rotation_schedules(session_name, &schedules);
2060 if (ret != LTTNG_OK) {
2061 ERR("Failed to list session rotation schedules: %s", lttng_strerror(ret));
2062 cmd_ret = CMD_ERROR;
2063 goto end;
2064 }
2065
2066 status = lttng_rotation_schedules_get_count(schedules, &count);
2067 if (status != LTTNG_ROTATION_STATUS_OK) {
2068 ERR("Failed to retrieve the number of session rotation schedules.");
2069 cmd_ret = CMD_ERROR;
2070 goto end;
2071 }
2072
2073 if (count == 0) {
2074 cmd_ret = CMD_SUCCESS;
2075 goto end;
2076 }
2077
2078 MSG("Automatic rotation schedules:");
2079 if (lttng_opt_mi) {
2080 ret = mi_lttng_writer_open_element(writer,
2081 mi_lttng_element_rotation_schedules);
2082 if (ret) {
2083 cmd_ret = CMD_ERROR;
2084 goto end;
2085 }
2086 }
2087
2088 for (i = 0; i < count; i++) {
2089 enum cmd_error_code tmp_ret = CMD_SUCCESS;
2090 const struct lttng_rotation_schedule *schedule;
2091
2092 schedule = lttng_rotation_schedules_get_at_index(schedules, i);
2093 if (!schedule) {
2094 ERR("Failed to retrieve session rotation schedule.");
2095 cmd_ret = CMD_ERROR;
2096 goto end;
2097 }
2098
2099 if (lttng_opt_mi) {
2100 ret = mi_lttng_rotation_schedule(writer, schedule);
2101 if (ret) {
2102 tmp_ret = CMD_ERROR;
2103 }
2104 } else {
2105 tmp_ret = print_rotation_schedule(schedule);
2106 }
2107
2108 /*
2109 * Report an error if the serialization of any of the
2110 * descriptors failed.
2111 */
2112 cmd_ret = cmd_ret ? cmd_ret : tmp_ret;
2113 }
2114
2115 _MSG("\n");
2116 if (lttng_opt_mi) {
2117 /* Close the rotation_schedules element. */
2118 ret = mi_lttng_writer_close_element(writer);
2119 if (ret) {
2120 cmd_ret = CMD_ERROR;
2121 goto end;
2122 }
2123 }
2124 end:
2125 lttng_rotation_schedules_destroy(schedules);
2126 return cmd_ret;
2127 }
2128
2129 /*
2130 * Machine interface
2131 * Find the session with session_name as name
2132 * and print his informations.
2133 */
2134 static int mi_list_session(const char *session_name,
2135 struct lttng_session *sessions, int count)
2136 {
2137 int ret, i;
2138 unsigned int session_found = 0;
2139
2140 if (session_name == NULL) {
2141 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2142 goto end;
2143 }
2144
2145 for (i = 0; i < count; i++) {
2146 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2147 /* We need to leave it open to append other informations
2148 * like domain, channel, events etc.*/
2149 session_found = 1;
2150 ret = mi_lttng_session(writer, &sessions[i], 1);
2151 if (ret) {
2152 goto end;
2153 }
2154 break;
2155 }
2156 }
2157
2158 if (!session_found) {
2159 ERR("Session '%s' not found", session_name);
2160 ret = -LTTNG_ERR_SESS_NOT_FOUND;
2161 goto end;
2162 }
2163
2164 end:
2165 return ret;
2166 }
2167
2168 /*
2169 * Machine interface
2170 * List all availables session
2171 */
2172 static int mi_list_sessions(struct lttng_session *sessions, int count)
2173 {
2174 int ret, i;
2175
2176 /* Opening sessions element */
2177 ret = mi_lttng_sessions_open(writer);
2178 if (ret) {
2179 goto end;
2180 }
2181
2182 /* Listing sessions */
2183 for (i = 0; i < count; i++) {
2184 ret = mi_lttng_session(writer, &sessions[i], 0);
2185 if (ret) {
2186 goto end;
2187 }
2188 }
2189
2190 /* Closing sessions element */
2191 ret = mi_lttng_writer_close_element(writer);
2192 if (ret) {
2193 goto end;
2194 }
2195
2196 end:
2197 return ret;
2198 }
2199
2200 /*
2201 * List available tracing session. List only basic information.
2202 *
2203 * If session_name is NULL, all sessions are listed.
2204 */
2205 static int list_sessions(const char *session_name)
2206 {
2207 int ret = CMD_SUCCESS;
2208 int count, i;
2209 unsigned int session_found = 0;
2210 struct lttng_session *sessions = NULL;
2211
2212 count = lttng_list_sessions(&sessions);
2213 DBG("Session count %d", count);
2214 if (count < 0) {
2215 ret = CMD_ERROR;
2216 ERR("%s", lttng_strerror(count));
2217 goto end;
2218 }
2219
2220 if (lttng_opt_mi) {
2221 /* Mi */
2222 if (session_name == NULL) {
2223 /* List all sessions */
2224 ret = mi_list_sessions(sessions, count);
2225 } else {
2226 /* Note : this return an open session element */
2227 ret = mi_list_session(session_name, sessions, count);
2228 }
2229 if (ret) {
2230 ret = CMD_ERROR;
2231 goto end;
2232 }
2233 } else {
2234 /* Pretty print */
2235 if (count == 0) {
2236 MSG("Currently no available tracing session");
2237 goto end;
2238 }
2239
2240 if (session_name == NULL) {
2241 MSG("Available tracing sessions:");
2242 }
2243
2244 for (i = 0; i < count; i++) {
2245 if (session_name != NULL) {
2246 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
2247 session_found = 1;
2248 MSG("Tracing session %s: [%s%s]", session_name,
2249 active_string(sessions[i].enabled),
2250 snapshot_string(sessions[i].snapshot_mode));
2251 if (*sessions[i].path) {
2252 MSG("%sTrace output: %s\n", indent4, sessions[i].path);
2253 }
2254 memcpy(&listed_session, &sessions[i],
2255 sizeof(listed_session));
2256 break;
2257 }
2258 } else {
2259 MSG(" %d) %s [%s%s]", i + 1,
2260 sessions[i].name,
2261 active_string(sessions[i].enabled),
2262 snapshot_string(sessions[i].snapshot_mode));
2263 if (*sessions[i].path) {
2264 MSG("%sTrace output: %s", indent4, sessions[i].path);
2265 }
2266 if (sessions[i].live_timer_interval != 0) {
2267 MSG("%sLive timer interval: %u %s", indent4,
2268 sessions[i].live_timer_interval,
2269 USEC_UNIT);
2270 }
2271 MSG("");
2272 }
2273 }
2274
2275 if (!session_found && session_name != NULL) {
2276 ERR("Session '%s' not found", session_name);
2277 ret = CMD_ERROR;
2278 goto end;
2279 }
2280
2281 if (session_name == NULL) {
2282 MSG("\nUse lttng list <session_name> for more details");
2283 }
2284 }
2285
2286 end:
2287 free(sessions);
2288 return ret;
2289 }
2290
2291
2292 /*
2293 * Machine Interface
2294 * list available domain(s) for a session.
2295 */
2296 static int mi_list_domains(struct lttng_domain *domains, int count)
2297 {
2298 int i, ret;
2299 /* Open domains element */
2300 ret = mi_lttng_domains_open(writer);
2301 if (ret) {
2302 goto end;
2303 }
2304
2305 for (i = 0; i < count; i++) {
2306 ret = mi_lttng_domain(writer, &domains[i] , 0);
2307 if (ret) {
2308 goto end;
2309 }
2310 }
2311
2312 /* Closing domains element */
2313 ret = mi_lttng_writer_close_element(writer);
2314 if (ret) {
2315 goto end;
2316 }
2317 end:
2318 return ret;
2319 }
2320
2321 /*
2322 * List available domain(s) for a session.
2323 */
2324 static int list_domains(const char *session_name)
2325 {
2326 int i, count, ret = CMD_SUCCESS;
2327 struct lttng_domain *domains = NULL;
2328
2329
2330 count = lttng_list_domains(session_name, &domains);
2331 if (count < 0) {
2332 ret = CMD_ERROR;
2333 ERR("%s", lttng_strerror(count));
2334 goto end;
2335 }
2336
2337 if (lttng_opt_mi) {
2338 /* Mi output */
2339 ret = mi_list_domains(domains, count);
2340 if (ret) {
2341 ret = CMD_ERROR;
2342 goto error;
2343 }
2344 } else {
2345 /* Pretty print */
2346 MSG("Domains:\n-------------");
2347 if (count == 0) {
2348 MSG(" None");
2349 goto end;
2350 }
2351
2352 for (i = 0; i < count; i++) {
2353 switch (domains[i].type) {
2354 case LTTNG_DOMAIN_KERNEL:
2355 MSG(" - Kernel");
2356 break;
2357 case LTTNG_DOMAIN_UST:
2358 MSG(" - UST global");
2359 break;
2360 case LTTNG_DOMAIN_JUL:
2361 MSG(" - JUL (Java Util Logging)");
2362 break;
2363 case LTTNG_DOMAIN_LOG4J:
2364 MSG(" - LOG4j (Logging for Java)");
2365 break;
2366 case LTTNG_DOMAIN_PYTHON:
2367 MSG(" - Python (logging)");
2368 break;
2369 default:
2370 break;
2371 }
2372 }
2373 }
2374
2375 error:
2376 free(domains);
2377
2378 end:
2379 return ret;
2380 }
2381
2382 /*
2383 * The 'list <options>' first level command
2384 */
2385 int cmd_list(int argc, const char **argv)
2386 {
2387 int opt, ret = CMD_SUCCESS;
2388 const char *session_name, *leftover = NULL;
2389 static poptContext pc;
2390 struct lttng_domain domain;
2391 struct lttng_domain *domains = NULL;
2392
2393 memset(&domain, 0, sizeof(domain));
2394
2395 if (argc < 1) {
2396 ret = CMD_ERROR;
2397 goto end;
2398 }
2399
2400 pc = poptGetContext(NULL, argc, argv, long_options, 0);
2401 poptReadDefaultConfig(pc, 0);
2402
2403 while ((opt = poptGetNextOpt(pc)) != -1) {
2404 switch (opt) {
2405 case OPT_HELP:
2406 SHOW_HELP();
2407 goto end;
2408 case OPT_USERSPACE:
2409 opt_userspace = 1;
2410 break;
2411 case OPT_LIST_OPTIONS:
2412 list_cmd_options(stdout, long_options);
2413 goto end;
2414 default:
2415 ret = CMD_UNDEFINED;
2416 goto end;
2417 }
2418 }
2419
2420 /* Mi check */
2421 if (lttng_opt_mi) {
2422 writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
2423 if (!writer) {
2424 ret = CMD_ERROR;
2425 goto end;
2426 }
2427
2428 /* Open command element */
2429 ret = mi_lttng_writer_command_open(writer,
2430 mi_lttng_element_command_list);
2431 if (ret) {
2432 ret = CMD_ERROR;
2433 goto end;
2434 }
2435
2436 /* Open output element */
2437 ret = mi_lttng_writer_open_element(writer,
2438 mi_lttng_element_command_output);
2439 if (ret) {
2440 ret = CMD_ERROR;
2441 goto end;
2442 }
2443 }
2444
2445 /* Get session name (trailing argument) */
2446 session_name = poptGetArg(pc);
2447 DBG2("Session name: %s", session_name);
2448
2449 leftover = poptGetArg(pc);
2450 if (leftover) {
2451 ERR("Unknown argument: %s", leftover);
2452 ret = CMD_ERROR;
2453 goto end;
2454 }
2455
2456 if (opt_kernel) {
2457 domain.type = LTTNG_DOMAIN_KERNEL;
2458 } else if (opt_userspace) {
2459 DBG2("Listing userspace global domain");
2460 domain.type = LTTNG_DOMAIN_UST;
2461 } else if (opt_jul) {
2462 DBG2("Listing JUL domain");
2463 domain.type = LTTNG_DOMAIN_JUL;
2464 } else if (opt_log4j) {
2465 domain.type = LTTNG_DOMAIN_LOG4J;
2466 } else if (opt_python) {
2467 domain.type = LTTNG_DOMAIN_PYTHON;
2468 }
2469
2470 if (!opt_kernel && opt_syscall) {
2471 WARN("--syscall will only work with the Kernel domain (-k)");
2472 ret = CMD_ERROR;
2473 goto end;
2474 }
2475
2476 if (opt_kernel || opt_userspace || opt_jul || opt_log4j || opt_python) {
2477 handle = lttng_create_handle(session_name, &domain);
2478 if (handle == NULL) {
2479 ret = CMD_FATAL;
2480 goto end;
2481 }
2482 }
2483
2484 if (session_name == NULL) {
2485 if (!opt_kernel && !opt_userspace && !opt_jul && !opt_log4j
2486 && !opt_python) {
2487 ret = list_sessions(NULL);
2488 if (ret) {
2489 goto end;
2490 }
2491 }
2492 if (opt_kernel) {
2493 if (opt_syscall) {
2494 ret = list_syscalls();
2495 if (ret) {
2496 goto end;
2497 }
2498 } else {
2499 ret = list_kernel_events();
2500 if (ret) {
2501 goto end;
2502 }
2503 }
2504 }
2505 if (opt_userspace) {
2506 if (opt_fields) {
2507 ret = list_ust_event_fields();
2508 } else {
2509 ret = list_ust_events();
2510 }
2511 if (ret) {
2512 goto end;
2513 }
2514 }
2515 if (opt_jul || opt_log4j || opt_python) {
2516 ret = list_agent_events();
2517 if (ret) {
2518 goto end;
2519 }
2520 }
2521 } else {
2522 /* List session attributes */
2523 if (lttng_opt_mi) {
2524 /* Open element sessions
2525 * Present for xml consistency */
2526 ret = mi_lttng_sessions_open(writer);
2527 if (ret) {
2528 goto end;
2529 }
2530 }
2531 /* MI: the ouptut of list_sessions is an unclosed session element */
2532 ret = list_sessions(session_name);
2533 if (ret) {
2534 goto end;
2535 }
2536
2537 ret = list_rotate_settings(session_name);
2538 if (ret) {
2539 goto end;
2540 }
2541
2542 /* Domain listing */
2543 if (opt_domain) {
2544 ret = list_domains(session_name);
2545 goto end;
2546 }
2547
2548 /* Channel listing */
2549 if (opt_kernel || opt_userspace) {
2550 if (lttng_opt_mi) {
2551 /* Add of domains and domain element for xml
2552 * consistency and validation
2553 */
2554 ret = mi_lttng_domains_open(writer);
2555 if (ret) {
2556 goto end;
2557 }
2558
2559 /* Open domain and leave it open for
2560 * nested channels printing */
2561 ret = mi_lttng_domain(writer, &domain, 1);
2562 if (ret) {
2563 goto end;
2564 }
2565
2566 }
2567
2568
2569 /* Trackers */
2570 ret = list_trackers(&domain);
2571 if (ret) {
2572 goto end;
2573 }
2574
2575 /* Channels */
2576 ret = list_channels(opt_channel);
2577 if (ret) {
2578 goto end;
2579 }
2580
2581 ret = list_maps(opt_map);
2582 if (ret) {
2583 goto end;
2584 }
2585
2586 if (lttng_opt_mi) {
2587 /* Close domain and domain element */
2588 ret = mi_lttng_close_multi_element(writer, 2);
2589 }
2590 if (ret) {
2591 goto end;
2592 }
2593
2594
2595 } else {
2596 int i, nb_domain;
2597
2598 /* We want all domain(s) */
2599 nb_domain = lttng_list_domains(session_name, &domains);
2600 if (nb_domain < 0) {
2601 ret = CMD_ERROR;
2602 ERR("%s", lttng_strerror(nb_domain));
2603 goto end;
2604 }
2605
2606 if (lttng_opt_mi) {
2607 ret = mi_lttng_domains_open(writer);
2608 if (ret) {
2609 ret = CMD_ERROR;
2610 goto end;
2611 }
2612 }
2613
2614 for (i = 0; i < nb_domain; i++) {
2615 switch (domains[i].type) {
2616 case LTTNG_DOMAIN_KERNEL:
2617 MSG("=== Domain: Linux kernel ===\n");
2618 break;
2619 case LTTNG_DOMAIN_UST:
2620 MSG("=== Domain: User space ===\n");
2621 MSG("Buffering scheme: %s\n",
2622 domains[i].buf_type ==
2623 LTTNG_BUFFER_PER_PID ? "per-process" : "per-user");
2624 break;
2625 case LTTNG_DOMAIN_JUL:
2626 MSG("=== Domain: java.util.logging (JUL) ===\n");
2627 break;
2628 case LTTNG_DOMAIN_LOG4J:
2629 MSG("=== Domain: log4j ===\n");
2630 break;
2631 case LTTNG_DOMAIN_PYTHON:
2632 MSG("=== Domain: Python logging ===\n");
2633 break;
2634 default:
2635 MSG("=== Domain: Unimplemented ===\n");
2636 break;
2637 }
2638
2639 if (lttng_opt_mi) {
2640 ret = mi_lttng_domain(writer, &domains[i], 1);
2641 if (ret) {
2642 ret = CMD_ERROR;
2643 goto end;
2644 }
2645 }
2646
2647 /* Clean handle before creating a new one */
2648 if (handle) {
2649 lttng_destroy_handle(handle);
2650 }
2651
2652 handle = lttng_create_handle(session_name, &domains[i]);
2653 if (handle == NULL) {
2654 ret = CMD_FATAL;
2655 goto end;
2656 }
2657
2658 if (domains[i].type == LTTNG_DOMAIN_JUL ||
2659 domains[i].type == LTTNG_DOMAIN_LOG4J ||
2660 domains[i].type == LTTNG_DOMAIN_PYTHON) {
2661 ret = list_session_agent_events();
2662 if (ret) {
2663 goto end;
2664 }
2665
2666 goto next_domain;
2667 }
2668
2669 switch (domains[i].type) {
2670 case LTTNG_DOMAIN_KERNEL:
2671 case LTTNG_DOMAIN_UST:
2672 ret = list_trackers(&domains[i]);
2673 if (ret) {
2674 goto end;
2675 }
2676 break;
2677 default:
2678 break;
2679 }
2680
2681 ret = list_channels(opt_channel);
2682 if (ret) {
2683 goto end;
2684 }
2685
2686 ret = list_maps(opt_map);
2687 if (ret) {
2688 goto end;
2689 }
2690
2691 next_domain:
2692 if (lttng_opt_mi) {
2693 /* Close domain element */
2694 ret = mi_lttng_writer_close_element(writer);
2695 if (ret) {
2696 ret = CMD_ERROR;
2697 goto end;
2698 }
2699 }
2700
2701 }
2702 if (lttng_opt_mi) {
2703 /* Close the domains, session and sessions element */
2704 ret = mi_lttng_close_multi_element(writer, 3);
2705 if (ret) {
2706 ret = CMD_ERROR;
2707 goto end;
2708 }
2709 }
2710 }
2711 }
2712
2713 /* Mi closing */
2714 if (lttng_opt_mi) {
2715 /* Close output element */
2716 ret = mi_lttng_writer_close_element(writer);
2717 if (ret) {
2718 ret = CMD_ERROR;
2719 goto end;
2720 }
2721
2722 /* Command element close */
2723 ret = mi_lttng_writer_command_close(writer);
2724 if (ret) {
2725 ret = CMD_ERROR;
2726 goto end;
2727 }
2728 }
2729 end:
2730 /* Mi clean-up */
2731 if (writer && mi_lttng_writer_destroy(writer)) {
2732 /* Preserve original error code */
2733 ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
2734 }
2735
2736 free(domains);
2737 if (handle) {
2738 lttng_destroy_handle(handle);
2739 }
2740
2741 poptFreeContext(pc);
2742 return ret;
2743 }
This page took 0.15229 seconds and 5 git commands to generate.