1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 */
7 #include <dirent.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <getopt.h>
13 #include <time.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <sys/wait.h>
18 #include <sys/socket.h>
19 #include <sys/syscall.h>
20 #include <sys/utsname.h>
21 #ifndef NO_PTRACE
22 #include <sys/ptrace.h>
23 #else
24 #ifdef WARN_NO_PTRACE
25 #warning ptrace not supported. -c feature will not work
26 #endif
27 #endif
28 #include <netdb.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <sched.h>
33 #include <glob.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <libgen.h>
37 #include <poll.h>
38 #include <pwd.h>
39 #include <grp.h>
40
41 #include "tracefs.h"
42 #include "version.h"
43 #include "trace-local.h"
44 #include "trace-msg.h"
45
46 #define _STR(x) #x
47 #define STR(x) _STR(x)
48
49 #define RECORD_PIDFILE "trace-cmd-record.pid"
50
51 #define TRACE_CTRL "tracing_on"
52 #define TRACE "trace"
53 #define AVAILABLE "available_tracers"
54 #define CURRENT "current_tracer"
55 #define ITER_CTRL "trace_options"
56 #define MAX_LATENCY "tracing_max_latency"
57 #define STAMP "stamp"
58 #define FUNC_STACK_TRACE "func_stack_trace"
59 #define TSC_CLOCK "x86-tsc"
60
61 #define dprint(fmt, ...) tracecmd_debug(fmt, ##__VA_ARGS__)
62
63 enum trace_type {
64 TRACE_TYPE_RECORD = 1,
65 TRACE_TYPE_START = (1 << 1),
66 TRACE_TYPE_STREAM = (1 << 2),
67 TRACE_TYPE_EXTRACT = (1 << 3),
68 TRACE_TYPE_SET = (1 << 4),
69 };
70
71 static tracecmd_handle_init_func handle_init = NULL;
72
73 static int rt_prio;
74
75 static int keep;
76
77 static int latency;
78 static long sleep_time = 1000;
79 static int recorder_threads;
80 static struct pid_record_data *pids;
81 static int buffers;
82
83 /* Clear all function filters */
84 static int clear_function_filters;
85
86 static bool no_fifos;
87
88 static char *host;
89
90 static const char *gai_err;
91
92 static bool quiet;
93
94 static bool fork_process;
95
96 static bool do_daemonize;
97
98 static bool created_pidfile;
99
100 /* Max size to let a per cpu file get */
101 static int max_kb;
102
103 static int do_ptrace;
104
105 static int filter_task;
106 static bool no_filter = false;
107
108 static int local_cpu_count;
109
110 static int finished;
111
112 /* setting of /proc/sys/kernel/ftrace_enabled */
113 static int fset;
114
115 static unsigned recorder_flags;
116
117 /* Try a few times to get an accurate date */
118 static int date2ts_tries = 50;
119
120 static struct func_list *graph_funcs;
121
122 static int func_stack;
123
124 static int save_stdout = -1;
125
126 static struct hook_list *hooks;
127
128 struct event_list {
129 struct event_list *next;
130 const char *event;
131 char *trigger;
132 char *filter;
133 char *pid_filter;
134 char *filter_file;
135 char *trigger_file;
136 char *enable_file;
137 int neg;
138 };
139
140 struct tracecmd_event_list *listed_events;
141
142 struct events {
143 struct events *sibling;
144 struct events *children;
145 struct events *next;
146 char *name;
147 };
148
149 /* Files to be reset when done recording */
150 struct reset_file {
151 struct reset_file *next;
152 char *path;
153 char *reset;
154 int prio;
155 };
156
157 static struct reset_file *reset_files;
158
159 /* Triggers need to be cleared in a special way */
160 static struct reset_file *reset_triggers;
161
162 struct buffer_instance top_instance;
163 struct buffer_instance *buffer_instances;
164 struct buffer_instance *first_instance;
165
166 static struct tracecmd_recorder *recorder;
167
168 static int ignore_event_not_found = 0;
169
is_top_instance(struct buffer_instance * instance)170 static inline int is_top_instance(struct buffer_instance *instance)
171 {
172 return instance == &top_instance;
173 }
174
no_top_instance(void)175 static inline int no_top_instance(void)
176 {
177 return first_instance != &top_instance;
178 }
179
init_instance(struct buffer_instance * instance)180 static void init_instance(struct buffer_instance *instance)
181 {
182 instance->event_next = &instance->events;
183 }
184
185 enum {
186 RESET_DEFAULT_PRIO = 0,
187 RESET_HIGH_PRIO = 100000,
188 };
189
190 enum trace_cmd {
191 CMD_extract,
192 CMD_start,
193 CMD_stream,
194 CMD_profile,
195 CMD_record,
196 CMD_record_agent,
197 CMD_set,
198 };
199
200 struct common_record_context {
201 enum trace_cmd curr_cmd;
202 struct buffer_instance *instance;
203 const char *output;
204 const char *temp;
205 char *date2ts;
206 char *user;
207 const char *clock;
208 const char *compression;
209 struct tsc_nsec tsc2nsec;
210 int data_flags;
211 int tsync_loop_interval;
212
213 int record_all;
214 int total_disable;
215 int disable;
216 int events;
217 int global;
218 int filtered;
219 int date;
220 int manual;
221 int topt;
222 int run_command;
223 int saved_cmdlines_size;
224 int file_version;
225 };
226
add_reset_file(const char * file,const char * val,int prio)227 static void add_reset_file(const char *file, const char *val, int prio)
228 {
229 struct reset_file *reset;
230 struct reset_file **last = &reset_files;
231
232 /* Only reset if we are not keeping the state */
233 if (keep)
234 return;
235
236 reset = malloc(sizeof(*reset));
237 if (!reset)
238 die("Failed to allocate reset");
239 reset->path = strdup(file);
240 reset->reset = strdup(val);
241 reset->prio = prio;
242 if (!reset->path || !reset->reset)
243 die("Failed to allocate reset path or val");
244
245 while (*last && (*last)->prio > prio)
246 last = &(*last)->next;
247
248 reset->next = *last;
249 *last = reset;
250 }
251
add_reset_trigger(const char * file)252 static void add_reset_trigger(const char *file)
253 {
254 struct reset_file *reset;
255
256 /* Only reset if we are not keeping the state */
257 if (keep)
258 return;
259
260 reset = malloc(sizeof(*reset));
261 if (!reset)
262 die("Failed to allocate reset");
263 reset->path = strdup(file);
264
265 reset->next = reset_triggers;
266 reset_triggers = reset;
267 }
268
269 /* To save the contents of the file */
reset_save_file(const char * file,int prio)270 static void reset_save_file(const char *file, int prio)
271 {
272 char *content;
273
274 content = get_file_content(file);
275 if (content) {
276 add_reset_file(file, content, prio);
277 free(content);
278 }
279 }
280
281 /*
282 * @file: the file to check
283 * @nop: If the content of the file is this, use the reset value
284 * @reset: What to write if the file == @nop
285 */
reset_save_file_cond(const char * file,int prio,const char * nop,const char * reset)286 static void reset_save_file_cond(const char *file, int prio,
287 const char *nop, const char *reset)
288 {
289 char *content;
290 char *cond;
291
292 if (keep)
293 return;
294
295 content = get_file_content(file);
296
297 cond = strstrip(content);
298
299 if (strcmp(cond, nop) == 0)
300 add_reset_file(file, reset, prio);
301 else
302 add_reset_file(file, content, prio);
303
304 free(content);
305 }
306
307 /**
308 * add_instance - add a buffer instance to the internal list
309 * @instance: The buffer instance to add
310 */
add_instance(struct buffer_instance * instance,int cpu_count)311 void add_instance(struct buffer_instance *instance, int cpu_count)
312 {
313 init_instance(instance);
314 instance->next = buffer_instances;
315 if (first_instance == buffer_instances)
316 first_instance = instance;
317 buffer_instances = instance;
318 instance->cpu_count = cpu_count;
319 buffers++;
320 }
321
instance_reset_file_save(struct buffer_instance * instance,char * file,int prio)322 static void instance_reset_file_save(struct buffer_instance *instance, char *file, int prio)
323 {
324 char *path;
325
326 path = tracefs_instance_get_file(instance->tracefs, file);
327 if (path)
328 reset_save_file(path, prio);
329 tracefs_put_tracing_file(path);
330 }
331
test_set_event_pid(struct buffer_instance * instance)332 static void test_set_event_pid(struct buffer_instance *instance)
333 {
334 static int have_set_event_pid;
335 static int have_event_fork;
336 static int have_func_fork;
337
338 if (!have_set_event_pid &&
339 tracefs_file_exists(top_instance.tracefs, "set_event_pid"))
340 have_set_event_pid = 1;
341 if (!have_event_fork &&
342 tracefs_file_exists(top_instance.tracefs, "options/event-fork"))
343 have_event_fork = 1;
344 if (!have_func_fork &&
345 tracefs_file_exists(top_instance.tracefs, "options/function-fork"))
346 have_func_fork = 1;
347
348 if (!instance->have_set_event_pid && have_set_event_pid) {
349 instance->have_set_event_pid = 1;
350 instance_reset_file_save(instance, "set_event_pid",
351 RESET_DEFAULT_PRIO);
352 }
353 if (!instance->have_event_fork && have_event_fork) {
354 instance->have_event_fork = 1;
355 instance_reset_file_save(instance, "options/event-fork",
356 RESET_DEFAULT_PRIO);
357 }
358 if (!instance->have_func_fork && have_func_fork) {
359 instance->have_func_fork = 1;
360 instance_reset_file_save(instance, "options/function-fork",
361 RESET_DEFAULT_PRIO);
362 }
363 }
364
365 /**
366 * allocate_instance - allocate a new buffer instance,
367 * it must exist in the ftrace system
368 * @name: The name of the instance (instance will point to this)
369 *
370 * Returns a newly allocated instance. In case of an error or if the
371 * instance does not exist in the ftrace system, NULL is returned.
372 */
allocate_instance(const char * name)373 struct buffer_instance *allocate_instance(const char *name)
374 {
375 struct buffer_instance *instance;
376
377 instance = calloc(1, sizeof(*instance));
378 if (!instance)
379 return NULL;
380 if (name)
381 instance->name = strdup(name);
382 if (tracefs_instance_exists(name)) {
383 instance->tracefs = tracefs_instance_create(name);
384 if (!instance->tracefs)
385 goto error;
386 }
387
388 return instance;
389
390 error:
391 free(instance->name);
392 tracefs_instance_free(instance->tracefs);
393 free(instance);
394 return NULL;
395 }
396
__add_all_instances(const char * tracing_dir)397 static int __add_all_instances(const char *tracing_dir)
398 {
399 struct dirent *dent;
400 char *instances_dir;
401 struct stat st;
402 DIR *dir;
403 int ret;
404
405 if (!tracing_dir)
406 return -1;
407
408 instances_dir = append_file(tracing_dir, "instances");
409 if (!instances_dir)
410 return -1;
411
412 ret = stat(instances_dir, &st);
413 if (ret < 0 || !S_ISDIR(st.st_mode)) {
414 ret = -1;
415 goto out_free;
416 }
417
418 dir = opendir(instances_dir);
419 if (!dir) {
420 ret = -1;
421 goto out_free;
422 }
423
424 while ((dent = readdir(dir))) {
425 const char *name = dent->d_name;
426 char *instance_path;
427 struct buffer_instance *instance;
428
429 if (strcmp(name, ".") == 0 ||
430 strcmp(name, "..") == 0)
431 continue;
432
433 instance_path = append_file(instances_dir, name);
434 ret = stat(instance_path, &st);
435 if (ret < 0 || !S_ISDIR(st.st_mode)) {
436 free(instance_path);
437 continue;
438 }
439 free(instance_path);
440
441 instance = allocate_instance(name);
442 if (!instance)
443 die("Failed to create instance");
444 add_instance(instance, local_cpu_count);
445 }
446
447 closedir(dir);
448 ret = 0;
449
450 out_free:
451 free(instances_dir);
452 return ret;
453 }
454
455 /**
456 * add_all_instances - Add all pre-existing instances to the internal list
457 * @tracing_dir: The top-level tracing directory
458 *
459 * Returns whether the operation succeeded
460 */
add_all_instances(void)461 void add_all_instances(void)
462 {
463 const char *tracing_dir = tracefs_tracing_dir();
464 if (!tracing_dir)
465 die("can't get the tracing directory");
466
467 __add_all_instances(tracing_dir);
468 }
469
470 /**
471 * tracecmd_stat_cpu - show the buffer stats of a particular CPU
472 * @s: the trace_seq to record the data in.
473 * @cpu: the CPU to stat
474 *
475 */
tracecmd_stat_cpu_instance(struct buffer_instance * instance,struct trace_seq * s,int cpu)476 void tracecmd_stat_cpu_instance(struct buffer_instance *instance,
477 struct trace_seq *s, int cpu)
478 {
479 char buf[BUFSIZ];
480 char *path;
481 char *file;
482 int fd;
483 int r;
484
485 file = malloc(40);
486 if (!file)
487 return;
488 snprintf(file, 40, "per_cpu/cpu%d/stats", cpu);
489
490 path = tracefs_instance_get_file(instance->tracefs, file);
491 free(file);
492 fd = open(path, O_RDONLY);
493 tracefs_put_tracing_file(path);
494 if (fd < 0)
495 return;
496
497 while ((r = read(fd, buf, BUFSIZ)) > 0)
498 trace_seq_printf(s, "%.*s", r, buf);
499
500 close(fd);
501 }
502
503 /**
504 * tracecmd_stat_cpu - show the buffer stats of a particular CPU
505 * @s: the trace_seq to record the data in.
506 * @cpu: the CPU to stat
507 *
508 */
tracecmd_stat_cpu(struct trace_seq * s,int cpu)509 void tracecmd_stat_cpu(struct trace_seq *s, int cpu)
510 {
511 tracecmd_stat_cpu_instance(&top_instance, s, cpu);
512 }
513
add_event(struct buffer_instance * instance,struct event_list * event)514 static void add_event(struct buffer_instance *instance, struct event_list *event)
515 {
516 *instance->event_next = event;
517 instance->event_next = &event->next;
518 event->next = NULL;
519 }
520
reset_event_list(struct buffer_instance * instance)521 static void reset_event_list(struct buffer_instance *instance)
522 {
523 instance->events = NULL;
524 init_instance(instance);
525 }
526
get_temp_file(struct buffer_instance * instance,int cpu)527 static char *get_temp_file(struct buffer_instance *instance, int cpu)
528 {
529 const char *output_file = instance->output_file;
530 const char *name;
531 char *file = NULL;
532 int size;
533
534 if (instance->temp_dir) {
535 if (!instance->temp_file) {
536 const char *f = output_file + strlen(output_file) - 1;;
537 int ret;
538
539 for (; f > output_file && *f != '/'; f--)
540 ;
541 if (*f == '/')
542 f++;
543 ret = asprintf(&instance->temp_file, "%s/%s",
544 instance->temp_dir, f);
545 if (ret < 0)
546 die("Failed to create temp file");
547 }
548 output_file = instance->temp_file;
549 }
550
551 name = tracefs_instance_get_name(instance->tracefs);
552 if (name) {
553 size = snprintf(file, 0, "%s.%s.cpu%d", output_file, name, cpu);
554 file = malloc(size + 1);
555 if (!file)
556 die("Failed to allocate temp file for %s", name);
557 sprintf(file, "%s.%s.cpu%d", output_file, name, cpu);
558 } else {
559 size = snprintf(file, 0, "%s.cpu%d", output_file, cpu);
560 file = malloc(size + 1);
561 if (!file)
562 die("Failed to allocate temp file");
563 sprintf(file, "%s.cpu%d", output_file, cpu);
564 }
565
566 return file;
567 }
568
trace_get_guest_file(const char * file,const char * guest)569 char *trace_get_guest_file(const char *file, const char *guest)
570 {
571 const char *p;
572 char *out = NULL;
573 int ret, base_len;
574
575 p = strrchr(file, '.');
576 if (p && p != file)
577 base_len = p - file;
578 else
579 base_len = strlen(file);
580
581 ret = asprintf(&out, "%.*s-%s%s", base_len, file,
582 guest, file + base_len);
583 if (ret < 0)
584 return NULL;
585 return out;
586 }
587
put_temp_file(char * file)588 static void put_temp_file(char *file)
589 {
590 free(file);
591 }
592
delete_temp_file(struct buffer_instance * instance,int cpu)593 static void delete_temp_file(struct buffer_instance *instance, int cpu)
594 {
595 const char *output_file;
596 const char *name;
597 char file[PATH_MAX];
598
599 if (instance->temp_file)
600 output_file = instance->temp_file;
601 else
602 output_file = instance->output_file;
603
604 name = tracefs_instance_get_name(instance->tracefs);
605 if (name)
606 snprintf(file, PATH_MAX, "%s.%s.cpu%d", output_file, name, cpu);
607 else
608 snprintf(file, PATH_MAX, "%s.cpu%d", output_file, cpu);
609 unlink(file);
610 }
611
kill_thread_instance(int start,struct buffer_instance * instance)612 static int kill_thread_instance(int start, struct buffer_instance *instance)
613 {
614 int n = start;
615 int i;
616
617 for (i = 0; i < instance->cpu_count; i++) {
618 if (pids[n].pid > 0) {
619 kill(pids[n].pid, SIGKILL);
620 delete_temp_file(instance, i);
621 pids[n].pid = 0;
622 if (pids[n].brass[0] >= 0)
623 close(pids[n].brass[0]);
624 }
625 n++;
626 }
627
628 return n;
629 }
630
kill_threads(void)631 static void kill_threads(void)
632 {
633 struct buffer_instance *instance;
634 int i = 0;
635
636 if (!recorder_threads || !pids)
637 return;
638
639 for_all_instances(instance)
640 i = kill_thread_instance(i, instance);
641 }
642
die(const char * fmt,...)643 void die(const char *fmt, ...)
644 {
645 va_list ap;
646 int ret = errno;
647
648 if (errno)
649 perror("trace-cmd");
650 else
651 ret = -1;
652
653 if (created_pidfile)
654 remove_pid_file(RECORD_PIDFILE);
655
656 kill_threads();
657 va_start(ap, fmt);
658 fprintf(stderr, " ");
659 vfprintf(stderr, fmt, ap);
660 va_end(ap);
661
662 fprintf(stderr, "\n");
663 exit(ret);
664 }
665
delete_thread_instance(int start,struct buffer_instance * instance)666 static int delete_thread_instance(int start, struct buffer_instance *instance)
667 {
668 int n = start;
669 int i;
670
671 for (i = 0; i < instance->cpu_count; i++) {
672 if (pids) {
673 if (pids[n].pid) {
674 delete_temp_file(instance, i);
675 if (pids[n].pid < 0)
676 pids[n].pid = 0;
677 }
678 n++;
679 } else
680 /* Extract does not allocate pids */
681 delete_temp_file(instance, i);
682 }
683 return n;
684 }
685
delete_thread_data(void)686 static void delete_thread_data(void)
687 {
688 struct buffer_instance *instance;
689 int i = 0;
690
691 for_all_instances(instance)
692 i = delete_thread_instance(i, instance);
693 /*
694 * Top instance temp files are still created even if it
695 * isn't used.
696 */
697 if (no_top_instance()) {
698 for (i = 0; i < local_cpu_count; i++)
699 delete_temp_file(&top_instance, i);
700 }
701 }
702
703 static void
add_tsc2nsec(struct tracecmd_output * handle,struct tsc_nsec * tsc2nsec)704 add_tsc2nsec(struct tracecmd_output *handle, struct tsc_nsec *tsc2nsec)
705 {
706 /* multiplier, shift, offset */
707 struct iovec vector[3];
708
709 vector[0].iov_len = 4;
710 vector[0].iov_base = &tsc2nsec->mult;
711 vector[1].iov_len = 4;
712 vector[1].iov_base = &tsc2nsec->shift;
713 vector[2].iov_len = 8;
714 vector[2].iov_base = &tsc2nsec->offset;
715
716 tracecmd_add_option_v(handle, TRACECMD_OPTION_TSC2NSEC, vector, 3);
717 }
718
guest_tsync_complete(struct buffer_instance * instance)719 static void guest_tsync_complete(struct buffer_instance *instance)
720 {
721 tracecmd_tsync_with_host_stop(instance->tsync);
722 tracecmd_tsync_free(instance->tsync);
723 }
724
host_tsync_complete(struct common_record_context * ctx,struct buffer_instance * instance)725 static void host_tsync_complete(struct common_record_context *ctx,
726 struct buffer_instance *instance)
727 {
728 struct tracecmd_output *handle = NULL;
729 int fd = -1;
730 int ret;
731
732 ret = tracecmd_tsync_with_guest_stop(instance->tsync);
733 if (!ret) {
734 fd = open(instance->output_file, O_RDWR);
735 if (fd < 0)
736 die("error opening %s", instance->output_file);
737 handle = tracecmd_get_output_handle_fd(fd);
738 if (!handle)
739 die("cannot create output handle");
740
741 if (ctx->tsc2nsec.mult)
742 add_tsc2nsec(handle, &ctx->tsc2nsec);
743
744 tracecmd_write_guest_time_shift(handle, instance->tsync);
745 tracecmd_append_options(handle);
746 tracecmd_output_close(handle);
747 }
748
749 tracecmd_tsync_free(instance->tsync);
750 instance->tsync = NULL;
751 }
752
tell_guests_to_stop(struct common_record_context * ctx)753 static void tell_guests_to_stop(struct common_record_context *ctx)
754 {
755 struct buffer_instance *instance;
756
757 /* Send close message to guests */
758 for_all_instances(instance) {
759 if (is_guest(instance)) {
760 tracecmd_msg_send_close_msg(instance->msg_handle);
761 if (is_proxy(instance) && instance->proxy_fd >= 0) {
762 /* The proxy will send more data now */
763 if (tracecmd_msg_read_data(instance->msg_handle, instance->proxy_fd))
764 warning("Failed receiving finishing metadata");
765 close(instance->proxy_fd);
766 }
767 }
768 }
769
770 for_all_instances(instance) {
771 if (is_guest(instance)) {
772 if (is_proxy(instance))
773 guest_tsync_complete(instance);
774 else
775 host_tsync_complete(ctx, instance);
776 }
777 }
778
779 /* Wait for guests to acknowledge */
780 for_all_instances(instance) {
781 if (is_guest(instance)) {
782 if (!is_proxy(instance)) {
783 tracecmd_msg_wait_close_resp(instance->msg_handle);
784 tracecmd_msg_handle_close(instance->msg_handle);
785 }
786 }
787 }
788 }
789
stop_threads(enum trace_type type)790 static void stop_threads(enum trace_type type)
791 {
792 int ret;
793 int i;
794
795 if (!recorder_threads)
796 return;
797
798 /* Tell all threads to finish up */
799 for (i = 0; i < recorder_threads; i++) {
800 if (pids[i].pid > 0) {
801 kill(pids[i].pid, SIGUSR1);
802 }
803 }
804
805 /* Flush out the pipes */
806 if (type & TRACE_TYPE_STREAM) {
807 do {
808 ret = trace_stream_read(pids, recorder_threads, 0);
809 } while (ret > 0);
810 }
811 }
812
wait_threads()813 static void wait_threads()
814 {
815 int i;
816
817 for (i = 0; i < recorder_threads; i++) {
818 if (pids[i].pid > 0) {
819 waitpid(pids[i].pid, NULL, 0);
820 pids[i].pid = -1;
821 }
822 }
823 }
824
825 static int create_recorder(struct buffer_instance *instance, int cpu,
826 enum trace_type type, int *brass);
827
flush_threads(void)828 static void flush_threads(void)
829 {
830 struct buffer_instance *instance;
831 long ret;
832 int i;
833
834 for_all_instances(instance) {
835 for (i = 0; i < instance->cpu_count; i++) {
836 /* Extract doesn't support sub buffers yet */
837 ret = create_recorder(instance, i, TRACE_TYPE_EXTRACT, NULL);
838 if (ret < 0)
839 die("error reading ring buffer");
840 }
841 }
842 }
843
set_ftrace_enable(const char * path,int set)844 static int set_ftrace_enable(const char *path, int set)
845 {
846 struct stat st;
847 int fd;
848 char *val = set ? "1" : "0";
849 int ret;
850
851 /* if ftace_enable does not exist, simply ignore it */
852 fd = stat(path, &st);
853 if (fd < 0)
854 return -ENODEV;
855
856 reset_save_file(path, RESET_DEFAULT_PRIO);
857
858 ret = -1;
859 fd = open(path, O_WRONLY);
860 if (fd < 0)
861 goto out;
862
863 /* Now set or clear the function option */
864 ret = write(fd, val, 1);
865 close(fd);
866
867 out:
868 return ret < 0 ? ret : 0;
869 }
870
set_ftrace_proc(int set)871 static int set_ftrace_proc(int set)
872 {
873 const char *path = "/proc/sys/kernel/ftrace_enabled";
874 int ret;
875
876 ret = set_ftrace_enable(path, set);
877 if (ret == -1)
878 die ("Can't %s ftrace", set ? "enable" : "disable");
879 return ret;
880 }
881
set_ftrace(struct buffer_instance * instance,int set,int use_proc)882 static int set_ftrace(struct buffer_instance *instance, int set, int use_proc)
883 {
884 char *path;
885 int ret;
886
887 path = tracefs_instance_get_file(instance->tracefs, "options/function-trace");
888 if (!path)
889 return -1;
890 ret = set_ftrace_enable(path, set);
891 tracefs_put_tracing_file(path);
892
893 /* Always enable ftrace_enable proc file when set is true */
894 if (ret < 0 || set || use_proc)
895 ret = set_ftrace_proc(set);
896
897 return ret;
898 }
899
write_file(const char * file,const char * str)900 static int write_file(const char *file, const char *str)
901 {
902 int ret;
903 int fd;
904
905 fd = open(file, O_WRONLY | O_TRUNC);
906 if (fd < 0)
907 die("opening to '%s'", file);
908 ret = write(fd, str, strlen(str));
909 close(fd);
910 return ret;
911 }
912
__clear_trace(struct buffer_instance * instance)913 static void __clear_trace(struct buffer_instance *instance)
914 {
915 FILE *fp;
916 char *path;
917
918 if (is_guest(instance))
919 return;
920
921 /* reset the trace */
922 path = tracefs_instance_get_file(instance->tracefs, "trace");
923 fp = fopen(path, "w");
924 if (!fp)
925 die("writing to '%s'", path);
926 tracefs_put_tracing_file(path);
927 fwrite("0", 1, 1, fp);
928 fclose(fp);
929 }
930
clear_trace_instances(void)931 static void clear_trace_instances(void)
932 {
933 struct buffer_instance *instance;
934
935 for_all_instances(instance)
936 __clear_trace(instance);
937 }
938
reset_max_latency(struct buffer_instance * instance)939 static void reset_max_latency(struct buffer_instance *instance)
940 {
941 tracefs_instance_file_write(instance->tracefs,
942 "tracing_max_latency", "0");
943 }
944
add_filter_pid(struct buffer_instance * instance,int pid,int exclude)945 static int add_filter_pid(struct buffer_instance *instance, int pid, int exclude)
946 {
947 struct filter_pids *p;
948 char buf[100];
949
950 for (p = instance->filter_pids; p; p = p->next) {
951 if (p->pid == pid) {
952 p->exclude = exclude;
953 return 0;
954 }
955 }
956
957 p = malloc(sizeof(*p));
958 if (!p)
959 die("Failed to allocate pid filter");
960 p->next = instance->filter_pids;
961 p->exclude = exclude;
962 p->pid = pid;
963 instance->filter_pids = p;
964 instance->nr_filter_pids++;
965
966 instance->len_filter_pids += sprintf(buf, "%d", pid);
967
968 return 1;
969 }
970
add_filter_pid_all(int pid,int exclude)971 static void add_filter_pid_all(int pid, int exclude)
972 {
973 struct buffer_instance *instance;
974
975 for_all_instances(instance)
976 add_filter_pid(instance, pid, exclude);
977 }
978
reset_save_ftrace_pid(struct buffer_instance * instance)979 static void reset_save_ftrace_pid(struct buffer_instance *instance)
980 {
981 static char *path;
982
983 if (!tracefs_file_exists(instance->tracefs, "set_ftrace_pid"))
984 return;
985
986 path = tracefs_instance_get_file(instance->tracefs, "set_ftrace_pid");
987 if (!path)
988 return;
989
990 reset_save_file_cond(path, RESET_DEFAULT_PRIO, "no pid", "");
991
992 tracefs_put_tracing_file(path);
993 }
994
update_ftrace_pid(struct buffer_instance * instance,const char * pid,int reset)995 static void update_ftrace_pid(struct buffer_instance *instance,
996 const char *pid, int reset)
997 {
998 int fd = -1;
999 char *path;
1000 int ret;
1001
1002 if (!tracefs_file_exists(instance->tracefs, "set_ftrace_pid"))
1003 return;
1004
1005 path = tracefs_instance_get_file(instance->tracefs, "set_ftrace_pid");
1006 if (!path)
1007 return;
1008
1009 fd = open(path, O_WRONLY | O_CLOEXEC | (reset ? O_TRUNC : 0));
1010 tracefs_put_tracing_file(path);
1011 if (fd < 0)
1012 return;
1013
1014 ret = write(fd, pid, strlen(pid));
1015
1016 /*
1017 * Older kernels required "-1" to disable pid
1018 */
1019 if (ret < 0 && !strlen(pid))
1020 ret = write(fd, "-1", 2);
1021
1022 if (ret < 0)
1023 die("error writing to %s", path);
1024 /* add whitespace in case another pid is written */
1025 write(fd, " ", 1);
1026 close(fd);
1027 }
1028
update_ftrace_pids(int reset)1029 static void update_ftrace_pids(int reset)
1030 {
1031 struct buffer_instance *instance;
1032 struct filter_pids *pid;
1033 static int first = 1;
1034 char buf[100];
1035 int rst;
1036
1037 for_all_instances(instance) {
1038 if (first)
1039 reset_save_ftrace_pid(instance);
1040 rst = reset;
1041 for (pid = instance->filter_pids; pid; pid = pid->next) {
1042 if (pid->exclude)
1043 continue;
1044 snprintf(buf, 100, "%d ", pid->pid);
1045 update_ftrace_pid(instance, buf, rst);
1046 /* Only reset the first entry */
1047 rst = 0;
1048 }
1049 }
1050
1051 if (first)
1052 first = 0;
1053 }
1054
1055 static void update_event_filters(struct buffer_instance *instance);
1056 static void update_pid_event_filters(struct buffer_instance *instance);
1057
append_filter_pid_range(char ** filter,int * curr_len,const char * field,int start_pid,int end_pid,bool exclude)1058 static void append_filter_pid_range(char **filter, int *curr_len,
1059 const char *field,
1060 int start_pid, int end_pid, bool exclude)
1061 {
1062 const char *op = "", *op1, *op2, *op3;
1063 int len;
1064
1065 if (*filter && **filter)
1066 op = exclude ? "&&" : "||";
1067
1068 /* Handle thus case explicitly so that we get `pid==3` instead of
1069 * `pid>=3&&pid<=3` for singleton ranges
1070 */
1071 if (start_pid == end_pid) {
1072 #define FMT "%s(%s%s%d)"
1073 len = snprintf(NULL, 0, FMT, op,
1074 field, exclude ? "!=" : "==", start_pid);
1075 *filter = realloc(*filter, *curr_len + len + 1);
1076 if (!*filter)
1077 die("realloc");
1078
1079 len = snprintf(*filter + *curr_len, len + 1, FMT, op,
1080 field, exclude ? "!=" : "==", start_pid);
1081 *curr_len += len;
1082
1083 return;
1084 #undef FMT
1085 }
1086
1087 if (exclude) {
1088 op1 = "<";
1089 op2 = "||";
1090 op3 = ">";
1091 } else {
1092 op1 = ">=";
1093 op2 = "&&";
1094 op3 = "<=";
1095 }
1096
1097 #define FMT "%s(%s%s%d%s%s%s%d)"
1098 len = snprintf(NULL, 0, FMT, op,
1099 field, op1, start_pid, op2,
1100 field, op3, end_pid);
1101 *filter = realloc(*filter, *curr_len + len + 1);
1102 if (!*filter)
1103 die("realloc");
1104
1105 len = snprintf(*filter + *curr_len, len + 1, FMT, op,
1106 field, op1, start_pid, op2,
1107 field, op3, end_pid);
1108 *curr_len += len;
1109 }
1110
1111 /**
1112 * make_pid_filter - create a filter string to all pids against @field
1113 * @curr_filter: Append to a previous filter (may realloc). Can be NULL
1114 * @field: The field to compare the pids against
1115 *
1116 * Creates a new string or appends to an existing one if @curr_filter
1117 * is not NULL. The new string will contain a filter with all pids
1118 * in pid_filter list with the format (@field == pid) || ..
1119 * If @curr_filter is not NULL, it will add this string as:
1120 * (@curr_filter) && ((@field == pid) || ...)
1121 */
make_pid_filter(struct buffer_instance * instance,char * curr_filter,const char * field)1122 static char *make_pid_filter(struct buffer_instance *instance,
1123 char *curr_filter, const char *field)
1124 {
1125 int start_pid = -1, last_pid = -1;
1126 int last_exclude = -1;
1127 struct filter_pids *p;
1128 char *filter = NULL;
1129 int curr_len = 0;
1130
1131 /* Use the new method if possible */
1132 if (instance->have_set_event_pid)
1133 return NULL;
1134
1135 if (!instance->filter_pids)
1136 return curr_filter;
1137
1138 for (p = instance->filter_pids; p; p = p->next) {
1139 /*
1140 * PIDs are inserted in `filter_pids` from the front and that's
1141 * why we expect them in descending order here.
1142 */
1143 if (p->pid == last_pid - 1 && p->exclude == last_exclude) {
1144 last_pid = p->pid;
1145 continue;
1146 }
1147
1148 if (start_pid != -1)
1149 append_filter_pid_range(&filter, &curr_len, field,
1150 last_pid, start_pid,
1151 last_exclude);
1152
1153 start_pid = last_pid = p->pid;
1154 last_exclude = p->exclude;
1155
1156 }
1157 append_filter_pid_range(&filter, &curr_len, field,
1158 last_pid, start_pid, last_exclude);
1159
1160 if (curr_filter) {
1161 char *save = filter;
1162 asprintf(&filter, "(%s)&&(%s)", curr_filter, filter);
1163 free(save);
1164 }
1165
1166 return filter;
1167 }
1168
1169 #define _STRINGIFY(x) #x
1170 #define STRINGIFY(x) _STRINGIFY(x)
1171
get_pid_addr_maps(struct buffer_instance * instance,int pid)1172 static int get_pid_addr_maps(struct buffer_instance *instance, int pid)
1173 {
1174 struct pid_addr_maps *maps = instance->pid_maps;
1175 struct tracecmd_proc_addr_map *map;
1176 unsigned long long begin, end;
1177 struct pid_addr_maps *m;
1178 char mapname[PATH_MAX+1];
1179 char fname[PATH_MAX+1];
1180 char buf[PATH_MAX+100];
1181 FILE *f;
1182 int ret;
1183 int res;
1184 int i;
1185
1186 sprintf(fname, "/proc/%d/exe", pid);
1187 ret = readlink(fname, mapname, PATH_MAX);
1188 if (ret >= PATH_MAX || ret < 0)
1189 return -ENOENT;
1190 mapname[ret] = 0;
1191
1192 sprintf(fname, "/proc/%d/maps", pid);
1193 f = fopen(fname, "r");
1194 if (!f)
1195 return -ENOENT;
1196
1197 while (maps) {
1198 if (pid == maps->pid)
1199 break;
1200 maps = maps->next;
1201 }
1202
1203 ret = -ENOMEM;
1204 if (!maps) {
1205 maps = calloc(1, sizeof(*maps));
1206 if (!maps)
1207 goto out_fail;
1208 maps->pid = pid;
1209 maps->next = instance->pid_maps;
1210 instance->pid_maps = maps;
1211 } else {
1212 for (i = 0; i < maps->nr_lib_maps; i++)
1213 free(maps->lib_maps[i].lib_name);
1214 free(maps->lib_maps);
1215 maps->lib_maps = NULL;
1216 maps->nr_lib_maps = 0;
1217 free(maps->proc_name);
1218 }
1219
1220 maps->proc_name = strdup(mapname);
1221 if (!maps->proc_name)
1222 goto out;
1223
1224 while (fgets(buf, sizeof(buf), f)) {
1225 mapname[0] = '\0';
1226 res = sscanf(buf, "%llx-%llx %*s %*x %*s %*d %"STRINGIFY(PATH_MAX)"s",
1227 &begin, &end, mapname);
1228 if (res == 3 && mapname[0] != '\0') {
1229 map = realloc(maps->lib_maps,
1230 (maps->nr_lib_maps + 1) * sizeof(*map));
1231 if (!map)
1232 goto out_fail;
1233 maps->lib_maps = map;
1234 map[maps->nr_lib_maps].end = end;
1235 map[maps->nr_lib_maps].start = begin;
1236 map[maps->nr_lib_maps].lib_name = strdup(mapname);
1237 if (!map[maps->nr_lib_maps].lib_name)
1238 goto out_fail;
1239 maps->nr_lib_maps++;
1240 }
1241 }
1242 out:
1243 fclose(f);
1244 return 0;
1245
1246 out_fail:
1247 fclose(f);
1248 if (maps) {
1249 for (i = 0; i < maps->nr_lib_maps; i++)
1250 free(maps->lib_maps[i].lib_name);
1251 if (instance->pid_maps != maps) {
1252 m = instance->pid_maps;
1253 while (m) {
1254 if (m->next == maps) {
1255 m->next = maps->next;
1256 break;
1257 }
1258 m = m->next;
1259 }
1260 } else
1261 instance->pid_maps = maps->next;
1262 free(maps->lib_maps);
1263 maps->lib_maps = NULL;
1264 maps->nr_lib_maps = 0;
1265 free(maps->proc_name);
1266 maps->proc_name = NULL;
1267 free(maps);
1268 }
1269 return ret;
1270 }
1271
get_filter_pid_maps(void)1272 static void get_filter_pid_maps(void)
1273 {
1274 struct buffer_instance *instance;
1275 struct filter_pids *p;
1276
1277 for_all_instances(instance) {
1278 if (!instance->get_procmap)
1279 continue;
1280 for (p = instance->filter_pids; p; p = p->next) {
1281 if (p->exclude)
1282 continue;
1283 get_pid_addr_maps(instance, p->pid);
1284 }
1285 }
1286 }
1287
update_task_filter(void)1288 static void update_task_filter(void)
1289 {
1290 struct buffer_instance *instance;
1291 int pid = getpid();
1292
1293 if (no_filter)
1294 return;
1295
1296 get_filter_pid_maps();
1297
1298 if (filter_task)
1299 add_filter_pid_all(pid, 0);
1300
1301 for_all_instances(instance) {
1302 if (!instance->filter_pids)
1303 continue;
1304 if (instance->common_pid_filter)
1305 free(instance->common_pid_filter);
1306 instance->common_pid_filter = make_pid_filter(instance, NULL,
1307 "common_pid");
1308 }
1309 update_ftrace_pids(1);
1310 for_all_instances(instance)
1311 update_pid_event_filters(instance);
1312 }
1313
trace_waitpid(enum trace_type type,pid_t pid,int * status,int options)1314 static pid_t trace_waitpid(enum trace_type type, pid_t pid, int *status, int options)
1315 {
1316 int ret;
1317
1318 if (type & TRACE_TYPE_STREAM)
1319 options |= WNOHANG;
1320
1321 do {
1322 ret = waitpid(pid, status, options);
1323 if (ret != 0)
1324 return ret;
1325
1326 if (type & TRACE_TYPE_STREAM)
1327 trace_stream_read(pids, recorder_threads, sleep_time);
1328 } while (1);
1329 }
1330
1331 #ifndef __NR_pidfd_open
1332 #define __NR_pidfd_open 434
1333 #endif
1334
pidfd_open(pid_t pid,unsigned int flags)1335 static int pidfd_open(pid_t pid, unsigned int flags) {
1336 return syscall(__NR_pidfd_open, pid, flags);
1337 }
1338
trace_waitpidfd(id_t pidfd)1339 static int trace_waitpidfd(id_t pidfd) {
1340 struct pollfd pollfd;
1341
1342 pollfd.fd = pidfd;
1343 pollfd.events = POLLIN;
1344
1345 while (!finished) {
1346 int ret = poll(&pollfd, 1, -1);
1347 /* If waitid was interrupted, keep waiting */
1348 if (ret < 0 && errno == EINTR)
1349 continue;
1350 else if (ret < 0)
1351 return 1;
1352 else
1353 break;
1354 }
1355
1356 return 0;
1357 }
1358
trace_wait_for_processes(struct buffer_instance * instance)1359 static int trace_wait_for_processes(struct buffer_instance *instance) {
1360 int ret = 0;
1361 int nr_fds = 0;
1362 int i;
1363 int *pidfds;
1364 struct filter_pids *pid;
1365
1366 pidfds = malloc(sizeof(int) * instance->nr_process_pids);
1367 if (!pidfds)
1368 return 1;
1369
1370 for (pid = instance->process_pids;
1371 pid && instance->nr_process_pids;
1372 pid = pid->next) {
1373 if (pid->exclude) {
1374 instance->nr_process_pids--;
1375 continue;
1376 }
1377 pidfds[nr_fds] = pidfd_open(pid->pid, 0);
1378
1379 /* If the pid doesn't exist, the process has probably exited */
1380 if (pidfds[nr_fds] < 0 && errno == ESRCH) {
1381 instance->nr_process_pids--;
1382 continue;
1383 } else if (pidfds[nr_fds] < 0) {
1384 ret = 1;
1385 goto out;
1386 }
1387
1388 nr_fds++;
1389 instance->nr_process_pids--;
1390 }
1391
1392 for (i = 0; i < nr_fds; i++) {
1393 if (trace_waitpidfd(pidfds[i])) {
1394 ret = 1;
1395 goto out;
1396 }
1397 }
1398
1399 out:
1400 for (i = 0; i < nr_fds; i++)
1401 close(pidfds[i]);
1402 free(pidfds);
1403 return ret;
1404 }
1405
add_event_pid(struct buffer_instance * instance,const char * buf)1406 static void add_event_pid(struct buffer_instance *instance, const char *buf)
1407 {
1408 tracefs_instance_file_write(instance->tracefs, "set_event_pid", buf);
1409 }
1410
1411 #ifndef NO_PTRACE
1412 /**
1413 * append_pid_filter - add a new pid to an existing filter
1414 * @curr_filter: the filter to append to. If NULL, then allocate one
1415 * @field: The fild to compare the pid to
1416 * @pid: The pid to add to.
1417 */
append_pid_filter(char * curr_filter,const char * field,int pid)1418 static char *append_pid_filter(char *curr_filter, const char *field, int pid)
1419 {
1420 char *filter;
1421 int len;
1422
1423 len = snprintf(NULL, 0, "(%s==%d)||", field, pid);
1424
1425 if (!curr_filter) {
1426 /* No need for +1 as we don't use the "||" */
1427 filter = malloc(len);
1428 if (!filter)
1429 die("Failed to allocate pid filter");
1430 sprintf(filter, "(%s==%d)", field, pid);
1431 } else {
1432 int indx = strlen(curr_filter);
1433
1434 len += indx;
1435 filter = realloc(curr_filter, len + indx + 1);
1436 if (!filter)
1437 die("realloc");
1438 sprintf(filter + indx, "||(%s==%d)", field, pid);
1439 }
1440
1441 return filter;
1442 }
1443
append_sched_event(struct event_list * event,const char * field,int pid)1444 static void append_sched_event(struct event_list *event, const char *field, int pid)
1445 {
1446 if (!event || !event->pid_filter)
1447 return;
1448
1449 event->pid_filter = append_pid_filter(event->pid_filter, field, pid);
1450 }
1451
update_sched_events(struct buffer_instance * instance,int pid)1452 static void update_sched_events(struct buffer_instance *instance, int pid)
1453 {
1454 /*
1455 * Also make sure that the sched_switch to this pid
1456 * and wakeups of this pid are also traced.
1457 * Only need to do this if the events are active.
1458 */
1459 append_sched_event(instance->sched_switch_event, "next_pid", pid);
1460 append_sched_event(instance->sched_wakeup_event, "pid", pid);
1461 append_sched_event(instance->sched_wakeup_new_event, "pid", pid);
1462 }
1463
1464 static int open_instance_fd(struct buffer_instance *instance,
1465 const char *file, int flags);
1466
add_new_filter_child_pid(int pid,int child)1467 static void add_new_filter_child_pid(int pid, int child)
1468 {
1469 struct buffer_instance *instance;
1470 struct filter_pids *fpid;
1471 char buf[100];
1472
1473 for_all_instances(instance) {
1474 if (!instance->ptrace_child || !instance->filter_pids)
1475 continue;
1476 for (fpid = instance->filter_pids; fpid; fpid = fpid->next) {
1477 if (fpid->pid == pid)
1478 break;
1479 }
1480 if (!fpid)
1481 continue;
1482
1483 add_filter_pid(instance, child, 0);
1484 sprintf(buf, "%d", child);
1485 update_ftrace_pid(instance, buf, 0);
1486
1487 instance->common_pid_filter = append_pid_filter(instance->common_pid_filter,
1488 "common_pid", pid);
1489 if (instance->have_set_event_pid) {
1490 add_event_pid(instance, buf);
1491 } else {
1492 update_sched_events(instance, pid);
1493 update_event_filters(instance);
1494 }
1495 }
1496
1497 }
1498
ptrace_attach(struct buffer_instance * instance,int pid)1499 static void ptrace_attach(struct buffer_instance *instance, int pid)
1500 {
1501 int ret;
1502
1503 ret = ptrace(PTRACE_ATTACH, pid, NULL, 0);
1504 if (ret < 0) {
1505 warning("Unable to trace process %d children", pid);
1506 do_ptrace = 0;
1507 return;
1508 }
1509 if (instance)
1510 add_filter_pid(instance, pid, 0);
1511 else
1512 add_filter_pid_all(pid, 0);
1513 }
1514
enable_ptrace(void)1515 static void enable_ptrace(void)
1516 {
1517 if (!do_ptrace || !filter_task)
1518 return;
1519
1520 ptrace(PTRACE_TRACEME, 0, NULL, 0);
1521 }
1522
get_intance_fpid(int pid)1523 static struct buffer_instance *get_intance_fpid(int pid)
1524 {
1525 struct buffer_instance *instance;
1526 struct filter_pids *fpid;
1527
1528 for_all_instances(instance) {
1529 for (fpid = instance->filter_pids; fpid; fpid = fpid->next) {
1530 if (fpid->exclude)
1531 continue;
1532 if (fpid->pid == pid)
1533 break;
1534 }
1535 if (fpid)
1536 return instance;
1537 }
1538
1539 return NULL;
1540 }
1541
ptrace_wait(enum trace_type type)1542 static void ptrace_wait(enum trace_type type)
1543 {
1544 struct buffer_instance *instance;
1545 struct filter_pids *fpid;
1546 unsigned long send_sig;
1547 unsigned long child;
1548 int nr_pids = 0;
1549 siginfo_t sig;
1550 int main_pids;
1551 int cstatus;
1552 int status;
1553 int i = 0;
1554 int *pids;
1555 int event;
1556 int pid;
1557 int ret;
1558
1559
1560 for_all_instances(instance)
1561 nr_pids += instance->nr_filter_pids;
1562
1563 pids = calloc(nr_pids, sizeof(int));
1564 if (!pids) {
1565 warning("Unable to allocate array for %d PIDs", nr_pids);
1566 return;
1567 }
1568 for_all_instances(instance) {
1569 if (!instance->ptrace_child && !instance->get_procmap)
1570 continue;
1571
1572 for (fpid = instance->filter_pids; fpid && i < nr_pids; fpid = fpid->next) {
1573 if (fpid->exclude)
1574 continue;
1575 pids[i++] = fpid->pid;
1576 }
1577 }
1578 main_pids = i;
1579
1580 do {
1581 ret = trace_waitpid(type, -1, &status, WSTOPPED | __WALL);
1582 if (ret < 0)
1583 continue;
1584
1585 pid = ret;
1586
1587 if (WIFSTOPPED(status)) {
1588 event = (status >> 16) & 0xff;
1589 ptrace(PTRACE_GETSIGINFO, pid, NULL, &sig);
1590 send_sig = sig.si_signo;
1591 /* Don't send ptrace sigs to child */
1592 if (send_sig == SIGTRAP || send_sig == SIGSTOP)
1593 send_sig = 0;
1594 switch (event) {
1595 case PTRACE_EVENT_FORK:
1596 case PTRACE_EVENT_VFORK:
1597 case PTRACE_EVENT_CLONE:
1598 /* forked a child */
1599 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &child);
1600 ptrace(PTRACE_SETOPTIONS, child, NULL,
1601 PTRACE_O_TRACEFORK |
1602 PTRACE_O_TRACEVFORK |
1603 PTRACE_O_TRACECLONE |
1604 PTRACE_O_TRACEEXIT);
1605 add_new_filter_child_pid(pid, child);
1606 ptrace(PTRACE_CONT, child, NULL, 0);
1607 break;
1608
1609 case PTRACE_EVENT_EXIT:
1610 instance = get_intance_fpid(pid);
1611 if (instance && instance->get_procmap)
1612 get_pid_addr_maps(instance, pid);
1613 ptrace(PTRACE_GETEVENTMSG, pid, NULL, &cstatus);
1614 ptrace(PTRACE_DETACH, pid, NULL, NULL);
1615 break;
1616 }
1617 ptrace(PTRACE_SETOPTIONS, pid, NULL,
1618 PTRACE_O_TRACEFORK |
1619 PTRACE_O_TRACEVFORK |
1620 PTRACE_O_TRACECLONE |
1621 PTRACE_O_TRACEEXIT);
1622 ptrace(PTRACE_CONT, pid, NULL, send_sig);
1623 }
1624 if (WIFEXITED(status) ||
1625 (WIFSTOPPED(status) && event == PTRACE_EVENT_EXIT)) {
1626 for (i = 0; i < nr_pids; i++) {
1627 if (pid == pids[i]) {
1628 pids[i] = 0;
1629 main_pids--;
1630 if (!main_pids)
1631 finished = 1;
1632 }
1633 }
1634 }
1635 } while (!finished && ret > 0);
1636
1637 free(pids);
1638 }
1639 #else
ptrace_wait(enum trace_type type)1640 static inline void ptrace_wait(enum trace_type type) { }
enable_ptrace(void)1641 static inline void enable_ptrace(void) { }
ptrace_attach(struct buffer_instance * instance,int pid)1642 static inline void ptrace_attach(struct buffer_instance *instance, int pid) { }
1643
1644 #endif /* NO_PTRACE */
1645
1646 static bool child_detached;
1647
daemonize_set_child_detached(int s)1648 static void daemonize_set_child_detached(int s)
1649 {
1650 child_detached = true;
1651 }
1652
daemonize_start(void)1653 static void daemonize_start(void)
1654 {
1655 int devnull;
1656 int status;
1657 int pid;
1658 int ret;
1659
1660 pid = fork();
1661 if (pid == -1)
1662 die("daemonize: fork failed");
1663
1664 if (pid == 0) { /* child */
1665 /*
1666 * We keep stdout and stderr open to allow the user to
1667 * see output and errors after the daemonization (the user can
1668 * choose to supress it with >/dev/null if the user wants).
1669 *
1670 * No reason to keep stdin open (it might interfere with the
1671 * shell), we redirect it to /dev/null.
1672 */
1673 devnull = open("/dev/null", O_RDONLY);
1674 if (devnull == -1)
1675 die("daemonize: open /dev/null failed");
1676
1677 if (devnull > 0) {
1678 if (dup2(devnull, 0) == -1)
1679 die("daemonize: dup2");
1680 close(0);
1681 }
1682
1683 return;
1684
1685 /*
1686 * The child returns to back to the caller, but the parent waits until
1687 * SIGRTMIN is received from the child (by calling daemonize_finish()),
1688 * or the child exits for some reason (usually an indication of
1689 * an error), which ever comes first.
1690 *
1691 * Then the parent exits (with the status code of the child,
1692 * if it finished early, or with 0 if SIGRTMIN was received),
1693 * which causes the child (and its entire process tree) to be
1694 * inherited by init.
1695 *
1696 * Note that until the child calls daemonize_finish(), it still has
1697 * the same session id as the parent, so it can die together with
1698 * the parent before daemonization finished (purposefully, since the
1699 * user might send a quick Ctrl^C to cancel the command, and we don't
1700 * want background processes staying alive in that case)
1701 */
1702 } else { /* parent */
1703 struct sigaction sa = {
1704 /* disable SA_RESTART, to allow waitpid() to be interrupted by SIGRTMIN */
1705 .sa_flags = 0,
1706 .sa_handler = daemonize_set_child_detached
1707 };
1708
1709 if (sigemptyset(&sa.sa_mask) == -1)
1710 die("daemonize: sigemptyset failed");
1711
1712 if (sigaddset(&sa.sa_mask, SIGRTMIN) == -1)
1713 die("daemonize: sigaddset failed");
1714
1715 if (sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL) == -1)
1716 die("daemonize: sigprocmask failed");
1717
1718 if (sigaction(SIGRTMIN, &sa, NULL) == -1)
1719 die("daemonize: sigaction failed");
1720
1721 do {
1722 ret = waitpid(pid, &status, 0);
1723 } while (!child_detached && ((ret < 0) && (errno == EINTR)));
1724
1725 if (child_detached)
1726 exit(0);
1727 else if (ret == pid)
1728 exit(WIFEXITED(status));
1729 else
1730 die("daemonize: waitpid failed");
1731
1732 __builtin_unreachable();
1733 }
1734 }
1735
daemonize_finish(void)1736 static void daemonize_finish(void)
1737 {
1738 /*
1739 * setsid() will also set the sid to be the pgid to all currently
1740 * running threads in the process group (such as the tsync thread).
1741 */
1742 if (setsid() == -1)
1743 die("daemonize: setsid");
1744
1745 if (kill(getppid(), SIGRTMIN) == -1)
1746 die("daemonize: kill");
1747
1748 make_pid_file(RECORD_PIDFILE);
1749 created_pidfile = true;
1750 }
1751
trace_or_sleep(enum trace_type type,bool pwait)1752 static void trace_or_sleep(enum trace_type type, bool pwait)
1753 {
1754 int i;
1755
1756 if (pwait)
1757 ptrace_wait(type);
1758 else if (type & TRACE_TYPE_STREAM) {
1759 /* Returns zero if it did not read anything (and did a sleep) */
1760 if (trace_stream_read(pids, recorder_threads, sleep_time) > 0)
1761 return;
1762 /* Force a flush if nothing was read (including on errors) */
1763 for (i = 0; i < recorder_threads; i++) {
1764 if (pids[i].pid > 0) {
1765 kill(pids[i].pid, SIGUSR2);
1766 }
1767 }
1768 } else
1769 sleep(10);
1770 }
1771
change_user(const char * user)1772 static int change_user(const char *user)
1773 {
1774 struct passwd *pwd;
1775
1776 if (!user)
1777 return 0;
1778
1779 pwd = getpwnam(user);
1780 if (!pwd)
1781 return -1;
1782 if (initgroups(user, pwd->pw_gid) < 0)
1783 return -1;
1784 if (setgid(pwd->pw_gid) < 0)
1785 return -1;
1786 if (setuid(pwd->pw_uid) < 0)
1787 return -1;
1788
1789 if (setenv("HOME", pwd->pw_dir, 1) < 0)
1790 return -1;
1791 if (setenv("USER", pwd->pw_name, 1) < 0)
1792 return -1;
1793 if (setenv("LOGNAME", pwd->pw_name, 1) < 0)
1794 return -1;
1795
1796 return 0;
1797 }
1798
execute_program(int argc,char ** argv)1799 static void execute_program(int argc, char **argv)
1800 {
1801 char buf[PATH_MAX + NAME_MAX + 1];
1802 char *path;
1803 char *entry;
1804 char *saveptr;
1805
1806 /*
1807 * if command specified by user is neither absolute nor
1808 * relative than we search for it in $PATH.
1809 */
1810 if (!strchr(argv[0], '/')) {
1811 path = getenv("PATH");
1812
1813 if (!path)
1814 die("can't search for '%s' if $PATH is NULL", argv[0]);
1815
1816 /* Do not modify the actual environment variable */
1817 path = strdup(path);
1818 if (!path)
1819 die("Failed to allocate PATH");
1820
1821 for (entry = strtok_r(path, ":", &saveptr);
1822 entry; entry = strtok_r(NULL, ":", &saveptr)) {
1823
1824 snprintf(buf, sizeof(buf), "%s/%s", entry, argv[0]);
1825
1826 /* does it exist and can we execute it? */
1827 if (access(buf, X_OK) == 0)
1828 break;
1829
1830 }
1831 free(path);
1832 } else {
1833 strncpy(buf, argv[0], sizeof(buf));
1834 }
1835
1836 tracecmd_enable_tracing();
1837 if (execve(buf, argv, environ)) {
1838 fprintf(stderr, "\n********************\n");
1839 fprintf(stderr, " Unable to exec %s\n", argv[0]);
1840 fprintf(stderr, "********************\n");
1841 die("Failed to exec %s", argv[0]);
1842 }
1843 }
1844
run_cmd(enum trace_type type,const char * user,int argc,char ** argv)1845 static void run_cmd(enum trace_type type, const char *user, int argc, char **argv)
1846 {
1847 int status;
1848 int pid;
1849
1850 if ((pid = fork()) < 0)
1851 die("failed to fork");
1852 if (!pid) {
1853 /* child */
1854 update_task_filter();
1855 if (!fork_process)
1856 enable_ptrace();
1857 /*
1858 * If we are using stderr for stdout, switch
1859 * it back to the saved stdout for the code we run.
1860 */
1861 if (save_stdout >= 0) {
1862 close(1);
1863 dup2(save_stdout, 1);
1864 close(save_stdout);
1865 }
1866
1867 if (change_user(user) < 0)
1868 die("Failed to change user to %s", user);
1869
1870 execute_program(argc, argv);
1871 }
1872
1873 if (do_daemonize)
1874 daemonize_finish();
1875 if (fork_process)
1876 exit(0);
1877 if (do_ptrace) {
1878 ptrace_attach(NULL, pid);
1879 ptrace_wait(type);
1880 } else
1881 trace_waitpid(type, pid, &status, 0);
1882 if (type & (TRACE_TYPE_START | TRACE_TYPE_SET))
1883 exit(0);
1884 }
1885
1886 static void
set_plugin_instance(struct buffer_instance * instance,const char * name)1887 set_plugin_instance(struct buffer_instance *instance, const char *name)
1888 {
1889 char *path;
1890 char zero = '0';
1891 int ret;
1892 int fd;
1893
1894 if (is_guest(instance))
1895 return;
1896
1897 path = tracefs_instance_get_file(instance->tracefs, "current_tracer");
1898 fd = open(path, O_WRONLY);
1899 if (fd < 0) {
1900 /*
1901 * Legacy kernels do not have current_tracer file, and they
1902 * always use nop. So, it doesn't need to try to change the
1903 * plugin for those if name is "nop".
1904 */
1905 if (!strncmp(name, "nop", 3)) {
1906 tracefs_put_tracing_file(path);
1907 return;
1908 }
1909 die("Opening '%s'", path);
1910 }
1911 ret = write(fd, name, strlen(name));
1912 close(fd);
1913
1914 if (ret < 0)
1915 die("writing to '%s'", path);
1916
1917 tracefs_put_tracing_file(path);
1918
1919 if (strncmp(name, "function", 8) != 0)
1920 return;
1921
1922 /* Make sure func_stack_trace option is disabled */
1923 /* First try instance file, then top level */
1924 path = tracefs_instance_get_file(instance->tracefs, "options/func_stack_trace");
1925 fd = open(path, O_WRONLY);
1926 if (fd < 0) {
1927 tracefs_put_tracing_file(path);
1928 path = tracefs_get_tracing_file("options/func_stack_trace");
1929 fd = open(path, O_WRONLY);
1930 if (fd < 0) {
1931 tracefs_put_tracing_file(path);
1932 return;
1933 }
1934 }
1935 /*
1936 * Always reset func_stack_trace to zero. Don't bother saving
1937 * the original content.
1938 */
1939 add_reset_file(path, "0", RESET_HIGH_PRIO);
1940 tracefs_put_tracing_file(path);
1941 write(fd, &zero, 1);
1942 close(fd);
1943 }
1944
set_plugin(const char * name)1945 static void set_plugin(const char *name)
1946 {
1947 struct buffer_instance *instance;
1948
1949 for_all_instances(instance)
1950 set_plugin_instance(instance, name);
1951 }
1952
save_option(struct buffer_instance * instance,const char * option)1953 static void save_option(struct buffer_instance *instance, const char *option)
1954 {
1955 struct opt_list *opt;
1956
1957 opt = malloc(sizeof(*opt));
1958 if (!opt)
1959 die("Failed to allocate option");
1960 opt->next = instance->options;
1961 instance->options = opt;
1962 opt->option = option;
1963 }
1964
set_option(struct buffer_instance * instance,const char * option)1965 static int set_option(struct buffer_instance *instance, const char *option)
1966 {
1967 FILE *fp;
1968 char *path;
1969
1970 path = tracefs_instance_get_file(instance->tracefs, "trace_options");
1971 fp = fopen(path, "w");
1972 if (!fp)
1973 warning("writing to '%s'", path);
1974 tracefs_put_tracing_file(path);
1975
1976 if (!fp)
1977 return -1;
1978
1979 fwrite(option, 1, strlen(option), fp);
1980 fclose(fp);
1981
1982 return 0;
1983 }
1984
disable_func_stack_trace_instance(struct buffer_instance * instance)1985 static void disable_func_stack_trace_instance(struct buffer_instance *instance)
1986 {
1987 struct stat st;
1988 char *content;
1989 char *path;
1990 char *cond;
1991 int size;
1992 int ret;
1993
1994 if (is_guest(instance))
1995 return;
1996
1997 path = tracefs_instance_get_file(instance->tracefs, "current_tracer");
1998 ret = stat(path, &st);
1999 tracefs_put_tracing_file(path);
2000 if (ret < 0)
2001 return;
2002
2003 content = tracefs_instance_file_read(instance->tracefs,
2004 "current_tracer", &size);
2005 cond = strstrip(content);
2006 if (memcmp(cond, "function", size - (cond - content)) !=0)
2007 goto out;
2008
2009 set_option(instance, "nofunc_stack_trace");
2010 out:
2011 free(content);
2012 }
2013
disable_func_stack_trace(void)2014 static void disable_func_stack_trace(void)
2015 {
2016 struct buffer_instance *instance;
2017
2018 for_all_instances(instance)
2019 disable_func_stack_trace_instance(instance);
2020 }
2021
add_reset_options(struct buffer_instance * instance)2022 static void add_reset_options(struct buffer_instance *instance)
2023 {
2024 struct opt_list *opt;
2025 const char *option;
2026 char *content;
2027 char *path;
2028 char *ptr;
2029 int len;
2030
2031 if (keep)
2032 return;
2033
2034 path = tracefs_instance_get_file(instance->tracefs, "trace_options");
2035 content = get_file_content(path);
2036
2037 for (opt = instance->options; opt; opt = opt->next) {
2038 option = opt->option;
2039 len = strlen(option);
2040 ptr = content;
2041 again:
2042 ptr = strstr(ptr, option);
2043 if (ptr) {
2044 /* First make sure its the option we want */
2045 if (ptr[len] != '\n') {
2046 ptr += len;
2047 goto again;
2048 }
2049 if (ptr - content >= 2 && strncmp(ptr - 2, "no", 2) == 0) {
2050 /* Make sure this isn't ohno-option */
2051 if (ptr > content + 2 && *(ptr - 3) != '\n') {
2052 ptr += len;
2053 goto again;
2054 }
2055 /* we enabled it */
2056 ptr[len] = 0;
2057 add_reset_file(path, ptr-2, RESET_DEFAULT_PRIO);
2058 ptr[len] = '\n';
2059 continue;
2060 }
2061 /* make sure this is our option */
2062 if (ptr > content && *(ptr - 1) != '\n') {
2063 ptr += len;
2064 goto again;
2065 }
2066 /* this option hasn't changed, ignore it */
2067 continue;
2068 }
2069
2070 /* ptr is NULL, not found, maybe option is a no */
2071 if (strncmp(option, "no", 2) != 0)
2072 /* option is really not found? */
2073 continue;
2074
2075 option += 2;
2076 len = strlen(option);
2077 ptr = content;
2078 loop:
2079 ptr = strstr(content, option);
2080 if (!ptr)
2081 /* Really not found? */
2082 continue;
2083
2084 /* make sure this is our option */
2085 if (ptr[len] != '\n') {
2086 ptr += len;
2087 goto loop;
2088 }
2089
2090 if (ptr > content && *(ptr - 1) != '\n') {
2091 ptr += len;
2092 goto loop;
2093 }
2094
2095 add_reset_file(path, option, RESET_DEFAULT_PRIO);
2096 }
2097 tracefs_put_tracing_file(path);
2098 free(content);
2099 }
2100
set_options(void)2101 static void set_options(void)
2102 {
2103 struct buffer_instance *instance;
2104 struct opt_list *opt;
2105 int ret;
2106
2107 for_all_instances(instance) {
2108 add_reset_options(instance);
2109 while (instance->options) {
2110 opt = instance->options;
2111 instance->options = opt->next;
2112 ret = set_option(instance, opt->option);
2113 if (ret < 0)
2114 die("Failed to set ftrace option %s",
2115 opt->option);
2116 free(opt);
2117 }
2118 }
2119 }
2120
set_saved_cmdlines_size(struct common_record_context * ctx)2121 static void set_saved_cmdlines_size(struct common_record_context *ctx)
2122 {
2123 int fd, len, ret = -1;
2124 char *path, *str;
2125
2126 if (!ctx->saved_cmdlines_size)
2127 return;
2128
2129 path = tracefs_get_tracing_file("saved_cmdlines_size");
2130 if (!path)
2131 goto err;
2132
2133 reset_save_file(path, RESET_DEFAULT_PRIO);
2134
2135 fd = open(path, O_WRONLY);
2136 tracefs_put_tracing_file(path);
2137 if (fd < 0)
2138 goto err;
2139
2140 len = asprintf(&str, "%d", ctx->saved_cmdlines_size);
2141 if (len < 0)
2142 die("%s couldn't allocate memory", __func__);
2143
2144 if (write(fd, str, len) > 0)
2145 ret = 0;
2146
2147 close(fd);
2148 free(str);
2149 err:
2150 if (ret)
2151 warning("Couldn't set saved_cmdlines_size");
2152 }
2153
trace_check_file_exists(struct buffer_instance * instance,char * file)2154 static int trace_check_file_exists(struct buffer_instance *instance, char *file)
2155 {
2156 struct stat st;
2157 char *path;
2158 int ret;
2159
2160 path = tracefs_instance_get_file(instance->tracefs, file);
2161 ret = stat(path, &st);
2162 tracefs_put_tracing_file(path);
2163
2164 return ret < 0 ? 0 : 1;
2165 }
2166
use_old_event_method(void)2167 static int use_old_event_method(void)
2168 {
2169 static int old_event_method;
2170 static int processed;
2171
2172 if (processed)
2173 return old_event_method;
2174
2175 /* Check if the kernel has the events/enable file */
2176 if (!trace_check_file_exists(&top_instance, "events/enable"))
2177 old_event_method = 1;
2178
2179 processed = 1;
2180
2181 return old_event_method;
2182 }
2183
old_update_events(const char * name,char update)2184 static void old_update_events(const char *name, char update)
2185 {
2186 char *path;
2187 FILE *fp;
2188 int ret;
2189
2190 if (strcmp(name, "all") == 0)
2191 name = "*:*";
2192
2193 /* need to use old way */
2194 path = tracefs_get_tracing_file("set_event");
2195 fp = fopen(path, "w");
2196 if (!fp)
2197 die("opening '%s'", path);
2198 tracefs_put_tracing_file(path);
2199
2200 /* Disable the event with "!" */
2201 if (update == '0')
2202 fwrite("!", 1, 1, fp);
2203
2204 ret = fwrite(name, 1, strlen(name), fp);
2205 if (ret < 0)
2206 die("bad event '%s'", name);
2207
2208 ret = fwrite("\n", 1, 1, fp);
2209 if (ret < 0)
2210 die("bad event '%s'", name);
2211
2212 fclose(fp);
2213
2214 return;
2215 }
2216
2217 static void
reset_events_instance(struct buffer_instance * instance)2218 reset_events_instance(struct buffer_instance *instance)
2219 {
2220 glob_t globbuf;
2221 char *path;
2222 char c;
2223 int fd;
2224 int i;
2225 int ret;
2226
2227 if (is_guest(instance))
2228 return;
2229
2230 if (use_old_event_method()) {
2231 /* old way only had top instance */
2232 if (!is_top_instance(instance))
2233 return;
2234 old_update_events("all", '0');
2235 return;
2236 }
2237
2238 c = '0';
2239 path = tracefs_instance_get_file(instance->tracefs, "events/enable");
2240 fd = open(path, O_WRONLY);
2241 if (fd < 0)
2242 die("opening to '%s'", path);
2243 ret = write(fd, &c, 1);
2244 close(fd);
2245 tracefs_put_tracing_file(path);
2246
2247 path = tracefs_instance_get_file(instance->tracefs, "events/*/filter");
2248 globbuf.gl_offs = 0;
2249 ret = glob(path, 0, NULL, &globbuf);
2250 tracefs_put_tracing_file(path);
2251 if (ret < 0)
2252 return;
2253
2254 for (i = 0; i < globbuf.gl_pathc; i++) {
2255 path = globbuf.gl_pathv[i];
2256 fd = open(path, O_WRONLY);
2257 if (fd < 0)
2258 die("opening to '%s'", path);
2259 ret = write(fd, &c, 1);
2260 close(fd);
2261 }
2262 globfree(&globbuf);
2263 }
2264
reset_events(void)2265 static void reset_events(void)
2266 {
2267 struct buffer_instance *instance;
2268
2269 for_all_instances(instance)
2270 reset_events_instance(instance);
2271 }
2272
2273 enum {
2274 STATE_NEWLINE,
2275 STATE_SKIP,
2276 STATE_COPY,
2277 };
2278
read_file(const char * file)2279 static char *read_file(const char *file)
2280 {
2281 char stbuf[BUFSIZ];
2282 char *buf = NULL;
2283 int size = 0;
2284 char *nbuf;
2285 int fd;
2286 int r;
2287
2288 fd = open(file, O_RDONLY);
2289 if (fd < 0)
2290 return NULL;
2291
2292 do {
2293 r = read(fd, stbuf, BUFSIZ);
2294 if (r <= 0)
2295 continue;
2296 nbuf = realloc(buf, size+r+1);
2297 if (!nbuf) {
2298 free(buf);
2299 buf = NULL;
2300 break;
2301 }
2302 buf = nbuf;
2303 memcpy(buf+size, stbuf, r);
2304 size += r;
2305 } while (r > 0);
2306
2307 close(fd);
2308 if (r == 0 && size > 0)
2309 buf[size] = '\0';
2310
2311 return buf;
2312 }
2313
read_error_log(const char * log)2314 static void read_error_log(const char *log)
2315 {
2316 char *buf, *line;
2317 char *start = NULL;
2318 char *p;
2319
2320 buf = read_file(log);
2321 if (!buf)
2322 return;
2323
2324 line = buf;
2325
2326 /* Only the last lines have meaning */
2327 while ((p = strstr(line, "\n")) && p[1]) {
2328 if (line[0] != ' ')
2329 start = line;
2330 line = p + 1;
2331 }
2332
2333 if (start)
2334 printf("%s", start);
2335
2336 free(buf);
2337 }
2338
show_error(const char * file,const char * type)2339 static void show_error(const char *file, const char *type)
2340 {
2341 struct stat st;
2342 char *path = strdup(file);
2343 char *p;
2344 int ret;
2345
2346 if (!path)
2347 die("Could not allocate memory");
2348
2349 p = strstr(path, "tracing");
2350 if (p) {
2351 if (strncmp(p + sizeof("tracing"), "instances", sizeof("instances") - 1) == 0) {
2352 p = strstr(p + sizeof("tracing") + sizeof("instances"), "/");
2353 if (!p)
2354 goto read_file;
2355 } else {
2356 p += sizeof("tracing") - 1;
2357 }
2358 ret = asprintf(&p, "%.*s/error_log", (int)(p - path), path);
2359 if (ret < 0)
2360 die("Could not allocate memory");
2361 ret = stat(p, &st);
2362 if (ret < 0) {
2363 free(p);
2364 goto read_file;
2365 }
2366 read_error_log(p);
2367 goto out;
2368 }
2369
2370 read_file:
2371 p = read_file(path);
2372 if (p)
2373 printf("%s", p);
2374
2375 out:
2376 printf("Failed %s of %s\n", type, file);
2377 free(path);
2378 return;
2379 }
2380
write_filter(const char * file,const char * filter)2381 static void write_filter(const char *file, const char *filter)
2382 {
2383 if (write_file(file, filter) < 0)
2384 show_error(file, "filter");
2385 }
2386
clear_filter(const char * file)2387 static void clear_filter(const char *file)
2388 {
2389 write_filter(file, "0");
2390 }
2391
write_trigger(const char * file,const char * trigger)2392 static void write_trigger(const char *file, const char *trigger)
2393 {
2394 if (write_file(file, trigger) < 0)
2395 show_error(file, "trigger");
2396 }
2397
clear_trigger(const char * file)2398 static int clear_trigger(const char *file)
2399 {
2400 char trigger[BUFSIZ];
2401 char *save = NULL;
2402 char *line;
2403 char *buf;
2404 int len;
2405 int ret;
2406
2407 buf = read_file(file);
2408 if (!buf) {
2409 perror(file);
2410 return 0;
2411 }
2412
2413 trigger[0] = '!';
2414
2415 for (line = strtok_r(buf, "\n", &save); line; line = strtok_r(NULL, "\n", &save)) {
2416 if (line[0] == '#')
2417 continue;
2418 len = strlen(line);
2419 if (len > BUFSIZ - 2)
2420 len = BUFSIZ - 2;
2421 strncpy(trigger + 1, line, len);
2422 trigger[len + 1] = '\0';
2423 /* We don't want any filters or extra on the line */
2424 strtok(trigger, " ");
2425 write_file(file, trigger);
2426 }
2427
2428 free(buf);
2429
2430 /*
2431 * Some triggers have an order in removing them.
2432 * They will not be removed if done in the wrong order.
2433 */
2434 buf = read_file(file);
2435 if (!buf)
2436 return 0;
2437
2438 ret = 0;
2439 for (line = strtok(buf, "\n"); line; line = strtok(NULL, "\n")) {
2440 if (line[0] == '#')
2441 continue;
2442 ret = 1;
2443 break;
2444 }
2445 free(buf);
2446 return ret;
2447 }
2448
clear_func_filter(const char * file)2449 static void clear_func_filter(const char *file)
2450 {
2451 char filter[BUFSIZ];
2452 struct stat st;
2453 char *line;
2454 char *buf;
2455 char *p;
2456 int len;
2457 int ret;
2458 int fd;
2459
2460 /* Function filters may not exist */
2461 ret = stat(file, &st);
2462 if (ret < 0)
2463 return;
2464
2465 /* First zero out normal filters */
2466 fd = open(file, O_WRONLY | O_TRUNC);
2467 if (fd < 0)
2468 die("opening to '%s'", file);
2469 close(fd);
2470
2471 buf = read_file(file);
2472 if (!buf) {
2473 perror(file);
2474 return;
2475 }
2476
2477 /* Now remove filters */
2478 filter[0] = '!';
2479
2480 /*
2481 * To delete a filter, we need to write a '!filter'
2482 * to the file for each filter.
2483 */
2484 for (line = strtok(buf, "\n"); line; line = strtok(NULL, "\n")) {
2485 if (line[0] == '#')
2486 continue;
2487 len = strlen(line);
2488 if (len > BUFSIZ - 2)
2489 len = BUFSIZ - 2;
2490
2491 strncpy(filter + 1, line, len);
2492 filter[len + 1] = '\0';
2493 /*
2494 * To remove "unlimited" filters, we must remove
2495 * the ":unlimited" from what we write.
2496 */
2497 if ((p = strstr(filter, ":unlimited"))) {
2498 *p = '\0';
2499 len = p - filter;
2500 }
2501 /*
2502 * The write to this file expects white space
2503 * at the end :-p
2504 */
2505 filter[len] = '\n';
2506 filter[len+1] = '\0';
2507 write_file(file, filter);
2508 }
2509 free(buf);
2510 }
2511
update_reset_triggers(void)2512 static void update_reset_triggers(void)
2513 {
2514 struct reset_file *reset;
2515
2516 while (reset_triggers) {
2517 reset = reset_triggers;
2518 reset_triggers = reset->next;
2519
2520 clear_trigger(reset->path);
2521 free(reset->path);
2522 free(reset);
2523 }
2524 }
2525
reset_buffer_files_instance(struct buffer_instance * instance)2526 static void reset_buffer_files_instance(struct buffer_instance *instance)
2527 {
2528 if (instance->old_buffer_size != instance->buffer_size)
2529 tracefs_instance_set_buffer_size(instance->tracefs,
2530 instance->old_buffer_size, -1);
2531
2532 if (instance->old_subbuf_size != instance->subbuf_size)
2533 tracefs_instance_set_subbuf_size(instance->tracefs,
2534 instance->old_subbuf_size);
2535 }
2536
reset_buffer_files(void)2537 static void reset_buffer_files(void)
2538 {
2539 struct buffer_instance *instance;
2540
2541 for_all_instances(instance) {
2542 reset_buffer_files_instance(instance);
2543 }
2544 }
2545
update_reset_files(void)2546 static void update_reset_files(void)
2547 {
2548 struct reset_file *reset;
2549
2550 while (reset_files) {
2551 reset = reset_files;
2552 reset_files = reset->next;
2553
2554 if (!keep)
2555 write_file(reset->path, reset->reset);
2556 free(reset->path);
2557 free(reset->reset);
2558 free(reset);
2559 }
2560
2561 reset_buffer_files();
2562 }
2563
2564 static void
update_event(struct event_list * event,const char * filter,int filter_only,char update)2565 update_event(struct event_list *event, const char *filter,
2566 int filter_only, char update)
2567 {
2568 const char *name = event->event;
2569 FILE *fp;
2570 char *path;
2571 int ret;
2572
2573 if (use_old_event_method()) {
2574 if (filter_only)
2575 return;
2576 old_update_events(name, update);
2577 return;
2578 }
2579
2580 if (filter && event->filter_file) {
2581 add_reset_file(event->filter_file, "0", RESET_DEFAULT_PRIO);
2582 write_filter(event->filter_file, filter);
2583 }
2584
2585 if (event->trigger_file) {
2586 add_reset_trigger(event->trigger_file);
2587 clear_trigger(event->trigger_file);
2588 write_trigger(event->trigger_file, event->trigger);
2589 /* Make sure we don't write this again */
2590 free(event->trigger_file);
2591 free(event->trigger);
2592 event->trigger_file = NULL;
2593 event->trigger = NULL;
2594 }
2595
2596 if (filter_only || !event->enable_file)
2597 return;
2598
2599 path = event->enable_file;
2600
2601 fp = fopen(path, "w");
2602 if (!fp)
2603 die("writing to '%s'", path);
2604 ret = fwrite(&update, 1, 1, fp);
2605 fclose(fp);
2606 if (ret < 0)
2607 die("writing to '%s'", path);
2608 }
2609
2610 /*
2611 * The debugfs file tracing_enabled needs to be deprecated.
2612 * But just in case anyone fiddled with it. If it exists,
2613 * make sure it is one.
2614 * No error checking needed here.
2615 */
check_tracing_enabled(void)2616 static void check_tracing_enabled(void)
2617 {
2618 static int fd = -1;
2619 char *path;
2620
2621 if (fd < 0) {
2622 path = tracefs_get_tracing_file("tracing_enabled");
2623 fd = open(path, O_WRONLY | O_CLOEXEC);
2624 tracefs_put_tracing_file(path);
2625
2626 if (fd < 0)
2627 return;
2628 }
2629 write(fd, "1", 1);
2630 }
2631
open_instance_fd(struct buffer_instance * instance,const char * file,int flags)2632 static int open_instance_fd(struct buffer_instance *instance,
2633 const char *file, int flags)
2634 {
2635 int fd;
2636 char *path;
2637
2638 path = tracefs_instance_get_file(instance->tracefs, file);
2639 fd = open(path, flags);
2640 if (fd < 0) {
2641 /* instances may not be created yet */
2642 if (is_top_instance(instance))
2643 die("opening '%s'", path);
2644 }
2645 tracefs_put_tracing_file(path);
2646
2647 return fd;
2648 }
2649
open_tracing_on(struct buffer_instance * instance)2650 static int open_tracing_on(struct buffer_instance *instance)
2651 {
2652 int fd = instance->tracing_on_fd;
2653
2654 /* OK, we keep zero for stdin */
2655 if (fd > 0)
2656 return fd;
2657
2658 fd = open_instance_fd(instance, "tracing_on", O_RDWR | O_CLOEXEC);
2659 if (fd < 0) {
2660 return fd;
2661 }
2662 instance->tracing_on_fd = fd;
2663
2664 return fd;
2665 }
2666
write_tracing_on(struct buffer_instance * instance,int on)2667 static void write_tracing_on(struct buffer_instance *instance, int on)
2668 {
2669 int ret;
2670 int fd;
2671
2672 if (is_guest(instance))
2673 return;
2674
2675 fd = open_tracing_on(instance);
2676 if (fd < 0)
2677 return;
2678
2679 if (on)
2680 ret = write(fd, "1", 1);
2681 else
2682 ret = write(fd, "0", 1);
2683
2684 if (ret < 0)
2685 die("writing 'tracing_on'");
2686 }
2687
read_tracing_on(struct buffer_instance * instance)2688 static int read_tracing_on(struct buffer_instance *instance)
2689 {
2690 int fd;
2691 char buf[10];
2692 int ret;
2693
2694 if (is_guest(instance))
2695 return -1;
2696
2697 fd = open_tracing_on(instance);
2698 if (fd < 0)
2699 return fd;
2700
2701 ret = read(fd, buf, 10);
2702 if (ret <= 0)
2703 die("Reading 'tracing_on'");
2704 buf[9] = 0;
2705 ret = atoi(buf);
2706
2707 return ret;
2708 }
2709
reset_max_latency_instance(void)2710 static void reset_max_latency_instance(void)
2711 {
2712 struct buffer_instance *instance;
2713
2714 for_all_instances(instance)
2715 reset_max_latency(instance);
2716 }
2717
tracecmd_enable_tracing(void)2718 void tracecmd_enable_tracing(void)
2719 {
2720 struct buffer_instance *instance;
2721
2722 check_tracing_enabled();
2723
2724 for_all_instances(instance)
2725 write_tracing_on(instance, 1);
2726
2727 if (latency)
2728 reset_max_latency_instance();
2729 }
2730
tracecmd_disable_tracing(void)2731 void tracecmd_disable_tracing(void)
2732 {
2733 struct buffer_instance *instance;
2734
2735 for_all_instances(instance)
2736 write_tracing_on(instance, 0);
2737 }
2738
tracecmd_disable_all_tracing(int disable_tracer)2739 void tracecmd_disable_all_tracing(int disable_tracer)
2740 {
2741 struct buffer_instance *instance;
2742
2743 tracecmd_disable_tracing();
2744
2745 disable_func_stack_trace();
2746
2747 if (disable_tracer)
2748 set_plugin("nop");
2749
2750 reset_events();
2751
2752 /* Force close and reset of ftrace pid file */
2753 for_all_instances(instance)
2754 update_ftrace_pid(instance, "", 1);
2755
2756 clear_trace_instances();
2757 }
2758
2759 static void
update_sched_event(struct buffer_instance * instance,struct event_list * event,const char * field)2760 update_sched_event(struct buffer_instance *instance,
2761 struct event_list *event, const char *field)
2762 {
2763 if (!event)
2764 return;
2765
2766 event->pid_filter = make_pid_filter(instance, event->pid_filter, field);
2767 }
2768
update_event_filters(struct buffer_instance * instance)2769 static void update_event_filters(struct buffer_instance *instance)
2770 {
2771 struct event_list *event;
2772 char *event_filter;
2773 int free_it;
2774 int len;
2775 int common_len = 0;
2776
2777 if (instance->common_pid_filter)
2778 common_len = strlen(instance->common_pid_filter);
2779
2780 for (event = instance->events; event; event = event->next) {
2781 if (!event->neg) {
2782
2783 free_it = 0;
2784 if (event->filter) {
2785 if (!instance->common_pid_filter)
2786 /*
2787 * event->pid_filter is only created if
2788 * common_pid_filter is. No need to check that.
2789 * Just use the current event->filter.
2790 */
2791 event_filter = event->filter;
2792 else if (event->pid_filter) {
2793 free_it = 1;
2794 len = common_len + strlen(event->pid_filter) +
2795 strlen(event->filter) + strlen("()&&(||)") + 1;
2796 event_filter = malloc(len);
2797 if (!event_filter)
2798 die("Failed to allocate event_filter");
2799 sprintf(event_filter, "(%s)&&(%s||%s)",
2800 event->filter, instance->common_pid_filter,
2801 event->pid_filter);
2802 } else {
2803 free_it = 1;
2804 len = common_len + strlen(event->filter) +
2805 strlen("()&&()") + 1;
2806 event_filter = malloc(len);
2807 if (!event_filter)
2808 die("Failed to allocate event_filter");
2809 sprintf(event_filter, "(%s)&&(%s)",
2810 event->filter, instance->common_pid_filter);
2811 }
2812 } else {
2813 /* event->pid_filter only exists when common_pid_filter does */
2814 if (!instance->common_pid_filter)
2815 continue;
2816
2817 if (event->pid_filter) {
2818 free_it = 1;
2819 len = common_len + strlen(event->pid_filter) +
2820 strlen("||") + 1;
2821 event_filter = malloc(len);
2822 if (!event_filter)
2823 die("Failed to allocate event_filter");
2824 sprintf(event_filter, "%s||%s",
2825 instance->common_pid_filter, event->pid_filter);
2826 } else
2827 event_filter = instance->common_pid_filter;
2828 }
2829
2830 update_event(event, event_filter, 1, '1');
2831 if (free_it)
2832 free(event_filter);
2833 }
2834 }
2835 }
2836
update_pid_filters(struct buffer_instance * instance)2837 static void update_pid_filters(struct buffer_instance *instance)
2838 {
2839 struct filter_pids *p;
2840 char *filter;
2841 char *str;
2842 int len;
2843 int ret;
2844 int fd;
2845
2846 if (is_guest(instance))
2847 return;
2848
2849 fd = open_instance_fd(instance, "set_event_pid",
2850 O_WRONLY | O_CLOEXEC | O_TRUNC);
2851 if (fd < 0)
2852 die("Failed to access set_event_pid");
2853
2854 len = instance->len_filter_pids + instance->nr_filter_pids;
2855 filter = malloc(len);
2856 if (!filter)
2857 die("Failed to allocate pid filter");
2858
2859 str = filter;
2860
2861 for (p = instance->filter_pids; p; p = p->next) {
2862 if (p->exclude)
2863 continue;
2864 len = sprintf(str, "%d ", p->pid);
2865 str += len;
2866 }
2867
2868 if (filter == str)
2869 goto out;
2870
2871 len = str - filter;
2872 str = filter;
2873 do {
2874 ret = write(fd, str, len);
2875 if (ret < 0)
2876 die("Failed to write to set_event_pid");
2877 str += ret;
2878 len -= ret;
2879 } while (ret >= 0 && len);
2880
2881 out:
2882 free(filter);
2883 close(fd);
2884 }
2885
update_pid_event_filters(struct buffer_instance * instance)2886 static void update_pid_event_filters(struct buffer_instance *instance)
2887 {
2888 if (instance->have_set_event_pid)
2889 return update_pid_filters(instance);
2890 /*
2891 * Also make sure that the sched_switch to this pid
2892 * and wakeups of this pid are also traced.
2893 * Only need to do this if the events are active.
2894 */
2895 update_sched_event(instance, instance->sched_switch_event, "next_pid");
2896 update_sched_event(instance, instance->sched_wakeup_event, "pid");
2897 update_sched_event(instance, instance->sched_wakeup_new_event, "pid");
2898
2899 update_event_filters(instance);
2900 }
2901
2902 #define MASK_STR_MAX 4096 /* Don't expect more than 32768 CPUS */
2903
alloc_mask_from_hex(struct buffer_instance * instance,const char * str)2904 static char *alloc_mask_from_hex(struct buffer_instance *instance, const char *str)
2905 {
2906 char *cpumask;
2907
2908 if (strcmp(str, "-1") == 0) {
2909 /* set all CPUs */
2910 int bytes = (instance->cpu_count + 7) / 8;
2911 int last = instance->cpu_count % 8;
2912 int i;
2913
2914 cpumask = malloc(MASK_STR_MAX);
2915 if (!cpumask)
2916 die("can't allocate cpumask");
2917
2918 if (bytes > (MASK_STR_MAX-1)) {
2919 warning("cpumask can't handle more than 32768 CPUS!");
2920 bytes = MASK_STR_MAX-1;
2921 }
2922
2923 sprintf(cpumask, "%x", (1 << last) - 1);
2924
2925 for (i = 1; i < bytes; i++)
2926 cpumask[i] = 'f';
2927
2928 cpumask[i+1] = 0;
2929 } else {
2930 cpumask = strdup(str);
2931 if (!cpumask)
2932 die("can't allocate cpumask");
2933 }
2934
2935 return cpumask;
2936 }
2937
set_mask(struct buffer_instance * instance)2938 static void set_mask(struct buffer_instance *instance)
2939 {
2940 struct stat st;
2941 char *path;
2942 int fd;
2943 int ret;
2944
2945 if (is_guest(instance))
2946 return;
2947
2948 if (!instance->cpumask)
2949 return;
2950
2951 path = tracefs_instance_get_file(instance->tracefs, "tracing_cpumask");
2952 if (!path)
2953 die("could not allocate path");
2954 reset_save_file(path, RESET_DEFAULT_PRIO);
2955
2956 ret = stat(path, &st);
2957 if (ret < 0) {
2958 warning("%s not found", path);
2959 goto out;
2960 }
2961
2962 fd = open(path, O_WRONLY | O_TRUNC);
2963 if (fd < 0)
2964 die("could not open %s\n", path);
2965
2966 write(fd, instance->cpumask, strlen(instance->cpumask));
2967
2968 close(fd);
2969 out:
2970 tracefs_put_tracing_file(path);
2971 free(instance->cpumask);
2972 instance->cpumask = NULL;
2973 }
2974
enable_events(struct buffer_instance * instance)2975 static void enable_events(struct buffer_instance *instance)
2976 {
2977 struct event_list *event;
2978
2979 if (is_guest(instance))
2980 return;
2981
2982 for (event = instance->events; event; event = event->next) {
2983 if (!event->neg)
2984 update_event(event, event->filter, 0, '1');
2985 }
2986
2987 /* Now disable any events */
2988 for (event = instance->events; event; event = event->next) {
2989 if (event->neg)
2990 update_event(event, NULL, 0, '0');
2991 }
2992 }
2993
tracecmd_enable_events(void)2994 void tracecmd_enable_events(void)
2995 {
2996 enable_events(first_instance);
2997 }
2998
set_clock(struct common_record_context * ctx,struct buffer_instance * instance)2999 static void set_clock(struct common_record_context *ctx, struct buffer_instance *instance)
3000 {
3001 const char *clock;
3002 char *path;
3003 char *content;
3004 char *str;
3005
3006 if (is_guest(instance))
3007 return;
3008
3009 if (instance->clock)
3010 clock = instance->clock;
3011 else
3012 clock = ctx->clock;
3013
3014 if (!clock)
3015 return;
3016
3017 /* The current clock is in brackets, reset it when we are done */
3018 content = tracefs_instance_file_read(instance->tracefs,
3019 "trace_clock", NULL);
3020
3021 /* check if first clock is set */
3022 if (*content == '[')
3023 str = strtok(content+1, "]");
3024 else {
3025 str = strtok(content, "[");
3026 if (!str)
3027 die("Can not find clock in trace_clock");
3028 str = strtok(NULL, "]");
3029 }
3030 path = tracefs_instance_get_file(instance->tracefs, "trace_clock");
3031 add_reset_file(path, str, RESET_DEFAULT_PRIO);
3032
3033 free(content);
3034 tracefs_put_tracing_file(path);
3035
3036 tracefs_instance_file_write(instance->tracefs,
3037 "trace_clock", clock);
3038 }
3039
set_max_graph_depth(struct buffer_instance * instance,char * max_graph_depth)3040 static void set_max_graph_depth(struct buffer_instance *instance, char *max_graph_depth)
3041 {
3042 char *path;
3043 int ret;
3044
3045 if (is_guest(instance))
3046 return;
3047
3048 path = tracefs_instance_get_file(instance->tracefs, "max_graph_depth");
3049 reset_save_file(path, RESET_DEFAULT_PRIO);
3050 tracefs_put_tracing_file(path);
3051 ret = tracefs_instance_file_write(instance->tracefs, "max_graph_depth",
3052 max_graph_depth);
3053 if (ret < 0)
3054 die("could not write to max_graph_depth");
3055 }
3056
check_file_in_dir(char * dir,char * file)3057 static bool check_file_in_dir(char *dir, char *file)
3058 {
3059 struct stat st;
3060 char *path;
3061 int ret;
3062
3063 ret = asprintf(&path, "%s/%s", dir, file);
3064 if (ret < 0)
3065 die("Failed to allocate id file path for %s/%s", dir, file);
3066 ret = stat(path, &st);
3067 free(path);
3068 if (ret < 0 || S_ISDIR(st.st_mode))
3069 return false;
3070 return true;
3071 }
3072
3073 /**
3074 * create_event - create and event descriptor
3075 * @instance: instance to use
3076 * @path: path to event attribute
3077 * @old_event: event descriptor to use as base
3078 *
3079 * NOTE: the function purpose is to create a data structure to describe
3080 * an ftrace event. During the process it becomes handy to change the
3081 * string `path`. So, do not rely on the content of `path` after you
3082 * invoke this function.
3083 */
3084 static struct event_list *
create_event(struct buffer_instance * instance,char * path,struct event_list * old_event)3085 create_event(struct buffer_instance *instance, char *path, struct event_list *old_event)
3086 {
3087 struct event_list *event;
3088 struct stat st;
3089 char *path_dirname;
3090 char *p;
3091 int ret;
3092
3093 event = malloc(sizeof(*event));
3094 if (!event)
3095 die("Failed to allocate event");
3096 *event = *old_event;
3097 add_event(instance, event);
3098
3099 if (event->filter || filter_task || instance->filter_pids) {
3100 event->filter_file = strdup(path);
3101 if (!event->filter_file)
3102 die("malloc filter file");
3103 }
3104
3105 path_dirname = dirname(path);
3106
3107 ret = asprintf(&p, "%s/enable", path_dirname);
3108 if (ret < 0)
3109 die("Failed to allocate enable path for %s", path);
3110 ret = stat(p, &st);
3111 if (ret >= 0)
3112 event->enable_file = p;
3113 else
3114 free(p);
3115
3116 if (old_event->trigger) {
3117 if (check_file_in_dir(path_dirname, "trigger")) {
3118 event->trigger = strdup(old_event->trigger);
3119 ret = asprintf(&p, "%s/trigger", path_dirname);
3120 if (ret < 0)
3121 die("Failed to allocate trigger path for %s", path);
3122 event->trigger_file = p;
3123 } else {
3124 /* Check if this is event or system.
3125 * Systems do not have trigger files by design
3126 */
3127 if (check_file_in_dir(path_dirname, "id"))
3128 die("trigger specified but not supported by this kernel");
3129 }
3130 }
3131
3132 return event;
3133 }
3134
make_sched_event(struct buffer_instance * instance,struct event_list ** event,struct event_list * sched,const char * sched_path)3135 static void make_sched_event(struct buffer_instance *instance,
3136 struct event_list **event, struct event_list *sched,
3137 const char *sched_path)
3138 {
3139 char *path_dirname;
3140 char *tmp_file;
3141 char *path;
3142 int ret;
3143
3144 /* Do nothing if the event already exists */
3145 if (*event)
3146 return;
3147
3148 /* we do not want to corrupt sched->filter_file when using dirname() */
3149 tmp_file = strdup(sched->filter_file);
3150 if (!tmp_file)
3151 die("Failed to allocate path for %s", sched_path);
3152 path_dirname = dirname(tmp_file);
3153
3154 ret = asprintf(&path, "%s/%s/filter", path_dirname, sched_path);
3155 free(tmp_file);
3156 if (ret < 0)
3157 die("Failed to allocate path for %s", sched_path);
3158
3159 *event = create_event(instance, path, sched);
3160 free(path);
3161 }
3162
test_event(struct event_list * event,const char * path,const char * name,struct event_list ** save,int len)3163 static void test_event(struct event_list *event, const char *path,
3164 const char *name, struct event_list **save, int len)
3165 {
3166 path += len - strlen(name);
3167
3168 if (strcmp(path, name) != 0)
3169 return;
3170
3171 *save = event;
3172 }
3173
print_event(const char * fmt,...)3174 static void print_event(const char *fmt, ...)
3175 {
3176 va_list ap;
3177
3178 if (!show_status)
3179 return;
3180
3181 va_start(ap, fmt);
3182 vprintf(fmt, ap);
3183 va_end(ap);
3184
3185 printf("\n");
3186 }
3187
3188
expand_event_files(struct buffer_instance * instance,const char * file,struct event_list * old_event)3189 static int expand_event_files(struct buffer_instance *instance,
3190 const char *file, struct event_list *old_event)
3191 {
3192 struct event_list **save_event_tail = instance->event_next;
3193 struct event_list *sched_event = NULL;
3194 struct event_list *event;
3195 glob_t globbuf;
3196 char *path;
3197 char *p;
3198 int ret;
3199 int i;
3200
3201 ret = asprintf(&p, "events/%s/filter", file);
3202 if (ret < 0)
3203 die("Failed to allocate event filter path for %s", file);
3204
3205 path = tracefs_instance_get_file(instance->tracefs, p);
3206
3207 globbuf.gl_offs = 0;
3208 ret = glob(path, 0, NULL, &globbuf);
3209 tracefs_put_tracing_file(path);
3210 free(p);
3211
3212 if (ret < 0)
3213 die("No filters found");
3214
3215 for (i = 0; i < globbuf.gl_pathc; i++) {
3216 int len;
3217
3218 path = globbuf.gl_pathv[i];
3219
3220 event = create_event(instance, path, old_event);
3221 print_event("%s\n", path);
3222
3223 len = strlen(path);
3224
3225 test_event(event, path, "sched", &sched_event, len);
3226 test_event(event, path, "sched/sched_switch", &instance->sched_switch_event, len);
3227 test_event(event, path, "sched/sched_wakeup_new", &instance->sched_wakeup_new_event, len);
3228 test_event(event, path, "sched/sched_wakeup", &instance->sched_wakeup_event, len);
3229 }
3230
3231 if (sched_event && sched_event->filter_file) {
3232 /* make sure all sched events exist */
3233 make_sched_event(instance, &instance->sched_switch_event,
3234 sched_event, "sched_switch");
3235 make_sched_event(instance, &instance->sched_wakeup_event,
3236 sched_event, "sched_wakeup");
3237 make_sched_event(instance, &instance->sched_wakeup_new_event,
3238 sched_event, "sched_wakeup_new");
3239
3240 }
3241
3242
3243 globfree(&globbuf);
3244
3245 /* If the event list tail changed, that means events were added */
3246 return save_event_tail == instance->event_next;
3247 }
3248
expand_events_all(struct buffer_instance * instance,char * system_name,char * event_name,struct event_list * event)3249 static int expand_events_all(struct buffer_instance *instance,
3250 char *system_name, char *event_name,
3251 struct event_list *event)
3252 {
3253 char *name;
3254 int ret;
3255
3256 ret = asprintf(&name, "%s/%s", system_name, event_name);
3257 if (ret < 0)
3258 die("Failed to allocate system/event for %s/%s",
3259 system_name, event_name);
3260 ret = expand_event_files(instance, name, event);
3261 free(name);
3262
3263 return ret;
3264 }
3265
expand_event(struct buffer_instance * instance,struct event_list * event)3266 static void expand_event(struct buffer_instance *instance, struct event_list *event)
3267 {
3268 const char *name = event->event;
3269 char *str;
3270 char *ptr;
3271 int ret;
3272
3273 /*
3274 * We allow the user to use "all" to enable all events.
3275 * Expand event_selection to all systems.
3276 */
3277 if (strcmp(name, "all") == 0) {
3278 expand_event_files(instance, "*", event);
3279 return;
3280 }
3281
3282 str = strdup(name);
3283 if (!str)
3284 die("Failed to allocate %s string", name);
3285
3286 ptr = strchr(str, ':');
3287 if (ptr) {
3288 *ptr = '\0';
3289 ptr++;
3290
3291 if (strlen(ptr))
3292 ret = expand_events_all(instance, str, ptr, event);
3293 else
3294 ret = expand_events_all(instance, str, "*", event);
3295
3296 if (!ignore_event_not_found && ret)
3297 die("No events enabled with %s", name);
3298
3299 goto out;
3300 }
3301
3302 /* No ':' so enable all matching systems and events */
3303 ret = expand_event_files(instance, str, event);
3304 ret &= expand_events_all(instance, "*", str, event);
3305 if (event->trigger)
3306 ret &= expand_events_all(instance, str, "*", event);
3307
3308 if (!ignore_event_not_found && ret)
3309 die("No events enabled with %s", name);
3310
3311 out:
3312 free(str);
3313 }
3314
expand_event_instance(struct buffer_instance * instance)3315 static void expand_event_instance(struct buffer_instance *instance)
3316 {
3317 struct event_list *compressed_list = instance->events;
3318 struct event_list *event;
3319
3320 if (is_guest(instance))
3321 return;
3322
3323 reset_event_list(instance);
3324
3325 while (compressed_list) {
3326 event = compressed_list;
3327 compressed_list = event->next;
3328 expand_event(instance, event);
3329 free(event->trigger);
3330 free(event);
3331 }
3332 }
3333
expand_event_list(void)3334 static void expand_event_list(void)
3335 {
3336 struct buffer_instance *instance;
3337
3338 if (use_old_event_method())
3339 return;
3340
3341 for_all_instances(instance)
3342 expand_event_instance(instance);
3343 }
3344
finish(void)3345 static void finish(void)
3346 {
3347 static int secs = 1;
3348
3349 sleep_time = 0;
3350
3351 /* all done */
3352 if (recorder) {
3353 tracecmd_stop_recording(recorder);
3354 /*
3355 * We could just call the alarm if the above returned non zero,
3356 * as zero is suppose to guarantee that the reader woke up.
3357 * But as this is called from a signal handler, that may not
3358 * necessarily be the case.
3359 */
3360 alarm(secs++);
3361 }
3362 finished = 1;
3363 }
3364
flush(void)3365 static void flush(void)
3366 {
3367 if (recorder)
3368 tracecmd_flush_recording(recorder, false);
3369 }
3370
do_sig(int sig)3371 static void do_sig(int sig)
3372 {
3373 switch (sig) {
3374 case SIGALRM:
3375 case SIGUSR1:
3376 case SIGINT:
3377 case SIGTERM:
3378 return finish();
3379 case SIGUSR2:
3380 return flush();
3381 }
3382 }
3383
do_getaddrinfo(const char * host,unsigned int port,enum port_type type)3384 static struct addrinfo *do_getaddrinfo(const char *host, unsigned int port,
3385 enum port_type type)
3386 {
3387 struct addrinfo *results;
3388 struct addrinfo hints;
3389 char buf[BUFSIZ];
3390 int s;
3391
3392 snprintf(buf, BUFSIZ, "%u", port);
3393
3394 memset(&hints, 0, sizeof(hints));
3395 hints.ai_family = AF_UNSPEC;
3396 hints.ai_socktype = type == USE_TCP ? SOCK_STREAM : SOCK_DGRAM;
3397
3398 s = getaddrinfo(host, buf, &hints, &results);
3399 if (s != 0) {
3400 gai_err = gai_strerror(s);
3401 return NULL;
3402 }
3403
3404 dprint("Attached port %s: %d to results: %p\n",
3405 type == USE_TCP ? "TCP" : "UDP", port, results);
3406
3407 return results;
3408 }
3409
connect_addr(struct addrinfo * results)3410 static int connect_addr(struct addrinfo *results)
3411 {
3412 struct addrinfo *rp;
3413 int sfd = -1;
3414
3415 for (rp = results; rp != NULL; rp = rp->ai_next) {
3416 sfd = socket(rp->ai_family, rp->ai_socktype,
3417 rp->ai_protocol);
3418 if (sfd == -1)
3419 continue;
3420
3421 set_tcp_no_delay(sfd, rp->ai_socktype);
3422 if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
3423 break;
3424 close(sfd);
3425 }
3426
3427 if (rp == NULL)
3428 return -1;
3429
3430 dprint("connect results: %p with fd: %d\n", results, sfd);
3431
3432 return sfd;
3433 }
3434
connect_port(const char * host,unsigned int port,enum port_type type)3435 static int connect_port(const char *host, unsigned int port, enum port_type type)
3436 {
3437 struct addrinfo *results;
3438 int sfd;
3439
3440 if (type == USE_VSOCK)
3441 return trace_vsock_open(atoi(host), port);
3442
3443 results = do_getaddrinfo(host, port, type);
3444
3445 if (!results)
3446 die("connecting to %s server %s:%u",
3447 type == USE_TCP ? "TCP" : "UDP", host, port);
3448
3449 sfd = connect_addr(results);
3450
3451 freeaddrinfo(results);
3452
3453 if (sfd < 0)
3454 die("Can not connect to %s server %s:%u",
3455 type == USE_TCP ? "TCP" : "UDP", host, port);
3456
3457 return sfd;
3458 }
3459
do_accept(int sd)3460 static int do_accept(int sd)
3461 {
3462 int cd;
3463
3464 for (;;) {
3465 dprint("Wait on accept: %d\n", sd);
3466 cd = accept(sd, NULL, NULL);
3467 dprint("accepted: %d\n", cd);
3468 if (cd < 0) {
3469 if (errno == EINTR)
3470 continue;
3471 die("accept");
3472 }
3473
3474 return cd;
3475 }
3476
3477 return -1;
3478 }
3479
parse_guest_name(char * gname,int * cid,int * port,struct addrinfo ** res)3480 static char *parse_guest_name(char *gname, int *cid, int *port,
3481 struct addrinfo **res)
3482 {
3483 struct trace_guest *guest = NULL;
3484 struct addrinfo *result;
3485 char *ip = NULL;
3486 char *p;
3487
3488 *res = NULL;
3489
3490 *port = -1;
3491 for (p = gname + strlen(gname); p > gname; p--) {
3492 if (*p == ':')
3493 break;
3494 }
3495 if (p > gname) {
3496 *p = '\0';
3497 *port = atoi(p + 1);
3498 }
3499
3500 *cid = -1;
3501 p = strrchr(gname, '@');
3502 if (p) {
3503 *p = '\0';
3504 *cid = atoi(p + 1);
3505 } else if (is_digits(gname)) {
3506 *cid = atoi(gname);
3507 } else {
3508 /* Check if this is an IP address */
3509 if (strstr(gname, ":") || strstr(gname, "."))
3510 ip = gname;
3511 }
3512
3513 if (!ip && *cid < 0)
3514 read_qemu_guests();
3515
3516 if (!ip)
3517 guest = trace_get_guest(*cid, gname);
3518 if (guest) {
3519 *cid = guest->cid;
3520 return guest->name;
3521 }
3522
3523 /* Test to see if this is an internet address */
3524 result = do_getaddrinfo(gname, *port, USE_TCP);
3525 if (!result)
3526 return NULL;
3527
3528 *res = result;
3529
3530 return gname;
3531 }
3532
set_prio(int prio)3533 static void set_prio(int prio)
3534 {
3535 struct sched_param sp;
3536
3537 memset(&sp, 0, sizeof(sp));
3538 sp.sched_priority = prio;
3539 if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0)
3540 warning("failed to set priority");
3541 }
3542
3543 static struct tracecmd_recorder *
create_recorder_instance_pipe(struct buffer_instance * instance,int cpu,int * brass)3544 create_recorder_instance_pipe(struct buffer_instance *instance,
3545 int cpu, int *brass)
3546 {
3547 struct tracecmd_recorder *recorder;
3548 unsigned flags = recorder_flags | TRACECMD_RECORD_BLOCK_SPLICE;
3549
3550 /* This is already the child */
3551 close(brass[0]);
3552
3553 recorder = tracecmd_create_buffer_recorder_fd(brass[1], cpu, flags, instance->tracefs);
3554
3555 return recorder;
3556 }
3557
3558 static struct tracecmd_recorder *
create_recorder_instance(struct buffer_instance * instance,const char * file,int cpu,int * brass)3559 create_recorder_instance(struct buffer_instance *instance, const char *file, int cpu,
3560 int *brass)
3561 {
3562 struct tracecmd_recorder *record;
3563 struct addrinfo *result;
3564
3565 if (is_guest(instance)) {
3566 int fd;
3567 unsigned int flags;
3568
3569 if (instance->use_fifos)
3570 fd = instance->fds[cpu];
3571 else if (is_network(instance)) {
3572 result = do_getaddrinfo(instance->name,
3573 instance->client_ports[cpu],
3574 instance->port_type);
3575 if (!result)
3576 die("Failed to connect to %s port %d\n",
3577 instance->name,
3578 instance->client_ports[cpu]);
3579 fd = connect_addr(result);
3580 freeaddrinfo(result);
3581 } else
3582 fd = trace_vsock_open(instance->cid, instance->client_ports[cpu]);
3583 if (fd < 0)
3584 die("Failed to connect to agent");
3585
3586 flags = recorder_flags;
3587 if (instance->use_fifos)
3588 flags |= TRACECMD_RECORD_NOBRASS;
3589 else if (!trace_vsock_can_splice_read())
3590 flags |= TRACECMD_RECORD_NOSPLICE;
3591 return tracecmd_create_recorder_virt(file, cpu, flags, fd, max_kb);
3592 }
3593
3594 if (brass)
3595 return create_recorder_instance_pipe(instance, cpu, brass);
3596
3597 if (!tracefs_instance_get_name(instance->tracefs))
3598 return tracecmd_create_recorder_maxkb(file, cpu, recorder_flags, max_kb);
3599
3600 record = tracecmd_create_buffer_recorder_maxkb(file, cpu, recorder_flags,
3601 instance->tracefs, max_kb);
3602 return record;
3603 }
3604
3605 /*
3606 * If extract is set, then this is going to set up the recorder,
3607 * connections and exit as the tracing is serialized by a single thread.
3608 */
create_recorder(struct buffer_instance * instance,int cpu,enum trace_type type,int * brass)3609 static int create_recorder(struct buffer_instance *instance, int cpu,
3610 enum trace_type type, int *brass)
3611 {
3612 struct tracefs_instance *recorder_instance = NULL;
3613 long ret;
3614 char *file;
3615 pid_t pid;
3616
3617 if (type != TRACE_TYPE_EXTRACT) {
3618
3619 pid = fork();
3620 if (pid < 0)
3621 die("fork");
3622
3623 if (pid)
3624 return pid;
3625
3626 signal(SIGINT, SIG_IGN);
3627 signal(SIGTERM, SIG_IGN);
3628 signal(SIGUSR1, do_sig);
3629 signal(SIGUSR2, do_sig);
3630 signal(SIGALRM, do_sig);
3631
3632 if (rt_prio)
3633 set_prio(rt_prio);
3634
3635 /* do not kill tasks on error */
3636 instance->cpu_count = 0;
3637 }
3638
3639 if ((instance->client_ports && !is_guest(instance)) || is_agent(instance)) {
3640 unsigned int flags = recorder_flags;
3641 int fd;
3642
3643 if (is_agent(instance)) {
3644 if (instance->use_fifos)
3645 fd = instance->fds[cpu];
3646 else {
3647 again:
3648 fd = do_accept(instance->fds[cpu]);
3649 if (instance->host &&
3650 !trace_net_cmp_connection_fd(fd, instance->host)) {
3651 dprint("Client does not match '%s' for cpu:%d\n",
3652 instance->host, cpu);
3653 close(fd);
3654 goto again;
3655 }
3656 }
3657 } else {
3658 fd = connect_port(host, instance->client_ports[cpu],
3659 instance->port_type);
3660 }
3661 if (fd < 0)
3662 die("Failed connecting to client");
3663 if (tracefs_instance_get_name(instance->tracefs) && !is_agent(instance))
3664 recorder_instance = instance->tracefs;
3665
3666 recorder = tracecmd_create_buffer_recorder_fd(fd, cpu, flags, recorder_instance);
3667 } else {
3668 file = get_temp_file(instance, cpu);
3669 recorder = create_recorder_instance(instance, file, cpu, brass);
3670 put_temp_file(file);
3671 }
3672
3673 if (!recorder)
3674 die ("can't create recorder");
3675
3676 if (type == TRACE_TYPE_EXTRACT) {
3677 ret = tracecmd_flush_recording(recorder, true);
3678 tracecmd_free_recorder(recorder);
3679 recorder = NULL;
3680 return ret;
3681 }
3682
3683 while (!finished) {
3684 if (tracecmd_start_recording(recorder, sleep_time) < 0)
3685 break;
3686 }
3687 tracecmd_free_recorder(recorder);
3688 recorder = NULL;
3689
3690 exit(0);
3691 }
3692
check_first_msg_from_server(struct tracecmd_msg_handle * msg_handle)3693 static void check_first_msg_from_server(struct tracecmd_msg_handle *msg_handle)
3694 {
3695 char buf[BUFSIZ];
3696
3697 read(msg_handle->fd, buf, 8);
3698
3699 /* Make sure the server is the tracecmd server */
3700 if (memcmp(buf, "tracecmd", 8) != 0)
3701 die("server not tracecmd server");
3702 }
3703
communicate_with_listener_v1(struct tracecmd_msg_handle * msg_handle,struct buffer_instance * instance)3704 static void communicate_with_listener_v1(struct tracecmd_msg_handle *msg_handle,
3705 struct buffer_instance *instance)
3706 {
3707 unsigned int *client_ports;
3708 char buf[BUFSIZ];
3709 ssize_t n;
3710 int cpu, i;
3711
3712 check_first_msg_from_server(msg_handle);
3713
3714 /* write the number of CPUs we have (in ASCII) */
3715 sprintf(buf, "%d", local_cpu_count);
3716
3717 /* include \0 */
3718 write(msg_handle->fd, buf, strlen(buf)+1);
3719
3720 /* write the pagesize (in ASCII) */
3721 sprintf(buf, "%d", page_size);
3722
3723 /* include \0 */
3724 write(msg_handle->fd, buf, strlen(buf)+1);
3725
3726 /*
3727 * If we are using IPV4 and our page size is greater than
3728 * or equal to 64K, we need to punt and use TCP. :-(
3729 */
3730
3731 /* TODO, test for ipv4 */
3732 if (page_size >= UDP_MAX_PACKET) {
3733 warning("page size too big for UDP using TCP in live read");
3734 instance->port_type = USE_TCP;
3735 msg_handle->flags |= TRACECMD_MSG_FL_USE_TCP;
3736 }
3737
3738 if (instance->port_type == USE_TCP) {
3739 /* Send one option */
3740 write(msg_handle->fd, "1", 2);
3741 /* Size 4 */
3742 write(msg_handle->fd, "4", 2);
3743 /* use TCP */
3744 write(msg_handle->fd, "TCP", 4);
3745 } else
3746 /* No options */
3747 write(msg_handle->fd, "0", 2);
3748
3749 client_ports = malloc(local_cpu_count * sizeof(*client_ports));
3750 if (!client_ports)
3751 die("Failed to allocate client ports for %d cpus", local_cpu_count);
3752
3753 /*
3754 * Now we will receive back a comma deliminated list
3755 * of client ports to connect to.
3756 */
3757 for (cpu = 0; cpu < local_cpu_count; cpu++) {
3758 for (i = 0; i < BUFSIZ; i++) {
3759 n = read(msg_handle->fd, buf+i, 1);
3760 if (n != 1)
3761 die("Error, reading server ports");
3762 if (!buf[i] || buf[i] == ',')
3763 break;
3764 }
3765 if (i == BUFSIZ)
3766 die("read bad port number");
3767 buf[i] = 0;
3768 client_ports[cpu] = atoi(buf);
3769 }
3770
3771 instance->client_ports = client_ports;
3772 }
3773
communicate_with_listener_v3(struct tracecmd_msg_handle * msg_handle,unsigned int ** client_ports)3774 static void communicate_with_listener_v3(struct tracecmd_msg_handle *msg_handle,
3775 unsigned int **client_ports)
3776 {
3777 if (tracecmd_msg_send_init_data(msg_handle, client_ports) < 0)
3778 die("Cannot communicate with server");
3779 }
3780
check_protocol_version(struct tracecmd_msg_handle * msg_handle)3781 static void check_protocol_version(struct tracecmd_msg_handle *msg_handle)
3782 {
3783 char buf[BUFSIZ];
3784 int fd = msg_handle->fd;
3785 int n;
3786
3787 check_first_msg_from_server(msg_handle);
3788
3789 /*
3790 * Write the protocol version, the magic number, and the dummy
3791 * option(0) (in ASCII). The client understands whether the client
3792 * uses the v3 protocol or not by checking a reply message from the
3793 * server. If the message is "V3", the server uses v3 protocol. On the
3794 * other hands, if the message is just number strings, the server
3795 * returned port numbers. So, in that time, the client understands the
3796 * server uses the v1 protocol. However, the old server tells the
3797 * client port numbers after reading cpu_count, page_size, and option.
3798 * So, we add the dummy number (the magic number and 0 option) to the
3799 * first client message.
3800 */
3801 write(fd, V3_CPU, sizeof(V3_CPU));
3802
3803 buf[0] = 0;
3804
3805 /* read a reply message */
3806 n = read(fd, buf, BUFSIZ);
3807
3808 if (n < 0 || !buf[0]) {
3809 /* the server uses the v1 protocol, so we'll use it */
3810 msg_handle->version = V1_PROTOCOL;
3811 tracecmd_plog("Use the v1 protocol\n");
3812 } else {
3813 if (memcmp(buf, "V3", n) != 0)
3814 die("Cannot handle the protocol %s", buf);
3815 /* OK, let's use v3 protocol */
3816 write(fd, V3_MAGIC, sizeof(V3_MAGIC));
3817
3818 n = read(fd, buf, BUFSIZ - 1);
3819 if (n != 2 || memcmp(buf, "OK", 2) != 0) {
3820 if (n < 0)
3821 n = 0;
3822 buf[n] = 0;
3823 die("Cannot handle the protocol %s", buf);
3824 }
3825 }
3826 }
3827
connect_vsock(char * vhost)3828 static int connect_vsock(char *vhost)
3829 {
3830 char *cid;
3831 char *port;
3832 char *p;
3833 int sd;
3834
3835 host = strdup(vhost);
3836 if (!host)
3837 die("alloctating server");
3838
3839 cid = strtok_r(host, ":", &p);
3840 port = strtok_r(NULL, "", &p);
3841
3842 if (!port)
3843 die("vsocket must have format of 'CID:PORT'");
3844
3845 sd = trace_vsock_open(atoi(cid), atoi(port));
3846
3847 return sd;
3848 }
3849
connect_ip(char * thost)3850 static int connect_ip(char *thost)
3851 {
3852 struct addrinfo *result;
3853 int sfd;
3854 char *server;
3855 char *port;
3856 char *p;
3857
3858 if (!strchr(thost, ':')) {
3859 server = strdup("localhost");
3860 if (!server)
3861 die("alloctating server");
3862 port = thost;
3863 host = server;
3864 } else {
3865 host = strdup(thost);
3866 if (!host)
3867 die("alloctating server");
3868 server = strtok_r(host, ":", &p);
3869 port = strtok_r(NULL, ":", &p);
3870 }
3871
3872 result = do_getaddrinfo(server, atoi(port), USE_TCP);
3873 if (!result)
3874 die("getaddrinfo: %s", gai_err);
3875
3876 sfd = connect_addr(result);
3877
3878 freeaddrinfo(result);
3879
3880 if (sfd < 0)
3881 die("Can not connect to %s:%s", server, port);
3882
3883 return sfd;
3884 }
3885
setup_network(struct buffer_instance * instance)3886 static struct tracecmd_msg_handle *setup_network(struct buffer_instance *instance)
3887 {
3888 struct tracecmd_msg_handle *msg_handle = NULL;
3889 enum port_type type = instance->port_type;
3890 char *thost = strdup(host);
3891 int sfd;
3892
3893 if (!thost)
3894 die("Failed to allocate host");
3895 again:
3896 switch (type) {
3897 case USE_VSOCK:
3898 sfd = connect_vsock(thost);
3899 break;
3900 default:
3901 sfd = connect_ip(thost);
3902 }
3903
3904 if (sfd < 0) {
3905 free(thost);
3906 return NULL;
3907 }
3908
3909 if (msg_handle) {
3910 msg_handle->fd = sfd;
3911 } else {
3912 msg_handle = tracecmd_msg_handle_alloc(sfd, 0);
3913 if (!msg_handle)
3914 die("Failed to allocate message handle");
3915
3916 msg_handle->cpu_count = local_cpu_count;
3917 msg_handle->version = V3_PROTOCOL;
3918 }
3919
3920 switch (type) {
3921 case USE_TCP:
3922 msg_handle->flags |= TRACECMD_MSG_FL_USE_TCP;
3923 break;
3924 case USE_VSOCK:
3925 msg_handle->flags |= TRACECMD_MSG_FL_USE_VSOCK;
3926 break;
3927 default:
3928 break;
3929 }
3930
3931 if (msg_handle->version == V3_PROTOCOL) {
3932 check_protocol_version(msg_handle);
3933 if (msg_handle->version == V1_PROTOCOL) {
3934 /* reconnect to the server for using the v1 protocol */
3935 close(sfd);
3936 free(host);
3937 host = NULL;
3938 goto again;
3939 }
3940 communicate_with_listener_v3(msg_handle, &instance->client_ports);
3941 }
3942
3943 if (msg_handle->version == V1_PROTOCOL)
3944 communicate_with_listener_v1(msg_handle, instance);
3945
3946 free(thost);
3947 return msg_handle;
3948 }
3949
3950 static void add_options(struct tracecmd_output *handle, struct common_record_context *ctx);
3951
create_net_output(struct common_record_context * ctx,struct tracecmd_msg_handle * msg_handle)3952 static struct tracecmd_output *create_net_output(struct common_record_context *ctx,
3953 struct tracecmd_msg_handle *msg_handle)
3954 {
3955 struct tracecmd_output *out;
3956
3957 out = tracecmd_output_create(NULL);
3958 if (!out)
3959 return NULL;
3960 if (ctx->file_version && tracecmd_output_set_version(out, ctx->file_version))
3961 goto error;
3962 if (tracecmd_output_set_msg(out, msg_handle))
3963 goto error;
3964
3965 if (ctx->compression) {
3966 if (tracecmd_output_set_compression(out, ctx->compression))
3967 goto error;
3968 } else if (ctx->file_version >= FILE_VERSION_COMPRESSION) {
3969 tracecmd_output_set_compression(out, "any");
3970 }
3971
3972 if (tracecmd_output_write_headers(out, listed_events))
3973 goto error;
3974
3975 return out;
3976 error:
3977 tracecmd_output_close(out);
3978 return NULL;
3979 }
3980
3981 static struct tracecmd_msg_handle *
setup_connection(struct buffer_instance * instance,struct common_record_context * ctx)3982 setup_connection(struct buffer_instance *instance, struct common_record_context *ctx)
3983 {
3984 struct tracecmd_msg_handle *msg_handle = NULL;
3985 struct tracecmd_output *network_handle = NULL;
3986 int ret;
3987
3988 msg_handle = setup_network(instance);
3989 if (!msg_handle)
3990 die("Failed to make connection");
3991
3992 /* Now create the handle through this socket */
3993 if (msg_handle->version == V3_PROTOCOL) {
3994 network_handle = create_net_output(ctx, msg_handle);
3995 if (!network_handle)
3996 goto error;
3997 tracecmd_set_quiet(network_handle, quiet);
3998 add_options(network_handle, ctx);
3999 ret = tracecmd_write_cmdlines(network_handle);
4000 if (ret)
4001 goto error;
4002 ret = tracecmd_write_cpus(network_handle, instance->cpu_count);
4003 if (ret)
4004 goto error;
4005 ret = tracecmd_write_buffer_info(network_handle);
4006 if (ret)
4007 goto error;
4008 ret = tracecmd_write_options(network_handle);
4009 if (ret)
4010 goto error;
4011 ret = tracecmd_msg_finish_sending_data(msg_handle);
4012 if (ret)
4013 goto error;
4014 } else {
4015 /*
4016 * V3 can handle compression, but V1 can not.
4017 * Set the file version back to 6.
4018 */
4019 ctx->file_version = FILE_VERSION_MIN;
4020 ctx->compression = false;
4021 network_handle = tracecmd_output_create_fd(msg_handle->fd);
4022 if (!network_handle)
4023 goto error;
4024 if (tracecmd_output_set_version(network_handle, ctx->file_version))
4025 goto error;
4026
4027 if (tracecmd_output_write_headers(network_handle, listed_events))
4028 goto error;
4029 tracecmd_set_quiet(network_handle, quiet);
4030 }
4031
4032 instance->network_handle = network_handle;
4033
4034 /* OK, we are all set, let'r rip! */
4035 return msg_handle;
4036
4037 error:
4038 if (msg_handle)
4039 tracecmd_msg_handle_close(msg_handle);
4040 if (network_handle)
4041 tracecmd_output_close(network_handle);
4042 return NULL;
4043 }
4044
finish_network(struct tracecmd_msg_handle * msg_handle)4045 static void finish_network(struct tracecmd_msg_handle *msg_handle)
4046 {
4047 if (msg_handle->version == V3_PROTOCOL)
4048 tracecmd_msg_send_close_msg(msg_handle);
4049 tracecmd_msg_handle_close(msg_handle);
4050 free(host);
4051 }
4052
open_guest_fifos(const char * guest,int ** fds)4053 static int open_guest_fifos(const char *guest, int **fds)
4054 {
4055 char path[PATH_MAX];
4056 int i, fd, flags;
4057
4058 for (i = 0; ; i++) {
4059 snprintf(path, sizeof(path), GUEST_FIFO_FMT ".out", guest, i);
4060
4061 /* O_NONBLOCK so we don't wait for writers */
4062 fd = open(path, O_RDONLY | O_NONBLOCK);
4063 if (fd < 0)
4064 break;
4065
4066 /* Success, now clear O_NONBLOCK */
4067 flags = fcntl(fd, F_GETFL);
4068 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
4069
4070 *fds = realloc(*fds, i + 1);
4071 (*fds)[i] = fd;
4072 }
4073
4074 return i;
4075 }
4076
4077 static bool clock_is_supported(struct tracefs_instance *instance, const char *clock);
4078
host_tsync(struct common_record_context * ctx,struct buffer_instance * instance,unsigned int tsync_port,char * proto)4079 static int host_tsync(struct common_record_context *ctx,
4080 struct buffer_instance *instance,
4081 unsigned int tsync_port, char *proto)
4082 {
4083 struct buffer_instance *iter_instance;
4084 int guest_id = -1;
4085 int fd;
4086
4087 if (!proto)
4088 return -1;
4089
4090 /* If connecting to a proxy, the clock may still need to be set */
4091 if (strcmp(proto, "kvm") == 0 &&
4092 clock_is_supported(NULL, TSC_CLOCK)) {
4093 ctx->clock = TSC_CLOCK;
4094 for_all_instances(iter_instance) {
4095 iter_instance->clock = TSC_CLOCK;
4096 set_clock(ctx, iter_instance);
4097 }
4098 }
4099
4100 if (is_network(instance)) {
4101 fd = connect_port(instance->name, tsync_port,
4102 instance->port_type);
4103 } else {
4104 guest_id = instance->cid;
4105 fd = trace_vsock_open(instance->cid, tsync_port);
4106 }
4107
4108 if (is_proxy(instance)) {
4109 instance->tsync = trace_tsync_as_guest(fd, proto, ctx->clock,
4110 guest_id, -1);
4111 } else {
4112 instance->tsync = trace_tsync_as_host(fd, top_instance.trace_id,
4113 instance->tsync_loop_interval,
4114 guest_id, instance->cpu_count,
4115 proto, ctx->clock);
4116 }
4117 return instance->tsync ? 0 : -1;
4118 }
4119
connect_to_agent(struct common_record_context * ctx,struct buffer_instance * instance)4120 static void connect_to_agent(struct common_record_context *ctx,
4121 struct buffer_instance *instance)
4122 {
4123 struct tracecmd_tsync_protos *protos = NULL;
4124 int sd, ret, nr_fifos, nr_cpus, page_size;
4125 struct tracecmd_msg_handle *msg_handle;
4126 enum tracecmd_time_sync_role role;
4127 char *tsync_protos_reply = NULL;
4128 unsigned int tsync_port = 0;
4129 unsigned int *ports;
4130 int i, *fds = NULL;
4131 bool use_fifos = false;
4132 int siblings = 0;
4133
4134 if (!no_fifos) {
4135 nr_fifos = open_guest_fifos(instance->name, &fds);
4136 use_fifos = nr_fifos > 0;
4137 }
4138
4139 if (instance->result) {
4140 role = TRACECMD_TIME_SYNC_ROLE_CLIENT;
4141 sd = connect_addr(instance->result);
4142 if (sd < 0)
4143 die("Failed to connect to host %s:%u",
4144 instance->name, instance->port);
4145 } else {
4146 /* If connecting to a proxy, then this is the guest */
4147 if (is_proxy(instance))
4148 role = TRACECMD_TIME_SYNC_ROLE_GUEST;
4149 else
4150 role = TRACECMD_TIME_SYNC_ROLE_HOST;
4151 sd = trace_vsock_open(instance->cid, instance->port);
4152 if (sd < 0)
4153 die("Failed to connect to vsocket @%u:%u",
4154 instance->cid, instance->port);
4155 }
4156
4157 msg_handle = tracecmd_msg_handle_alloc(sd, 0);
4158 if (!msg_handle)
4159 die("Failed to allocate message handle");
4160
4161 if (!instance->clock)
4162 instance->clock = tracefs_get_clock(NULL);
4163
4164 if (instance->tsync_loop_interval >= 0)
4165 tracecmd_tsync_proto_getall(&protos, instance->clock, role);
4166
4167 if (is_proxy(instance))
4168 ret = tracecmd_msg_send_trace_proxy(msg_handle, instance->argc,
4169 instance->argv, use_fifos,
4170 top_instance.trace_id, protos,
4171 tracecmd_count_cpus(),
4172 siblings);
4173 else
4174 ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc,
4175 instance->argv, use_fifos,
4176 top_instance.trace_id, protos);
4177 if (ret < 0)
4178 die("Failed to send trace %s",
4179 is_proxy(instance) ? "proxy" : "request");
4180
4181 if (protos) {
4182 free(protos->names);
4183 free(protos);
4184 }
4185 ret = tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size,
4186 &ports, &use_fifos,
4187 &instance->trace_id,
4188 &tsync_protos_reply, &tsync_port);
4189 if (ret < 0)
4190 die("Failed to receive trace response %d", ret);
4191 if (tsync_protos_reply && tsync_protos_reply[0]) {
4192 if (tsync_proto_is_supported(tsync_protos_reply)) {
4193 printf("Negotiated %s time sync protocol with guest %s\n",
4194 tsync_protos_reply,
4195 instance->name);
4196 instance->cpu_count = nr_cpus;
4197 host_tsync(ctx, instance, tsync_port, tsync_protos_reply);
4198 } else
4199 warning("Failed to negotiate timestamps synchronization with the guest");
4200 }
4201 free(tsync_protos_reply);
4202
4203 if (use_fifos) {
4204 if (nr_cpus != nr_fifos) {
4205 warning("number of FIFOs (%d) for guest %s differs "
4206 "from number of virtual CPUs (%d)",
4207 nr_fifos, instance->name, nr_cpus);
4208 nr_cpus = nr_cpus < nr_fifos ? nr_cpus : nr_fifos;
4209 }
4210 free(ports);
4211 instance->fds = fds;
4212 } else {
4213 for (i = 0; i < nr_fifos; i++)
4214 close(fds[i]);
4215 free(fds);
4216 instance->client_ports = ports;
4217 }
4218
4219 instance->use_fifos = use_fifos;
4220 instance->cpu_count = nr_cpus;
4221
4222 /* the msg_handle now points to the guest fd */
4223 instance->msg_handle = msg_handle;
4224 }
4225
setup_guest(struct buffer_instance * instance)4226 static void setup_guest(struct buffer_instance *instance)
4227 {
4228 struct tracecmd_msg_handle *msg_handle = instance->msg_handle;
4229 const char *output_file = instance->output_file;
4230 char *file;
4231 int fd;
4232
4233 /* Create a place to store the guest meta data */
4234 file = trace_get_guest_file(output_file, instance->name);
4235 if (!file)
4236 die("Failed to allocate memory");
4237
4238 free(instance->output_file);
4239 instance->output_file = file;
4240
4241 fd = open(file, O_CREAT|O_WRONLY|O_TRUNC, 0644);
4242 if (fd < 0)
4243 die("Failed to open %s", file);
4244
4245 /* Start reading tracing metadata */
4246 if (tracecmd_msg_read_data(msg_handle, fd))
4247 die("Failed receiving metadata");
4248
4249 /*
4250 * If connected to a proxy, then it still needs to send
4251 * the host / guest timings from its POV.
4252 */
4253 if (is_proxy(instance))
4254 instance->proxy_fd = fd;
4255 else
4256 close(fd);
4257 }
4258
setup_agent(struct buffer_instance * instance,struct common_record_context * ctx)4259 static void setup_agent(struct buffer_instance *instance,
4260 struct common_record_context *ctx)
4261 {
4262 struct tracecmd_output *network_handle;
4263
4264 network_handle = create_net_output(ctx, instance->msg_handle);
4265 add_options(network_handle, ctx);
4266 tracecmd_write_cmdlines(network_handle);
4267 tracecmd_write_cpus(network_handle, instance->cpu_count);
4268 tracecmd_write_buffer_info(network_handle);
4269 if (instance->msg_handle->flags & TRACECMD_MSG_FL_PROXY) {
4270 tracecmd_prepare_options(network_handle, 0, SEEK_CUR);
4271 tracecmd_msg_flush_data(instance->msg_handle);
4272 } else {
4273 tracecmd_write_options(network_handle);
4274 tracecmd_write_meta_strings(network_handle);
4275 tracecmd_msg_finish_sending_data(instance->msg_handle);
4276 }
4277 instance->network_handle = network_handle;
4278 }
4279
start_threads(enum trace_type type,struct common_record_context * ctx)4280 static void start_threads(enum trace_type type, struct common_record_context *ctx)
4281 {
4282 struct buffer_instance *instance;
4283 int total_cpu_count = 0;
4284 int i = 0;
4285 int ret;
4286
4287 for_all_instances(instance) {
4288 /* Start the connection now to find out how many CPUs we need */
4289 if (is_guest(instance))
4290 connect_to_agent(ctx, instance);
4291 total_cpu_count += instance->cpu_count;
4292 }
4293
4294 /* make a thread for every CPU we have */
4295 pids = calloc(total_cpu_count * (buffers + 1), sizeof(*pids));
4296 if (!pids)
4297 die("Failed to allocate pids for %d cpus", total_cpu_count);
4298
4299 for_all_instances(instance) {
4300 int *brass = NULL;
4301 int x, pid;
4302
4303 /* May be set by setup_guest() but all others is -1 */
4304 instance->proxy_fd = -1;
4305
4306 if (is_agent(instance)) {
4307 setup_agent(instance, ctx);
4308 } else if (is_guest(instance)) {
4309 setup_guest(instance);
4310 } else if (host) {
4311 instance->msg_handle = setup_connection(instance, ctx);
4312 if (!instance->msg_handle)
4313 die("Failed to make connection");
4314 }
4315
4316 for (x = 0; x < instance->cpu_count; x++) {
4317 if (type & TRACE_TYPE_STREAM) {
4318 brass = pids[i].brass;
4319 ret = pipe(brass);
4320 if (ret < 0)
4321 die("pipe");
4322 pids[i].stream = trace_stream_init(instance, x,
4323 brass[0],
4324 instance->cpu_count,
4325 hooks, handle_init,
4326 ctx->global);
4327 if (!pids[i].stream)
4328 die("Creating stream for %d", i);
4329 } else
4330 pids[i].brass[0] = -1;
4331 pids[i].cpu = x;
4332 pids[i].instance = instance;
4333 /* Make sure all output is flushed before forking */
4334 fflush(stdout);
4335 pid = pids[i++].pid = create_recorder(instance, x, type, brass);
4336 if (brass)
4337 close(brass[1]);
4338 if (pid > 0)
4339 add_filter_pid(instance, pid, 1);
4340 }
4341 }
4342 recorder_threads = i;
4343 }
4344
touch_file(const char * file)4345 static void touch_file(const char *file)
4346 {
4347 int fd;
4348
4349 fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
4350 if (fd < 0)
4351 die("could not create file %s\n", file);
4352 close(fd);
4353 }
4354
append_buffer(struct tracecmd_output * handle,struct buffer_instance * instance,char ** temp_files)4355 static void append_buffer(struct tracecmd_output *handle,
4356 struct buffer_instance *instance,
4357 char **temp_files)
4358 {
4359 int cpu_count = instance->cpu_count;
4360 int i;
4361
4362 /*
4363 * Since we can record remote and virtual machines in the same file
4364 * as the host, the buffers may no longer have matching number of
4365 * CPU data as the host. For backward compatibility for older
4366 * trace-cmd versions, which will blindly read the number of CPUs
4367 * for each buffer instance as there are for the host, if there are
4368 * fewer CPUs on the remote machine than on the host, an "empty"
4369 * CPU is needed for each CPU that the host has that the remote does
4370 * not. If there are more CPUs on the remote, older executables will
4371 * simply ignore them (which is OK, we only need to guarantee that
4372 * old executables don't crash).
4373 */
4374 if (instance->cpu_count < local_cpu_count)
4375 cpu_count = local_cpu_count;
4376
4377 for (i = 0; i < cpu_count; i++) {
4378 temp_files[i] = get_temp_file(instance, i);
4379 if (i >= instance->cpu_count)
4380 touch_file(temp_files[i]);
4381 }
4382
4383 tracecmd_append_buffer_cpu_data(handle, tracefs_instance_get_name(instance->tracefs),
4384 cpu_count, temp_files);
4385
4386 for (i = 0; i < instance->cpu_count; i++) {
4387 if (i >= instance->cpu_count)
4388 delete_temp_file(instance, i);
4389 put_temp_file(temp_files[i]);
4390 }
4391 }
4392
4393 static void
add_pid_maps(struct tracecmd_output * handle,struct buffer_instance * instance)4394 add_pid_maps(struct tracecmd_output *handle, struct buffer_instance *instance)
4395 {
4396 struct pid_addr_maps *maps = instance->pid_maps;
4397 struct trace_seq s;
4398 int i;
4399
4400 trace_seq_init(&s);
4401 while (maps) {
4402 if (!maps->nr_lib_maps) {
4403 maps = maps->next;
4404 continue;
4405 }
4406 trace_seq_reset(&s);
4407 trace_seq_printf(&s, "%x %x %s\n",
4408 maps->pid, maps->nr_lib_maps, maps->proc_name);
4409 for (i = 0; i < maps->nr_lib_maps; i++)
4410 trace_seq_printf(&s, "%zx %zx %s\n",
4411 maps->lib_maps[i].start,
4412 maps->lib_maps[i].end,
4413 maps->lib_maps[i].lib_name);
4414 trace_seq_terminate(&s);
4415 tracecmd_add_option(handle, TRACECMD_OPTION_PROCMAPS,
4416 s.len + 1, s.buffer);
4417 maps = maps->next;
4418 }
4419 trace_seq_destroy(&s);
4420 }
4421
4422 static void
add_trace_id(struct tracecmd_output * handle,struct buffer_instance * instance)4423 add_trace_id(struct tracecmd_output *handle, struct buffer_instance *instance)
4424 {
4425 tracecmd_add_option(handle, TRACECMD_OPTION_TRACEID,
4426 sizeof(long long), &instance->trace_id);
4427 }
4428
4429 static void
add_buffer_stat(struct tracecmd_output * handle,struct buffer_instance * instance)4430 add_buffer_stat(struct tracecmd_output *handle, struct buffer_instance *instance)
4431 {
4432 struct trace_seq s;
4433 int i;
4434
4435 trace_seq_init(&s);
4436 trace_seq_printf(&s, "\nBuffer: %s\n\n",
4437 tracefs_instance_get_name(instance->tracefs));
4438 tracecmd_add_option(handle, TRACECMD_OPTION_CPUSTAT,
4439 s.len+1, s.buffer);
4440 trace_seq_destroy(&s);
4441
4442 for (i = 0; i < instance->cpu_count; i++)
4443 tracecmd_add_option(handle, TRACECMD_OPTION_CPUSTAT,
4444 instance->s_save[i].len+1,
4445 instance->s_save[i].buffer);
4446 }
4447
add_option_hooks(struct tracecmd_output * handle)4448 static void add_option_hooks(struct tracecmd_output *handle)
4449 {
4450 struct hook_list *hook;
4451 int len;
4452
4453 for (hook = hooks; hook; hook = hook->next) {
4454 len = strlen(hook->hook);
4455 tracecmd_add_option(handle, TRACECMD_OPTION_HOOK,
4456 len + 1, hook->hook);
4457 }
4458 }
4459
add_uname(struct tracecmd_output * handle)4460 static void add_uname(struct tracecmd_output *handle)
4461 {
4462 struct utsname buf;
4463 char *str;
4464 int len;
4465 int ret;
4466
4467 ret = uname(&buf);
4468 /* if this fails for some reason, just ignore it */
4469 if (ret < 0)
4470 return;
4471
4472 len = strlen(buf.sysname) + strlen(buf.nodename) +
4473 strlen(buf.release) + strlen(buf.machine) + 4;
4474 str = malloc(len);
4475 if (!str)
4476 return;
4477 sprintf(str, "%s %s %s %s", buf.sysname, buf.nodename, buf.release, buf.machine);
4478 tracecmd_add_option(handle, TRACECMD_OPTION_UNAME, len, str);
4479 free(str);
4480 }
4481
add_version(struct tracecmd_output * handle)4482 static void add_version(struct tracecmd_output *handle)
4483 {
4484 char *str;
4485 int len;
4486
4487 len = asprintf(&str, "%s %s", VERSION_STRING, VERSION_GIT);
4488 if (len < 0)
4489 return;
4490
4491 tracecmd_add_option(handle, TRACECMD_OPTION_VERSION, len+1, str);
4492 free(str);
4493 }
4494
print_stat(struct buffer_instance * instance)4495 static void print_stat(struct buffer_instance *instance)
4496 {
4497 int cpu;
4498
4499 if (quiet)
4500 return;
4501
4502 if (!is_top_instance(instance))
4503 printf("\nBuffer: %s\n\n",
4504 tracefs_instance_get_name(instance->tracefs));
4505
4506 for (cpu = 0; cpu < instance->cpu_count; cpu++)
4507 trace_seq_do_printf(&instance->s_print[cpu]);
4508 }
4509
get_trace_clock(bool selected)4510 static char *get_trace_clock(bool selected)
4511 {
4512 struct buffer_instance *instance;
4513
4514 for_all_instances(instance) {
4515 if (is_guest(instance))
4516 continue;
4517 break;
4518 }
4519
4520 if (selected)
4521 return tracefs_get_clock(instance ? instance->tracefs : NULL);
4522 else
4523 return tracefs_instance_file_read(instance ? instance->tracefs : NULL,
4524 "trace_clock", NULL);
4525 }
4526
4527 enum {
4528 DATA_FL_NONE = 0,
4529 DATA_FL_DATE = 1,
4530 DATA_FL_OFFSET = 2,
4531 DATA_FL_GUEST = 4,
4532 DATA_FL_PROXY = 8,
4533 };
4534
add_options(struct tracecmd_output * handle,struct common_record_context * ctx)4535 static void add_options(struct tracecmd_output *handle, struct common_record_context *ctx)
4536 {
4537 int type = 0;
4538 char *clocks;
4539
4540 if (ctx->date2ts) {
4541 if (ctx->data_flags & DATA_FL_DATE)
4542 type = TRACECMD_OPTION_DATE;
4543 else if (ctx->data_flags & DATA_FL_OFFSET)
4544 type = TRACECMD_OPTION_OFFSET;
4545 }
4546
4547 if (type)
4548 tracecmd_add_option(handle, type, strlen(ctx->date2ts)+1, ctx->date2ts);
4549
4550 clocks = get_trace_clock(false);
4551 tracecmd_add_option(handle, TRACECMD_OPTION_TRACECLOCK,
4552 clocks ? strlen(clocks)+1 : 0, clocks);
4553 add_option_hooks(handle);
4554 add_uname(handle);
4555 add_version(handle);
4556 if (!no_top_instance())
4557 add_trace_id(handle, &top_instance);
4558 free(clocks);
4559 }
4560
write_guest_file(struct buffer_instance * instance)4561 static void write_guest_file(struct buffer_instance *instance)
4562 {
4563 struct tracecmd_output *handle;
4564 int cpu_count = instance->cpu_count;
4565 char *file;
4566 char **temp_files;
4567 int i, fd;
4568
4569 file = instance->output_file;
4570 fd = open(file, O_RDWR);
4571 if (fd < 0)
4572 die("error opening %s", file);
4573
4574 handle = tracecmd_get_output_handle_fd(fd);
4575 if (!handle)
4576 die("error writing to %s", file);
4577 if (instance->flags & BUFFER_FL_TSC2NSEC)
4578 tracecmd_set_out_clock(handle, TSCNSEC_CLOCK);
4579 temp_files = malloc(sizeof(*temp_files) * cpu_count);
4580 if (!temp_files)
4581 die("failed to allocate temp_files for %d cpus",
4582 cpu_count);
4583
4584 for (i = 0; i < cpu_count; i++) {
4585 temp_files[i] = get_temp_file(instance, i);
4586 if (!temp_files[i])
4587 die("failed to allocate memory");
4588 }
4589
4590 if (tracecmd_write_cpu_data(handle, cpu_count, temp_files, NULL) < 0)
4591 die("failed to write CPU data");
4592 tracecmd_output_close(handle);
4593
4594 for (i = 0; i < cpu_count; i++)
4595 put_temp_file(temp_files[i]);
4596 free(temp_files);
4597 }
4598
create_output(struct common_record_context * ctx)4599 static struct tracecmd_output *create_output(struct common_record_context *ctx)
4600 {
4601 struct tracecmd_output *out;
4602
4603 if (!ctx->output)
4604 return NULL;
4605
4606 out = tracecmd_output_create(ctx->output);
4607 if (!out)
4608 goto error;
4609 if (ctx->file_version && tracecmd_output_set_version(out, ctx->file_version))
4610 goto error;
4611
4612 if (ctx->compression) {
4613 if (tracecmd_output_set_compression(out, ctx->compression))
4614 goto error;
4615 } else if (ctx->file_version >= FILE_VERSION_COMPRESSION) {
4616 tracecmd_output_set_compression(out, "any");
4617 }
4618
4619 if (tracecmd_output_write_headers(out, listed_events))
4620 goto error;
4621
4622 return out;
4623 error:
4624 if (out)
4625 tracecmd_output_close(out);
4626 unlink(ctx->output);
4627 return NULL;
4628 }
4629
record_data(struct common_record_context * ctx)4630 static void record_data(struct common_record_context *ctx)
4631 {
4632 struct tracecmd_output *handle;
4633 struct buffer_instance *instance;
4634 bool have_proxy = false;
4635 bool local = false;
4636 int max_cpu_count = local_cpu_count;
4637 char **temp_files;
4638 int i;
4639
4640 for_all_instances(instance) {
4641 if (is_guest(instance)) {
4642 write_guest_file(instance);
4643 if (is_proxy(instance))
4644 have_proxy = true;
4645 } else if (host && instance->msg_handle)
4646 finish_network(instance->msg_handle);
4647 else
4648 local = true;
4649 }
4650
4651 if (!local)
4652 return;
4653
4654 if (latency) {
4655 handle = tracecmd_create_file_latency(ctx->output, local_cpu_count,
4656 ctx->file_version, ctx->compression);
4657 tracecmd_set_quiet(handle, quiet);
4658 } else {
4659 if (!local_cpu_count)
4660 return;
4661
4662 /* Allocate enough temp files to handle each instance */
4663 for_all_instances(instance) {
4664 if (instance->msg_handle)
4665 continue;
4666 if (instance->cpu_count > max_cpu_count)
4667 max_cpu_count = instance->cpu_count;
4668 }
4669
4670 temp_files = malloc(sizeof(*temp_files) * max_cpu_count);
4671 if (!temp_files)
4672 die("Failed to allocate temp_files for %d cpus",
4673 local_cpu_count);
4674
4675 for (i = 0; i < max_cpu_count; i++)
4676 temp_files[i] = get_temp_file(&top_instance, i);
4677
4678 /*
4679 * If top_instance was not used, we still need to create
4680 * empty trace.dat files for it.
4681 */
4682 if (no_top_instance() || top_instance.msg_handle) {
4683 for (i = 0; i < local_cpu_count; i++)
4684 touch_file(temp_files[i]);
4685 }
4686
4687 handle = create_output(ctx);
4688 if (!handle)
4689 die("Error creating output file");
4690 tracecmd_set_quiet(handle, quiet);
4691
4692 add_options(handle, ctx);
4693
4694 /*
4695 * If we connected to a proxy, then it will now send us
4696 * the tsync data for our file.
4697 */
4698 if (have_proxy) {
4699 for_all_instances(instance) {
4700 if (!is_proxy(instance))
4701 continue;
4702 /* Tell proxy we are ready for the rest */
4703 tracecmd_msg_cont(instance->msg_handle);
4704 tracecmd_msg_read_options(instance->msg_handle, handle);
4705 tracecmd_msg_wait_close_resp(instance->msg_handle);
4706 tracecmd_msg_handle_close(instance->msg_handle);
4707 }
4708 }
4709
4710 /* Only record the top instance under TRACECMD_OPTION_CPUSTAT*/
4711 if (!no_top_instance() && !top_instance.msg_handle) {
4712 struct trace_seq *s = top_instance.s_save;
4713
4714 for (i = 0; i < local_cpu_count; i++)
4715 tracecmd_add_option(handle, TRACECMD_OPTION_CPUSTAT,
4716 s[i].len+1, s[i].buffer);
4717 }
4718
4719 if (buffers) {
4720 i = 0;
4721 for_each_instance(instance) {
4722 int cpus = instance->cpu_count != local_cpu_count ?
4723 instance->cpu_count : 0;
4724
4725 if (instance->msg_handle)
4726 continue;
4727 tracecmd_add_buffer_info(handle,
4728 tracefs_instance_get_name(instance->tracefs),
4729 cpus);
4730 add_buffer_stat(handle, instance);
4731 }
4732 }
4733
4734 if (!no_top_instance() && !top_instance.msg_handle)
4735 print_stat(&top_instance);
4736
4737 for_all_instances(instance) {
4738 add_pid_maps(handle, instance);
4739 }
4740
4741 for_all_instances(instance) {
4742 if (is_guest(instance))
4743 trace_add_guest_info(handle, instance);
4744 }
4745
4746 if (ctx->tsc2nsec.mult) {
4747 add_tsc2nsec(handle, &ctx->tsc2nsec);
4748 tracecmd_set_out_clock(handle, TSCNSEC_CLOCK);
4749 }
4750 if (tracecmd_write_cmdlines(handle))
4751 die("Writing cmdlines");
4752
4753 tracecmd_append_cpu_data(handle, local_cpu_count, temp_files);
4754
4755 for (i = 0; i < max_cpu_count; i++)
4756 put_temp_file(temp_files[i]);
4757
4758 if (buffers) {
4759 i = 0;
4760 for_each_instance(instance) {
4761 if (instance->msg_handle)
4762 continue;
4763 print_stat(instance);
4764 append_buffer(handle, instance, temp_files);
4765 }
4766 }
4767
4768 free(temp_files);
4769 }
4770 if (!handle)
4771 die("could not write to file");
4772 tracecmd_output_close(handle);
4773 }
4774
4775 enum filter_type {
4776 FUNC_FILTER,
4777 FUNC_NOTRACE,
4778 };
4779
filter_command(struct tracefs_instance * instance,const char * cmd)4780 static int filter_command(struct tracefs_instance *instance, const char *cmd)
4781 {
4782 return tracefs_instance_file_append(instance, "set_ftrace_filter", cmd);
4783 }
4784
write_func_filter(enum filter_type type,struct buffer_instance * instance,struct func_list ** list)4785 static int write_func_filter(enum filter_type type, struct buffer_instance *instance,
4786 struct func_list **list)
4787 {
4788 struct func_list *item, *cmds = NULL;
4789 const char *file;
4790 int ret = -1;
4791 int (*filter_function)(struct tracefs_instance *instance, const char *filter,
4792 const char *module, unsigned int flags);
4793
4794 if (!*list)
4795 return 0;
4796
4797 switch (type) {
4798 case FUNC_FILTER:
4799 filter_function = tracefs_function_filter;
4800 file = "set_ftrace_filter";
4801 break;
4802 case FUNC_NOTRACE:
4803 filter_function = tracefs_function_notrace;
4804 file = "set_ftrace_notrace";
4805 break;
4806 }
4807
4808 ret = filter_function(instance->tracefs, NULL, NULL,
4809 TRACEFS_FL_RESET | TRACEFS_FL_CONTINUE);
4810 if (ret < 0)
4811 return ret;
4812
4813 while (*list) {
4814 item = *list;
4815 *list = item->next;
4816 /* Do commands separately at the end */
4817 if (type == FUNC_FILTER && strstr(item->func, ":")) {
4818 item->next = cmds;
4819 cmds = item;
4820 continue;
4821 }
4822 ret = filter_function(instance->tracefs, item->func, item->mod,
4823 TRACEFS_FL_CONTINUE);
4824 if (ret < 0)
4825 goto failed;
4826 free(item);
4827 }
4828 ret = filter_function(instance->tracefs, NULL, NULL, 0);
4829
4830 /* Now add any commands */
4831 while (cmds) {
4832 item = cmds;
4833 cmds = item->next;
4834 ret = filter_command(instance->tracefs, item->func);
4835 if (ret < 0)
4836 goto failed;
4837 free(item);
4838 }
4839 return ret;
4840 failed:
4841 die("Failed to write %s to %s.\n"
4842 "Perhaps this function is not available for tracing.\n"
4843 "run 'trace-cmd list -f %s' to see if it is.",
4844 item->func, file, item->func);
4845 return ret;
4846 }
4847
write_func_file(struct buffer_instance * instance,const char * file,struct func_list ** list)4848 static int write_func_file(struct buffer_instance *instance,
4849 const char *file, struct func_list **list)
4850 {
4851 struct func_list *item;
4852 const char *prefix = ":mod:";
4853 char *path;
4854 int fd;
4855 int ret = -1;
4856
4857 if (!*list)
4858 return 0;
4859
4860 path = tracefs_instance_get_file(instance->tracefs, file);
4861
4862 fd = open(path, O_WRONLY | O_TRUNC);
4863 if (fd < 0)
4864 goto free;
4865
4866 while (*list) {
4867 item = *list;
4868 *list = item->next;
4869 ret = write(fd, item->func, strlen(item->func));
4870 if (ret < 0)
4871 goto failed;
4872 if (item->mod) {
4873 ret = write(fd, prefix, strlen(prefix));
4874 if (ret < 0)
4875 goto failed;
4876 ret = write(fd, item->mod, strlen(item->mod));
4877 if (ret < 0)
4878 goto failed;
4879 }
4880 ret = write(fd, " ", 1);
4881 if (ret < 0)
4882 goto failed;
4883 free(item);
4884 }
4885 close(fd);
4886 ret = 0;
4887 free:
4888 tracefs_put_tracing_file(path);
4889 return ret;
4890 failed:
4891 die("Failed to write %s to %s.\n"
4892 "Perhaps this function is not available for tracing.\n"
4893 "run 'trace-cmd list -f %s' to see if it is.",
4894 item->func, file, item->func);
4895 return ret;
4896 }
4897
functions_filtered(struct buffer_instance * instance)4898 static int functions_filtered(struct buffer_instance *instance)
4899 {
4900 char buf[1] = { '#' };
4901 char *path;
4902 int fd;
4903
4904 path = tracefs_instance_get_file(instance->tracefs, "set_ftrace_filter");
4905 fd = open(path, O_RDONLY);
4906 tracefs_put_tracing_file(path);
4907 if (fd < 0) {
4908 if (is_top_instance(instance))
4909 warning("Can not set set_ftrace_filter");
4910 else
4911 warning("Can not set set_ftrace_filter for %s",
4912 tracefs_instance_get_name(instance->tracefs));
4913 return 0;
4914 }
4915
4916 /*
4917 * If functions are not filtered, than the first character
4918 * will be '#'. Make sure it is not an '#' and also not space.
4919 */
4920 read(fd, buf, 1);
4921 close(fd);
4922
4923 if (buf[0] == '#' || isspace(buf[0]))
4924 return 0;
4925 return 1;
4926 }
4927
set_funcs(struct buffer_instance * instance)4928 static void set_funcs(struct buffer_instance *instance)
4929 {
4930 int set_notrace = 0;
4931 int ret;
4932
4933 if (is_guest(instance))
4934 return;
4935
4936 ret = write_func_filter(FUNC_FILTER, instance, &instance->filter_funcs);
4937 if (ret < 0)
4938 die("set_ftrace_filter does not exist. Can not filter functions");
4939
4940 /* graph tracing currently only works for top instance */
4941 if (is_top_instance(instance)) {
4942 ret = write_func_file(instance, "set_graph_function", &graph_funcs);
4943 if (ret < 0)
4944 die("set_graph_function does not exist.");
4945 if (instance->plugin && strcmp(instance->plugin, "function_graph") == 0) {
4946 ret = write_func_file(instance, "set_graph_notrace",
4947 &instance->notrace_funcs);
4948 if (!ret)
4949 set_notrace = 1;
4950 }
4951 if (!set_notrace) {
4952 ret = write_func_filter(FUNC_NOTRACE, instance,
4953 &instance->notrace_funcs);
4954 if (ret < 0)
4955 die("set_ftrace_notrace does not exist. Can not filter functions");
4956 }
4957 } else
4958 write_func_filter(FUNC_NOTRACE, instance, &instance->notrace_funcs);
4959
4960 /* make sure we are filtering functions */
4961 if (func_stack && is_top_instance(instance)) {
4962 if (!functions_filtered(instance))
4963 die("Function stack trace set, but functions not filtered");
4964 save_option(instance, FUNC_STACK_TRACE);
4965 }
4966 clear_function_filters = 1;
4967 }
4968
add_func(struct func_list ** list,const char * mod,const char * func)4969 static void add_func(struct func_list **list, const char *mod, const char *func)
4970 {
4971 struct func_list *item;
4972
4973 item = malloc(sizeof(*item));
4974 if (!item)
4975 die("Failed to allocate function descriptor");
4976 item->func = func;
4977 item->mod = mod;
4978 item->next = *list;
4979 *list = item;
4980 }
4981
find_ts(struct tep_event * event,struct tep_record * record,int cpu,void * context)4982 static int find_ts(struct tep_event *event, struct tep_record *record,
4983 int cpu, void *context)
4984 {
4985 unsigned long long *ts = (unsigned long long *)context;
4986 struct tep_format_field *field;
4987
4988 if (!ts)
4989 return -1;
4990
4991 field = tep_find_field(event, "buf");
4992 if (field && strcmp(STAMP"\n", record->data + field->offset) == 0) {
4993 *ts = record->ts;
4994 return 1;
4995 }
4996
4997 return 0;
4998 }
4999
find_time_stamp(struct tep_handle * tep,struct tracefs_instance * instance)5000 static unsigned long long find_time_stamp(struct tep_handle *tep,
5001 struct tracefs_instance *instance)
5002 {
5003 unsigned long long ts = 0;
5004
5005 if (!tracefs_iterate_raw_events(tep, instance, NULL, 0, find_ts, &ts))
5006 return ts;
5007
5008 return 0;
5009 }
5010
5011
read_top_file(char * file,int * psize)5012 static char *read_top_file(char *file, int *psize)
5013 {
5014 return tracefs_instance_file_read(top_instance.tracefs, file, psize);
5015 }
5016
get_ftrace_tep(void)5017 static struct tep_handle *get_ftrace_tep(void)
5018 {
5019 const char *systems[] = {"ftrace", NULL};
5020 struct tep_handle *tep;
5021 char *buf;
5022 int size;
5023 int ret;
5024
5025 tep = tracefs_local_events_system(NULL, systems);
5026 if (!tep)
5027 return NULL;
5028 tep_set_file_bigendian(tep, tracecmd_host_bigendian());
5029 buf = read_top_file("events/header_page", &size);
5030 if (!buf)
5031 goto error;
5032 ret = tep_parse_header_page(tep, buf, size, sizeof(unsigned long));
5033 free(buf);
5034 if (ret < 0)
5035 goto error;
5036
5037 return tep;
5038
5039 error:
5040 tep_free(tep);
5041 return NULL;
5042 }
5043
5044 /*
5045 * Try to write the date into the ftrace buffer and then
5046 * read it back, mapping the timestamp to the date.
5047 */
get_date_to_ts(void)5048 static char *get_date_to_ts(void)
5049 {
5050 struct tep_handle *tep;
5051 unsigned long long min = -1ULL;
5052 unsigned long long diff;
5053 unsigned long long stamp;
5054 unsigned long long min_stamp;
5055 unsigned long long min_ts;
5056 unsigned long long ts;
5057 struct timespec start;
5058 struct timespec end;
5059 char *date2ts = NULL;
5060 int tfd;
5061 int i;
5062
5063 /* Set up a tep to read the raw format */
5064 tep = get_ftrace_tep();
5065 if (!tep) {
5066 warning("failed to alloc tep, --date ignored");
5067 return NULL;
5068 }
5069 tfd = tracefs_instance_file_open(NULL, "trace_marker", O_WRONLY);
5070 if (tfd < 0) {
5071 warning("Can not open 'trace_marker', --date ignored");
5072 goto out_pevent;
5073 }
5074
5075 for (i = 0; i < date2ts_tries; i++) {
5076 tracecmd_disable_tracing();
5077 clear_trace_instances();
5078 tracecmd_enable_tracing();
5079
5080 clock_gettime(CLOCK_REALTIME, &start);
5081 write(tfd, STAMP, 5);
5082 clock_gettime(CLOCK_REALTIME, &end);
5083
5084 tracecmd_disable_tracing();
5085 ts = find_time_stamp(tep, NULL);
5086 if (!ts)
5087 continue;
5088
5089 diff = (unsigned long long)end.tv_sec * 1000000000LL;
5090 diff += (unsigned long long)end.tv_nsec;
5091 stamp = diff;
5092 diff -= (unsigned long long)start.tv_sec * 1000000000LL;
5093 diff -= (unsigned long long)start.tv_nsec;
5094
5095 if (diff < min) {
5096 min_ts = ts;
5097 min_stamp = stamp - diff / 2;
5098 min = diff;
5099 }
5100 }
5101
5102 close(tfd);
5103
5104 if (min == -1ULL) {
5105 warning("Failed to make date offset, --date ignored");
5106 goto out_pevent;
5107 }
5108
5109 /* 16 hex chars + 0x + \0 */
5110 date2ts = malloc(19);
5111 if (!date2ts)
5112 goto out_pevent;
5113
5114 /*
5115 * The difference between the timestamp and the gtod is
5116 * stored as an ASCII string in hex.
5117 */
5118 diff = min_stamp - min_ts;
5119 snprintf(date2ts, 19, "0x%llx", diff/1000);
5120 out_pevent:
5121 tep_free(tep);
5122
5123 return date2ts;
5124 }
5125
set_buffer_size_instance(struct buffer_instance * instance)5126 static void set_buffer_size_instance(struct buffer_instance *instance)
5127 {
5128 int buffer_size = instance->buffer_size;
5129 int ret;
5130
5131 if (is_guest(instance))
5132 return;
5133
5134 if (!buffer_size)
5135 return;
5136
5137 if (buffer_size < 0)
5138 die("buffer size must be positive");
5139
5140 instance->old_buffer_size = tracefs_instance_get_buffer_size(instance->tracefs, 0);
5141 ret = tracefs_instance_set_buffer_size(instance->tracefs, buffer_size, -1);
5142 if (ret < 0)
5143 warning("Can't set buffer size");
5144 }
5145
set_subbuf_size_instance(struct buffer_instance * instance)5146 static void set_subbuf_size_instance(struct buffer_instance *instance)
5147 {
5148 int subbuf_size = instance->subbuf_size;
5149 int ret;
5150
5151 if (is_guest(instance))
5152 return;
5153
5154 if (!subbuf_size)
5155 return;
5156
5157 if (subbuf_size < 0)
5158 die("sub-buffer size must be positive");
5159
5160 instance->old_subbuf_size = tracefs_instance_get_subbuf_size(instance->tracefs);
5161 ret = tracefs_instance_set_subbuf_size(instance->tracefs, subbuf_size);
5162 if (ret < 0)
5163 warning("Can't set sub-buffer size");
5164 }
5165
set_buffer_size(void)5166 void set_buffer_size(void)
5167 {
5168 struct buffer_instance *instance;
5169
5170 for_all_instances(instance) {
5171 set_buffer_size_instance(instance);
5172 set_subbuf_size_instance(instance);
5173 }
5174 }
5175
5176 static int
process_event_trigger(char * path,struct event_iter * iter)5177 process_event_trigger(char *path, struct event_iter *iter)
5178 {
5179 const char *system = iter->system_dent->d_name;
5180 const char *event = iter->event_dent->d_name;
5181 struct stat st;
5182 char *trigger = NULL;
5183 char *file;
5184 int ret;
5185
5186 path = append_file(path, system);
5187 file = append_file(path, event);
5188 free(path);
5189
5190 ret = stat(file, &st);
5191 if (ret < 0 || !S_ISDIR(st.st_mode))
5192 goto out;
5193
5194 trigger = append_file(file, "trigger");
5195
5196 ret = stat(trigger, &st);
5197 if (ret < 0)
5198 goto out;
5199
5200 ret = clear_trigger(trigger);
5201 out:
5202 free(trigger);
5203 free(file);
5204 return ret;
5205 }
5206
clear_instance_triggers(struct buffer_instance * instance)5207 static void clear_instance_triggers(struct buffer_instance *instance)
5208 {
5209 enum event_iter_type type;
5210 struct event_iter *iter;
5211 char *system;
5212 char *path;
5213 int retry = 0;
5214 int ret;
5215
5216 path = tracefs_instance_get_file(instance->tracefs, "events");
5217 if (!path)
5218 die("malloc");
5219
5220 iter = trace_event_iter_alloc(path);
5221
5222 system = NULL;
5223 while ((type = trace_event_iter_next(iter, path, system))) {
5224
5225 if (type == EVENT_ITER_SYSTEM) {
5226 system = iter->system_dent->d_name;
5227 continue;
5228 }
5229
5230 ret = process_event_trigger(path, iter);
5231 if (ret > 0)
5232 retry++;
5233 }
5234
5235 trace_event_iter_free(iter);
5236
5237 if (retry) {
5238 int i;
5239
5240 /* Order matters for some triggers */
5241 for (i = 0; i < retry; i++) {
5242 int tries = 0;
5243
5244 iter = trace_event_iter_alloc(path);
5245 system = NULL;
5246 while ((type = trace_event_iter_next(iter, path, system))) {
5247
5248 if (type == EVENT_ITER_SYSTEM) {
5249 system = iter->system_dent->d_name;
5250 continue;
5251 }
5252
5253 ret = process_event_trigger(path, iter);
5254 if (ret > 0)
5255 tries++;
5256 }
5257 trace_event_iter_free(iter);
5258 if (!tries)
5259 break;
5260 }
5261 }
5262
5263 tracefs_put_tracing_file(path);
5264 }
5265
5266 static void
process_event_filter(char * path,struct event_iter * iter,enum event_process * processed)5267 process_event_filter(char *path, struct event_iter *iter, enum event_process *processed)
5268 {
5269 const char *system = iter->system_dent->d_name;
5270 const char *event = iter->event_dent->d_name;
5271 struct stat st;
5272 char *filter = NULL;
5273 char *file;
5274 int ret;
5275
5276 path = append_file(path, system);
5277 file = append_file(path, event);
5278 free(path);
5279
5280 ret = stat(file, &st);
5281 if (ret < 0 || !S_ISDIR(st.st_mode))
5282 goto out;
5283
5284 filter = append_file(file, "filter");
5285
5286 ret = stat(filter, &st);
5287 if (ret < 0)
5288 goto out;
5289
5290 clear_filter(filter);
5291 out:
5292 free(filter);
5293 free(file);
5294 }
5295
clear_instance_filters(struct buffer_instance * instance)5296 static void clear_instance_filters(struct buffer_instance *instance)
5297 {
5298 struct event_iter *iter;
5299 char *path;
5300 char *system;
5301 enum event_iter_type type;
5302 enum event_process processed = PROCESSED_NONE;
5303
5304 path = tracefs_instance_get_file(instance->tracefs, "events");
5305 if (!path)
5306 die("malloc");
5307
5308 iter = trace_event_iter_alloc(path);
5309
5310 processed = PROCESSED_NONE;
5311 system = NULL;
5312 while ((type = trace_event_iter_next(iter, path, system))) {
5313
5314 if (type == EVENT_ITER_SYSTEM) {
5315 system = iter->system_dent->d_name;
5316 continue;
5317 }
5318
5319 process_event_filter(path, iter, &processed);
5320 }
5321
5322 trace_event_iter_free(iter);
5323
5324 tracefs_put_tracing_file(path);
5325 }
5326
clear_filters(void)5327 static void clear_filters(void)
5328 {
5329 struct buffer_instance *instance;
5330
5331 for_all_instances(instance)
5332 clear_instance_filters(instance);
5333 }
5334
reset_clock(void)5335 static void reset_clock(void)
5336 {
5337 struct buffer_instance *instance;
5338
5339 for_all_instances(instance)
5340 tracefs_instance_file_write(instance->tracefs,
5341 "trace_clock", "local");
5342 }
5343
reset_cpu_mask(void)5344 static void reset_cpu_mask(void)
5345 {
5346 struct buffer_instance *instance;
5347 int cpus = tracecmd_count_cpus();
5348 int fullwords = (cpus - 1) / 32;
5349 int bits = (cpus - 1) % 32 + 1;
5350 int len = (fullwords + 1) * 9;
5351 char buf[len + 1];
5352
5353 buf[0] = '\0';
5354
5355 sprintf(buf, "%x", (unsigned int)((1ULL << bits) - 1));
5356 while (fullwords-- > 0)
5357 strcat(buf, ",ffffffff");
5358
5359 for_all_instances(instance)
5360 tracefs_instance_file_write(instance->tracefs,
5361 "tracing_cpumask", buf);
5362 }
5363
reset_event_pid(void)5364 static void reset_event_pid(void)
5365 {
5366 struct buffer_instance *instance;
5367
5368 for_all_instances(instance)
5369 add_event_pid(instance, "");
5370 }
5371
clear_triggers(void)5372 static void clear_triggers(void)
5373 {
5374 struct buffer_instance *instance;
5375
5376 for_all_instances(instance)
5377 clear_instance_triggers(instance);
5378 }
5379
clear_instance_error_log(struct buffer_instance * instance)5380 static void clear_instance_error_log(struct buffer_instance *instance)
5381 {
5382 char *file;
5383
5384 if (!tracefs_file_exists(instance->tracefs, "error_log"))
5385 return;
5386
5387 file = tracefs_instance_get_file(instance->tracefs, "error_log");
5388 if (!file)
5389 return;
5390 write_file(file, " ");
5391 tracefs_put_tracing_file(file);
5392 }
5393
clear_error_log(void)5394 static void clear_error_log(void)
5395 {
5396 struct buffer_instance *instance;
5397
5398 for_all_instances(instance)
5399 clear_instance_error_log(instance);
5400 }
5401
clear_all_dynamic_events(void)5402 static void clear_all_dynamic_events(void)
5403 {
5404 /* Clear event probes first, as they may be attached to other dynamic event */
5405 tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_EPROBE, true);
5406 tracefs_dynevent_destroy_all(TRACEFS_DYNEVENT_ALL, true);
5407 }
5408
clear_func_filters(void)5409 static void clear_func_filters(void)
5410 {
5411 struct buffer_instance *instance;
5412 char *path;
5413 int i;
5414 const char * const files[] = { "set_ftrace_filter",
5415 "set_ftrace_notrace",
5416 "set_graph_function",
5417 "set_graph_notrace",
5418 NULL };
5419
5420 for_all_instances(instance) {
5421 for (i = 0; files[i]; i++) {
5422 path = tracefs_instance_get_file(instance->tracefs, files[i]);
5423 clear_func_filter(path);
5424 tracefs_put_tracing_file(path);
5425 }
5426 }
5427 }
5428
make_instances(void)5429 static void make_instances(void)
5430 {
5431 struct buffer_instance *instance;
5432
5433 for_each_instance(instance) {
5434 if (is_guest(instance))
5435 continue;
5436 if (instance->name && !instance->tracefs) {
5437 instance->tracefs = tracefs_instance_create(instance->name);
5438 /* Don't delete instances that already exist */
5439 if (instance->tracefs && !tracefs_instance_is_new(instance->tracefs))
5440 instance->flags |= BUFFER_FL_KEEP;
5441 }
5442 }
5443 }
5444
tracecmd_remove_instances(void)5445 void tracecmd_remove_instances(void)
5446 {
5447 struct buffer_instance *instance;
5448
5449 for_each_instance(instance) {
5450 /* Only delete what we created */
5451 if (is_guest(instance) || (instance->flags & BUFFER_FL_KEEP))
5452 continue;
5453 if (instance->tracing_on_fd > 0) {
5454 close(instance->tracing_on_fd);
5455 instance->tracing_on_fd = 0;
5456 }
5457 tracefs_instance_destroy(instance->tracefs);
5458 }
5459 }
5460
check_plugin(const char * plugin)5461 static void check_plugin(const char *plugin)
5462 {
5463 char *buf;
5464 char *str;
5465 char *tok;
5466
5467 /*
5468 * nop is special. We may want to just trace
5469 * trace_printks, that are in the kernel.
5470 */
5471 if (strcmp(plugin, "nop") == 0)
5472 return;
5473
5474 buf = read_top_file("available_tracers", NULL);
5475 if (!buf)
5476 die("No plugins available");
5477
5478 str = buf;
5479 while ((tok = strtok(str, " "))) {
5480 str = NULL;
5481 if (strcmp(tok, plugin) == 0)
5482 goto out;
5483 }
5484 die ("Plugin '%s' does not exist", plugin);
5485 out:
5486 if (!quiet)
5487 fprintf(stderr, " plugin '%s'\n", plugin);
5488 free(buf);
5489 }
5490
check_function_plugin(void)5491 static void check_function_plugin(void)
5492 {
5493 const char *plugin;
5494
5495 /* We only care about the top_instance */
5496 if (no_top_instance())
5497 return;
5498
5499 plugin = top_instance.plugin;
5500 if (!plugin)
5501 return;
5502
5503 if (plugin && strncmp(plugin, "function", 8) == 0 &&
5504 func_stack && !top_instance.filter_funcs)
5505 die("Must supply function filtering with --func-stack\n");
5506 }
5507
__check_doing_something(struct buffer_instance * instance)5508 static int __check_doing_something(struct buffer_instance *instance)
5509 {
5510 return is_guest(instance) || (instance->flags & BUFFER_FL_PROFILE) ||
5511 instance->plugin || instance->events || instance->get_procmap;
5512 }
5513
check_doing_something(void)5514 static void check_doing_something(void)
5515 {
5516 struct buffer_instance *instance;
5517
5518 for_all_instances(instance) {
5519 if (__check_doing_something(instance))
5520 return;
5521 }
5522
5523 die("no event or plugin was specified... aborting");
5524 }
5525
5526 static void
update_plugin_instance(struct buffer_instance * instance,enum trace_type type)5527 update_plugin_instance(struct buffer_instance *instance,
5528 enum trace_type type)
5529 {
5530 const char *plugin = instance->plugin;
5531
5532 if (is_guest(instance))
5533 return;
5534
5535 if (!plugin)
5536 return;
5537
5538 check_plugin(plugin);
5539
5540 /*
5541 * Latency tracers just save the trace and kill
5542 * the threads.
5543 */
5544 if (strcmp(plugin, "irqsoff") == 0 ||
5545 strcmp(plugin, "preemptoff") == 0 ||
5546 strcmp(plugin, "preemptirqsoff") == 0 ||
5547 strcmp(plugin, "wakeup") == 0 ||
5548 strcmp(plugin, "wakeup_rt") == 0) {
5549 latency = 1;
5550 if (host)
5551 die("Network tracing not available with latency tracer plugins");
5552 if (type & TRACE_TYPE_STREAM)
5553 die("Streaming is not available with latency tracer plugins");
5554 } else if (type == TRACE_TYPE_RECORD) {
5555 if (latency)
5556 die("Can not record latency tracer and non latency trace together");
5557 }
5558
5559 if (fset < 0 && (strcmp(plugin, "function") == 0 ||
5560 strcmp(plugin, "function_graph") == 0))
5561 die("function tracing not configured on this kernel");
5562
5563 if (type != TRACE_TYPE_EXTRACT)
5564 set_plugin_instance(instance, plugin);
5565 }
5566
update_plugins(enum trace_type type)5567 static void update_plugins(enum trace_type type)
5568 {
5569 struct buffer_instance *instance;
5570
5571 for_all_instances(instance)
5572 update_plugin_instance(instance, type);
5573 }
5574
allocate_seq(void)5575 static void allocate_seq(void)
5576 {
5577 struct buffer_instance *instance;
5578
5579 for_all_instances(instance) {
5580 instance->s_save = malloc(sizeof(struct trace_seq) * instance->cpu_count);
5581 instance->s_print = malloc(sizeof(struct trace_seq) * instance->cpu_count);
5582 if (!instance->s_save || !instance->s_print)
5583 die("Failed to allocate instance info");
5584 }
5585 }
5586
5587 /* Find the overrun output, and add it to the print seq */
add_overrun(int cpu,struct trace_seq * src,struct trace_seq * dst)5588 static void add_overrun(int cpu, struct trace_seq *src, struct trace_seq *dst)
5589 {
5590 const char overrun_str[] = "overrun: ";
5591 const char commit_overrun_str[] = "commit overrun: ";
5592 const char *p;
5593 int overrun;
5594 int commit_overrun;
5595
5596 p = strstr(src->buffer, overrun_str);
5597 if (!p) {
5598 /* Warn? */
5599 trace_seq_printf(dst, "CPU %d: no overrun found?\n", cpu);
5600 return;
5601 }
5602
5603 overrun = atoi(p + strlen(overrun_str));
5604
5605 p = strstr(p + 9, commit_overrun_str);
5606 if (p)
5607 commit_overrun = atoi(p + strlen(commit_overrun_str));
5608 else
5609 commit_overrun = -1;
5610
5611 if (!overrun && !commit_overrun)
5612 return;
5613
5614 trace_seq_printf(dst, "CPU %d:", cpu);
5615
5616 if (overrun)
5617 trace_seq_printf(dst, " %d events lost", overrun);
5618
5619 if (commit_overrun)
5620 trace_seq_printf(dst, " %d events lost due to commit overrun",
5621 commit_overrun);
5622
5623 trace_seq_putc(dst, '\n');
5624 }
5625
record_stats(void)5626 static void record_stats(void)
5627 {
5628 struct buffer_instance *instance;
5629 struct trace_seq *s_save;
5630 struct trace_seq *s_print;
5631 int cpu;
5632
5633 for_all_instances(instance) {
5634 if (is_guest(instance))
5635 continue;
5636
5637 s_save = instance->s_save;
5638 s_print = instance->s_print;
5639 for (cpu = 0; cpu < instance->cpu_count; cpu++) {
5640 trace_seq_init(&s_save[cpu]);
5641 trace_seq_init(&s_print[cpu]);
5642 trace_seq_printf(&s_save[cpu], "CPU: %d\n", cpu);
5643 tracecmd_stat_cpu_instance(instance, &s_save[cpu], cpu);
5644 add_overrun(cpu, &s_save[cpu], &s_print[cpu]);
5645 }
5646 }
5647 }
5648
print_stats(void)5649 static void print_stats(void)
5650 {
5651 struct buffer_instance *instance;
5652
5653 for_all_instances(instance)
5654 print_stat(instance);
5655 }
5656
destroy_stats(void)5657 static void destroy_stats(void)
5658 {
5659 struct buffer_instance *instance;
5660 int cpu;
5661
5662 for_all_instances(instance) {
5663 if (is_guest(instance))
5664 continue;
5665
5666 for (cpu = 0; cpu < instance->cpu_count; cpu++) {
5667 trace_seq_destroy(&instance->s_save[cpu]);
5668 trace_seq_destroy(&instance->s_print[cpu]);
5669 }
5670 }
5671 }
5672
list_event(const char * event)5673 static void list_event(const char *event)
5674 {
5675 struct tracecmd_event_list *list;
5676
5677 list = malloc(sizeof(*list));
5678 if (!list)
5679 die("Failed to allocate list for event");
5680 list->next = listed_events;
5681 list->glob = event;
5682 listed_events = list;
5683 }
5684
5685 #define ALL_EVENTS "*/*"
5686
record_all_events(void)5687 static void record_all_events(void)
5688 {
5689 struct tracecmd_event_list *list;
5690
5691 while (listed_events) {
5692 list = listed_events;
5693 listed_events = list->next;
5694 free(list);
5695 }
5696 list = malloc(sizeof(*list));
5697 if (!list)
5698 die("Failed to allocate list for all events");
5699 list->next = NULL;
5700 list->glob = ALL_EVENTS;
5701 listed_events = list;
5702 }
5703
recording_all_events(void)5704 static int recording_all_events(void)
5705 {
5706 return listed_events && strcmp(listed_events->glob, ALL_EVENTS) == 0;
5707 }
5708
add_trigger(struct event_list * event,const char * trigger)5709 static void add_trigger(struct event_list *event, const char *trigger)
5710 {
5711 int ret;
5712
5713 if (event->trigger) {
5714 event->trigger = realloc(event->trigger,
5715 strlen(event->trigger) + strlen("\n") +
5716 strlen(trigger) + 1);
5717 strcat(event->trigger, "\n");
5718 strcat(event->trigger, trigger);
5719 } else {
5720 ret = asprintf(&event->trigger, "%s", trigger);
5721 if (ret < 0)
5722 die("Failed to allocate event trigger");
5723 }
5724 }
5725
test_stacktrace_trigger(struct buffer_instance * instance)5726 static int test_stacktrace_trigger(struct buffer_instance *instance)
5727 {
5728 char *path;
5729 int ret = 0;
5730 int fd;
5731
5732 path = tracefs_instance_get_file(instance->tracefs,
5733 "events/sched/sched_switch/trigger");
5734
5735 clear_trigger(path);
5736
5737 fd = open(path, O_WRONLY);
5738 if (fd < 0)
5739 goto out;
5740
5741 ret = write(fd, "stacktrace", 10);
5742 if (ret != 10)
5743 ret = 0;
5744 else
5745 ret = 1;
5746 close(fd);
5747 out:
5748 tracefs_put_tracing_file(path);
5749
5750 return ret;
5751 }
5752
5753 static int
profile_add_event(struct buffer_instance * instance,const char * event_str,int stack)5754 profile_add_event(struct buffer_instance *instance, const char *event_str, int stack)
5755 {
5756 struct event_list *event;
5757 char buf[BUFSIZ];
5758 char *p;
5759
5760 strcpy(buf, "events/");
5761 strncpy(buf + 7, event_str, BUFSIZ - 7);
5762 buf[BUFSIZ-1] = 0;
5763
5764 if ((p = strstr(buf, ":"))) {
5765 *p = '/';
5766 p++;
5767 }
5768
5769 if (!trace_check_file_exists(instance, buf))
5770 return -1;
5771
5772 /* Only add event if it isn't already added */
5773 for (event = instance->events; event; event = event->next) {
5774 if (p && strcmp(event->event, p) == 0)
5775 break;
5776 if (strcmp(event->event, event_str) == 0)
5777 break;
5778 }
5779
5780 if (!event) {
5781 event = malloc(sizeof(*event));
5782 if (!event)
5783 die("Failed to allocate event");
5784 memset(event, 0, sizeof(*event));
5785 event->event = event_str;
5786 add_event(instance, event);
5787 }
5788
5789 if (!recording_all_events())
5790 list_event(event_str);
5791
5792 if (stack) {
5793 if (!event->trigger || !strstr(event->trigger, "stacktrace"))
5794 add_trigger(event, "stacktrace");
5795 }
5796
5797 return 0;
5798 }
5799
tracecmd_add_event(const char * event_str,int stack)5800 int tracecmd_add_event(const char *event_str, int stack)
5801 {
5802 return profile_add_event(first_instance, event_str, stack);
5803 }
5804
enable_profile(struct buffer_instance * instance)5805 static void enable_profile(struct buffer_instance *instance)
5806 {
5807 int stacktrace = 0;
5808 int i;
5809 char *trigger_events[] = {
5810 "sched:sched_switch",
5811 "sched:sched_wakeup",
5812 NULL,
5813 };
5814 char *events[] = {
5815 "exceptions:page_fault_user",
5816 "irq:irq_handler_entry",
5817 "irq:irq_handler_exit",
5818 "irq:softirq_entry",
5819 "irq:softirq_exit",
5820 "irq:softirq_raise",
5821 "sched:sched_process_exec",
5822 "raw_syscalls",
5823 NULL,
5824 };
5825
5826 if (!instance->plugin) {
5827 if (trace_check_file_exists(instance, "max_graph_depth")) {
5828 instance->plugin = "function_graph";
5829 set_max_graph_depth(instance, "1");
5830 } else
5831 warning("Kernel does not support max_graph_depth\n"
5832 " Skipping user/kernel profiling");
5833 }
5834
5835 if (test_stacktrace_trigger(instance))
5836 stacktrace = 1;
5837 else
5838 /*
5839 * The stacktrace trigger is not implemented with this
5840 * kernel, then we need to default to the stack trace option.
5841 * This is less efficient but still works.
5842 */
5843 save_option(instance, "stacktrace");
5844
5845
5846 for (i = 0; trigger_events[i]; i++)
5847 profile_add_event(instance, trigger_events[i], stacktrace);
5848
5849 for (i = 0; events[i]; i++)
5850 profile_add_event(instance, events[i], 0);
5851 }
5852
5853 static struct event_list *
create_hook_event(struct buffer_instance * instance,const char * system,const char * event)5854 create_hook_event(struct buffer_instance *instance,
5855 const char *system, const char *event)
5856 {
5857 struct event_list *event_list;
5858 char *event_name;
5859 int len;
5860
5861 if (!system)
5862 system = "*";
5863
5864 len = strlen(event);
5865 len += strlen(system) + 2;
5866
5867 event_name = malloc(len);
5868 if (!event_name)
5869 die("Failed to allocate %s/%s", system, event);
5870 sprintf(event_name, "%s:%s", system, event);
5871
5872 event_list = malloc(sizeof(*event_list));
5873 if (!event_list)
5874 die("Failed to allocate event list for %s", event_name);
5875 memset(event_list, 0, sizeof(*event_list));
5876 event_list->event = event_name;
5877 add_event(instance, event_list);
5878
5879 list_event(event_name);
5880
5881 return event_list;
5882 }
5883
add_hook(struct buffer_instance * instance,const char * arg)5884 static void add_hook(struct buffer_instance *instance, const char *arg)
5885 {
5886 struct event_list *event;
5887 struct hook_list *hook;
5888
5889 hook = tracecmd_create_event_hook(arg);
5890 if (!hook)
5891 die("Failed to create event hook %s", arg);
5892
5893 hook->instance = instance;
5894 hook->next = hooks;
5895 hooks = hook;
5896
5897 /* Make sure the event is enabled */
5898 event = create_hook_event(instance, hook->start_system, hook->start_event);
5899 create_hook_event(instance, hook->end_system, hook->end_event);
5900
5901 if (hook->stack) {
5902 if (!event->trigger || !strstr(event->trigger, "stacktrace"))
5903 add_trigger(event, "stacktrace");
5904 }
5905 }
5906
update_first_instance(struct buffer_instance * instance,int topt)5907 void update_first_instance(struct buffer_instance *instance, int topt)
5908 {
5909 if (topt || instance == &top_instance)
5910 first_instance = &top_instance;
5911 else
5912 first_instance = buffer_instances;
5913 }
5914
init_top_instance(void)5915 void init_top_instance(void)
5916 {
5917 if (!top_instance.tracefs)
5918 top_instance.tracefs = tracefs_instance_create(NULL);
5919 top_instance.cpu_count = tracecmd_count_cpus();
5920 top_instance.flags = BUFFER_FL_KEEP;
5921 top_instance.trace_id = tracecmd_generate_traceid();
5922 init_instance(&top_instance);
5923 }
5924
5925 enum {
5926 OPT_compression = 237,
5927 OPT_file_ver = 238,
5928 OPT_verbose = 239,
5929 OPT_tsc2nsec = 240,
5930 OPT_fork = 241,
5931 OPT_tsyncinterval = 242,
5932 OPT_user = 243,
5933 OPT_procmap = 244,
5934 OPT_quiet = 245,
5935 OPT_debug = 246,
5936 OPT_no_filter = 247,
5937 OPT_max_graph_depth = 248,
5938 OPT_tsoffset = 249,
5939 OPT_bycomm = 250,
5940 OPT_stderr = 251,
5941 OPT_profile = 252,
5942 OPT_nosplice = 253,
5943 OPT_funcstack = 254,
5944 OPT_date = 255,
5945 OPT_module = 256,
5946 OPT_nofifos = 257,
5947 OPT_cmdlines_size = 258,
5948 OPT_poll = 259,
5949 OPT_name = 260,
5950 OPT_proxy = 261,
5951 OPT_temp = 262,
5952 OPT_notimeout = 264,
5953 OPT_daemonize = 265,
5954 OPT_subbuf = 266,
5955 };
5956
trace_stop(int argc,char ** argv)5957 void trace_stop(int argc, char **argv)
5958 {
5959 int topt = 0;
5960 struct buffer_instance *instance = &top_instance;
5961
5962 init_top_instance();
5963
5964 for (;;) {
5965 int c;
5966
5967 c = getopt(argc-1, argv+1, "hatB:");
5968 if (c == -1)
5969 break;
5970
5971 switch (c) {
5972 case 'h':
5973 usage(argv);
5974 break;
5975 case 'B':
5976 instance = allocate_instance(optarg);
5977 if (!instance)
5978 die("Failed to create instance");
5979 add_instance(instance, local_cpu_count);
5980 break;
5981 case 'a':
5982 add_all_instances();
5983 break;
5984 case 't':
5985 /* Force to use top instance */
5986 topt = 1;
5987 instance = &top_instance;
5988 break;
5989 default:
5990 usage(argv);
5991 }
5992 }
5993 update_first_instance(instance, topt);
5994 tracecmd_disable_tracing();
5995 exit(0);
5996 }
5997
trace_restart(int argc,char ** argv)5998 void trace_restart(int argc, char **argv)
5999 {
6000 int topt = 0;
6001 struct buffer_instance *instance = &top_instance;
6002
6003 init_top_instance();
6004
6005 for (;;) {
6006 int c;
6007
6008 c = getopt(argc-1, argv+1, "hatB:");
6009 if (c == -1)
6010 break;
6011 switch (c) {
6012 case 'h':
6013 usage(argv);
6014 break;
6015 case 'B':
6016 instance = allocate_instance(optarg);
6017 if (!instance)
6018 die("Failed to create instance");
6019 add_instance(instance, local_cpu_count);
6020 break;
6021 case 'a':
6022 add_all_instances();
6023 break;
6024 case 't':
6025 /* Force to use top instance */
6026 topt = 1;
6027 instance = &top_instance;
6028 break;
6029 default:
6030 usage(argv);
6031 }
6032
6033 }
6034 update_first_instance(instance, topt);
6035 tracecmd_enable_tracing();
6036 exit(0);
6037 }
6038
trace_reset(int argc,char ** argv)6039 void trace_reset(int argc, char **argv)
6040 {
6041 int c;
6042 int topt = 0;
6043 struct buffer_instance *instance = &top_instance;
6044
6045 init_top_instance();
6046
6047 /* if last arg is -a, then -b and -d apply to all instances */
6048 int last_specified_all = 0;
6049 struct buffer_instance *inst; /* iterator */
6050
6051 while ((c = getopt(argc-1, argv+1, "hab:B:td")) >= 0) {
6052
6053 switch (c) {
6054 case 'h':
6055 usage(argv);
6056 break;
6057 case 'b':
6058 {
6059 int size = atoi(optarg);
6060 /* Min buffer size is 1 */
6061 if (size <= 1)
6062 size = 1;
6063 if (last_specified_all) {
6064 for_each_instance(inst) {
6065 inst->buffer_size = size;
6066 }
6067 } else {
6068 instance->buffer_size = size;
6069 }
6070 break;
6071 }
6072 case 'B':
6073 last_specified_all = 0;
6074 instance = allocate_instance(optarg);
6075 if (!instance)
6076 die("Failed to create instance");
6077 add_instance(instance, local_cpu_count);
6078 /* -d will remove keep */
6079 instance->flags |= BUFFER_FL_KEEP;
6080 break;
6081 case 't':
6082 /* Force to use top instance */
6083 last_specified_all = 0;
6084 topt = 1;
6085 instance = &top_instance;
6086 break;
6087 case 'a':
6088 last_specified_all = 1;
6089 add_all_instances();
6090 for_each_instance(inst) {
6091 inst->flags |= BUFFER_FL_KEEP;
6092 }
6093 break;
6094 case 'd':
6095 if (last_specified_all) {
6096 for_each_instance(inst) {
6097 inst->flags &= ~BUFFER_FL_KEEP;
6098 }
6099 } else {
6100 if (is_top_instance(instance))
6101 die("Can not delete top level buffer");
6102 instance->flags &= ~BUFFER_FL_KEEP;
6103 }
6104 break;
6105 }
6106 }
6107 update_first_instance(instance, topt);
6108 tracecmd_disable_all_tracing(1);
6109 set_buffer_size();
6110 clear_filters();
6111 clear_triggers();
6112 clear_all_dynamic_events();
6113 clear_error_log();
6114 /* set clock to "local" */
6115 reset_clock();
6116 reset_event_pid();
6117 reset_max_latency_instance();
6118 reset_cpu_mask();
6119 tracecmd_remove_instances();
6120 clear_func_filters();
6121 /* restore tracing_on to 1 */
6122 tracecmd_enable_tracing();
6123 exit(0);
6124 }
6125
init_common_record_context(struct common_record_context * ctx,enum trace_cmd curr_cmd)6126 static void init_common_record_context(struct common_record_context *ctx,
6127 enum trace_cmd curr_cmd)
6128 {
6129 memset(ctx, 0, sizeof(*ctx));
6130 ctx->instance = &top_instance;
6131 ctx->curr_cmd = curr_cmd;
6132 local_cpu_count = tracecmd_count_cpus();
6133 ctx->file_version = tracecmd_default_file_version();
6134 init_top_instance();
6135 }
6136
6137 #define IS_EXTRACT(ctx) ((ctx)->curr_cmd == CMD_extract)
6138 #define IS_START(ctx) ((ctx)->curr_cmd == CMD_start)
6139 #define IS_CMDSET(ctx) ((ctx)->curr_cmd == CMD_set)
6140 #define IS_STREAM(ctx) ((ctx)->curr_cmd == CMD_stream)
6141 #define IS_PROFILE(ctx) ((ctx)->curr_cmd == CMD_profile)
6142 #define IS_RECORD(ctx) ((ctx)->curr_cmd == CMD_record)
6143 #define IS_RECORD_AGENT(ctx) ((ctx)->curr_cmd == CMD_record_agent)
6144
add_argv(struct buffer_instance * instance,char * arg,bool prepend)6145 static void add_argv(struct buffer_instance *instance, char *arg, bool prepend)
6146 {
6147 instance->argv = realloc(instance->argv,
6148 (instance->argc + 1) * sizeof(char *));
6149 if (!instance->argv)
6150 die("Can not allocate instance args");
6151 if (prepend) {
6152 memmove(instance->argv + 1, instance->argv,
6153 instance->argc * sizeof(*instance->argv));
6154 instance->argv[0] = arg;
6155 } else {
6156 instance->argv[instance->argc] = arg;
6157 }
6158 instance->argc++;
6159 }
6160
add_arg(struct buffer_instance * instance,int c,const char * opts,struct option * long_options,char * optarg)6161 static void add_arg(struct buffer_instance *instance,
6162 int c, const char *opts,
6163 struct option *long_options, char *optarg)
6164 {
6165 char *ptr, *arg;
6166 int i, ret;
6167
6168 /* Short or long arg */
6169 if (!(c & 0x80)) {
6170 ptr = strchr(opts, c);
6171 if (!ptr)
6172 return; /* Not found? */
6173 ret = asprintf(&arg, "-%c", c);
6174 if (ret < 0)
6175 die("Can not allocate argument");
6176 add_argv(instance, arg, false);
6177 if (ptr[1] == ':') {
6178 arg = strdup(optarg);
6179 if (!arg)
6180 die("Can not allocate arguments");
6181 add_argv(instance, arg, false);
6182 }
6183 return;
6184 }
6185 for (i = 0; long_options[i].name; i++) {
6186 if (c != long_options[i].val)
6187 continue;
6188 ret = asprintf(&arg, "--%s", long_options[i].name);
6189 if (ret < 0)
6190 die("Can not allocate argument");
6191 add_argv(instance, arg, false);
6192 if (long_options[i].has_arg) {
6193 arg = strdup(optarg);
6194 if (!arg)
6195 die("Can not allocate arguments");
6196 add_argv(instance, arg, false);
6197 }
6198 return;
6199 }
6200 /* Not found? */
6201 }
6202
cmd_check_die(struct common_record_context * ctx,enum trace_cmd id,char * cmd,char * param)6203 static inline void cmd_check_die(struct common_record_context *ctx,
6204 enum trace_cmd id, char *cmd, char *param)
6205 {
6206 if (ctx->curr_cmd == id)
6207 die("%s has no effect with the command %s\n"
6208 "Did you mean 'record'?", param, cmd);
6209 }
6210
remove_instances(struct buffer_instance * instances)6211 static inline void remove_instances(struct buffer_instance *instances)
6212 {
6213 struct buffer_instance *del;
6214
6215 while (instances) {
6216 del = instances;
6217 instances = instances->next;
6218 free(del->name);
6219 if (tracefs_instance_is_new(del->tracefs))
6220 tracefs_instance_destroy(del->tracefs);
6221 tracefs_instance_free(del->tracefs);
6222 free(del);
6223 }
6224 }
6225
6226 static inline void
check_instance_die(struct buffer_instance * instance,char * param)6227 check_instance_die(struct buffer_instance *instance, char *param)
6228 {
6229 if (instance->delete)
6230 die("Instance %s is marked for deletion, invalid option %s",
6231 tracefs_instance_get_name(instance->tracefs), param);
6232 }
6233
clock_is_supported(struct tracefs_instance * instance,const char * clock)6234 static bool clock_is_supported(struct tracefs_instance *instance, const char *clock)
6235 {
6236 char *all_clocks = NULL;
6237 char *ret = NULL;
6238
6239 all_clocks = tracefs_instance_file_read(instance, "trace_clock", NULL);
6240 if (!all_clocks)
6241 return false;
6242
6243 ret = strstr(all_clocks, clock);
6244 if (ret && (ret == all_clocks || ret[-1] == ' ' || ret[-1] == '[')) {
6245 switch (ret[strlen(clock)]) {
6246 case ' ':
6247 case '\0':
6248 case ']':
6249 case '\n':
6250 break;
6251 default:
6252 ret = NULL;
6253 }
6254 } else {
6255 ret = NULL;
6256 }
6257 free(all_clocks);
6258
6259 return ret != NULL;
6260 }
6261
6262 #ifdef PERF
get_tsc_nsec(int * shift,int * mult)6263 static int get_tsc_nsec(int *shift, int *mult)
6264 {
6265 static int cpu_shift, cpu_mult;
6266 static int supported;
6267 int cpus = tracecmd_count_cpus();
6268 struct trace_perf perf;
6269 int i;
6270
6271 if (supported)
6272 goto out;
6273
6274 supported = -1;
6275 if (trace_perf_init(&perf, 1, 0, getpid()))
6276 return -1;
6277 if (trace_perf_open(&perf))
6278 return -1;
6279 cpu_shift = perf.mmap->time_shift;
6280 cpu_mult = perf.mmap->time_mult;
6281 for (i = 1; i < cpus; i++) {
6282 trace_perf_close(&perf);
6283 if (trace_perf_init(&perf, 1, i, getpid()))
6284 break;
6285 if (trace_perf_open(&perf))
6286 break;
6287 if (perf.mmap->time_shift != cpu_shift ||
6288 perf.mmap->time_mult != cpu_mult) {
6289 warning("Found different TSC multiplier and shift for CPU %d: %d;%d instead of %d;%d",
6290 i, perf.mmap->time_mult, perf.mmap->time_shift, cpu_mult, cpu_shift);
6291 break;
6292 }
6293 }
6294 trace_perf_close(&perf);
6295 if (i < cpus)
6296 return -1;
6297
6298 if (cpu_shift || cpu_mult)
6299 supported = 1;
6300 out:
6301 if (supported < 0)
6302 return -1;
6303
6304 if (shift)
6305 *shift = cpu_shift;
6306 if (mult)
6307 *mult = cpu_mult;
6308
6309 return 0;
6310 }
6311 #else
get_tsc_nsec(int * shift,int * mult)6312 static int get_tsc_nsec(int *shift, int *mult)
6313 {
6314 return -1;
6315 }
6316 #endif
6317
trace_tsc2nsec_is_supported(void)6318 bool trace_tsc2nsec_is_supported(void)
6319 {
6320 return get_tsc_nsec(NULL, NULL) == 0;
6321 }
6322
parse_record_options(int argc,char ** argv,enum trace_cmd curr_cmd,struct common_record_context * ctx)6323 static void parse_record_options(int argc,
6324 char **argv,
6325 enum trace_cmd curr_cmd,
6326 struct common_record_context *ctx)
6327 {
6328 const char *plugin = NULL;
6329 const char *option;
6330 struct event_list *event = NULL;
6331 struct event_list *last_event = NULL;
6332 struct addrinfo *result;
6333 char *pids;
6334 char *pid;
6335 char *sav;
6336 int name_counter = 0;
6337 int negative = 0;
6338 bool is_proxy = false;
6339 struct buffer_instance *instance, *del_list = NULL;
6340 int do_children = 0;
6341 int fpids_count = 0;
6342
6343 init_common_record_context(ctx, curr_cmd);
6344
6345 if (IS_CMDSET(ctx))
6346 keep = 1;
6347
6348 for (;;) {
6349 int option_index = 0;
6350 int ret;
6351 int c;
6352 const char *opts;
6353 static struct option long_options[] = {
6354 {"date", no_argument, NULL, OPT_date},
6355 {"func-stack", no_argument, NULL, OPT_funcstack},
6356 {"nosplice", no_argument, NULL, OPT_nosplice},
6357 {"nofifos", no_argument, NULL, OPT_nofifos},
6358 {"profile", no_argument, NULL, OPT_profile},
6359 {"stderr", no_argument, NULL, OPT_stderr},
6360 {"by-comm", no_argument, NULL, OPT_bycomm},
6361 {"ts-offset", required_argument, NULL, OPT_tsoffset},
6362 {"max-graph-depth", required_argument, NULL, OPT_max_graph_depth},
6363 {"cmdlines-size", required_argument, NULL, OPT_cmdlines_size},
6364 {"no-filter", no_argument, NULL, OPT_no_filter},
6365 {"debug", no_argument, NULL, OPT_debug},
6366 {"notimeout", no_argument, NULL, OPT_notimeout},
6367 {"quiet", no_argument, NULL, OPT_quiet},
6368 {"help", no_argument, NULL, '?'},
6369 {"proc-map", no_argument, NULL, OPT_procmap},
6370 {"user", required_argument, NULL, OPT_user},
6371 {"module", required_argument, NULL, OPT_module},
6372 {"tsync-interval", required_argument, NULL, OPT_tsyncinterval},
6373 {"fork", no_argument, NULL, OPT_fork},
6374 {"tsc2nsec", no_argument, NULL, OPT_tsc2nsec},
6375 {"poll", no_argument, NULL, OPT_poll},
6376 {"name", required_argument, NULL, OPT_name},
6377 {"verbose", optional_argument, NULL, OPT_verbose},
6378 {"compression", required_argument, NULL, OPT_compression},
6379 {"file-version", required_argument, NULL, OPT_file_ver},
6380 {"proxy", required_argument, NULL, OPT_proxy},
6381 {"temp", required_argument, NULL, OPT_temp},
6382 {"subbuf-size", required_argument, NULL, OPT_subbuf},
6383 {"daemonize", no_argument, NULL, OPT_daemonize},
6384 {NULL, 0, NULL, 0}
6385 };
6386
6387 if (IS_EXTRACT(ctx))
6388 opts = "+haf:Fp:co:O:sr:g:l:n:P:N:tb:B:ksiT";
6389 else
6390 opts = "+hae:f:FA:p:cC:dDGo:O:s:r:V:vg:l:n:P:N:tb:R:B:ksSiTm:M:H:q";
6391 c = getopt_long (argc-1, argv+1, opts, long_options, &option_index);
6392 if (c == -1)
6393 break;
6394
6395 /*
6396 * If the current instance is to record a guest, then save
6397 * all the arguments for this instance.
6398 */
6399 if (c != 'B' && (c != 'A' || is_proxy) && c != OPT_name &&
6400 is_guest(ctx->instance) && c != OPT_proxy) {
6401 add_arg(ctx->instance, c, opts, long_options, optarg);
6402 if (c == 'C')
6403 ctx->instance->flags |= BUFFER_FL_HAS_CLOCK;
6404 continue;
6405 }
6406
6407 switch (c) {
6408 case 'h':
6409 usage(argv);
6410 break;
6411 case 'a':
6412 cmd_check_die(ctx, CMD_set, *(argv+1), "-a");
6413 if (IS_EXTRACT(ctx)) {
6414 add_all_instances();
6415 } else {
6416 ctx->record_all = 1;
6417 record_all_events();
6418 }
6419 break;
6420 case 'e':
6421 check_instance_die(ctx->instance, "-e");
6422 ctx->events = 1;
6423 event = malloc(sizeof(*event));
6424 if (!event)
6425 die("Failed to allocate event %s", optarg);
6426 memset(event, 0, sizeof(*event));
6427 event->event = optarg;
6428 add_event(ctx->instance, event);
6429 event->neg = negative;
6430 event->filter = NULL;
6431 last_event = event;
6432
6433 if (!ctx->record_all)
6434 list_event(optarg);
6435 break;
6436 case 'f':
6437 if (!last_event)
6438 die("filter must come after event");
6439 if (last_event->filter) {
6440 last_event->filter =
6441 realloc(last_event->filter,
6442 strlen(last_event->filter) +
6443 strlen("&&()") +
6444 strlen(optarg) + 1);
6445 strcat(last_event->filter, "&&(");
6446 strcat(last_event->filter, optarg);
6447 strcat(last_event->filter, ")");
6448 } else {
6449 ret = asprintf(&last_event->filter, "(%s)", optarg);
6450 if (ret < 0)
6451 die("Failed to allocate filter %s", optarg);
6452 }
6453 break;
6454
6455 case 'R':
6456 if (!last_event)
6457 die("trigger must come after event");
6458 add_trigger(event, optarg);
6459 break;
6460
6461 case OPT_name:
6462 if (!ctx->instance)
6463 die("No instance defined for name option\n");
6464 if (!is_guest(ctx->instance))
6465 die(" --name is only used for -A options\n");
6466 free(ctx->instance->name);
6467 ctx->instance->name = strdup(optarg);
6468 if (!ctx->instance->name)
6469 die("Failed to allocate name");
6470 break;
6471
6472 case OPT_proxy:
6473 is_proxy = true;
6474 /* fall through */
6475 case 'A': {
6476 char *name = NULL;
6477 int cid = -1, port = -1;
6478
6479 if (!IS_RECORD(ctx))
6480 die("%s is only allowed for record operations",
6481 is_proxy ? "--proxy" : "-A");
6482
6483 name = parse_guest_name(optarg, &cid, &port, &result);
6484 if (cid == -1 && !result)
6485 die("guest %s not found", optarg);
6486 if (port == -1)
6487 port = TRACE_AGENT_DEFAULT_PORT;
6488 if (!name || !*name) {
6489 ret = asprintf(&name, "unnamed-%d", name_counter++);
6490 if (ret < 0)
6491 name = NULL;
6492 } else {
6493 /* Needs to be allocate */
6494 name = strdup(name);
6495 }
6496 if (!name)
6497 die("Failed to allocate guest name");
6498
6499 ctx->instance = allocate_instance(name);
6500 if (!ctx->instance)
6501 die("Failed to allocate instance");
6502
6503 if (result) {
6504 ctx->instance->flags |= BUFFER_FL_NETWORK;
6505 ctx->instance->port_type = USE_TCP;
6506 }
6507
6508 if (is_proxy)
6509 ctx->instance->flags |= BUFFER_FL_PROXY;
6510
6511 ctx->instance->flags |= BUFFER_FL_GUEST;
6512 ctx->instance->result = result;
6513 ctx->instance->cid = cid;
6514 ctx->instance->port = port;
6515 ctx->instance->name = name;
6516 add_instance(ctx->instance, 0);
6517 ctx->data_flags |= DATA_FL_GUEST;
6518
6519 /* Do not send a clock to a proxy */
6520 if (is_proxy)
6521 ctx->instance->flags |= BUFFER_FL_HAS_CLOCK;
6522
6523 break;
6524 }
6525 case 'F':
6526 test_set_event_pid(ctx->instance);
6527 filter_task = 1;
6528 break;
6529 case 'G':
6530 cmd_check_die(ctx, CMD_set, *(argv+1), "-G");
6531 ctx->global = 1;
6532 break;
6533 case 'P':
6534 check_instance_die(ctx->instance, "-P");
6535 test_set_event_pid(ctx->instance);
6536 pids = strdup(optarg);
6537 if (!pids)
6538 die("strdup");
6539 pid = strtok_r(pids, ",", &sav);
6540 while (pid) {
6541 fpids_count += add_filter_pid(ctx->instance,
6542 atoi(pid), 0);
6543 pid = strtok_r(NULL, ",", &sav);
6544 ctx->instance->nr_process_pids++;
6545 }
6546 ctx->instance->process_pids = ctx->instance->filter_pids;
6547 free(pids);
6548 break;
6549 case 'c':
6550 check_instance_die(ctx->instance, "-c");
6551 test_set_event_pid(ctx->instance);
6552 do_children = 1;
6553 if (!ctx->instance->have_event_fork) {
6554 #ifdef NO_PTRACE
6555 die("-c invalid: ptrace not supported");
6556 #endif
6557 do_ptrace = 1;
6558 ctx->instance->ptrace_child = 1;
6559
6560 } else {
6561 save_option(ctx->instance, "event-fork");
6562 }
6563 if (ctx->instance->have_func_fork)
6564 save_option(ctx->instance, "function-fork");
6565 break;
6566 case 'C':
6567 check_instance_die(ctx->instance, "-C");
6568 if (strcmp(optarg, TSCNSEC_CLOCK) == 0) {
6569 ret = get_tsc_nsec(&ctx->tsc2nsec.shift,
6570 &ctx->tsc2nsec.mult);
6571 if (ret)
6572 die("TSC to nanosecond is not supported");
6573 ctx->instance->flags |= BUFFER_FL_TSC2NSEC;
6574 ctx->instance->clock = TSC_CLOCK;
6575 } else {
6576 ctx->instance->clock = optarg;
6577 }
6578 if (!clock_is_supported(NULL, ctx->instance->clock))
6579 die("Clock %s is not supported", ctx->instance->clock);
6580 ctx->instance->clock = strdup(ctx->instance->clock);
6581 if (!ctx->instance->clock)
6582 die("Failed allocation");
6583 ctx->instance->flags |= BUFFER_FL_HAS_CLOCK;
6584 if (!ctx->clock && !is_guest(ctx->instance))
6585 ctx->clock = ctx->instance->clock;
6586 break;
6587 case 'v':
6588 negative = 1;
6589 break;
6590 case 'l':
6591 add_func(&ctx->instance->filter_funcs,
6592 ctx->instance->filter_mod, optarg);
6593 ctx->filtered = 1;
6594 break;
6595 case 'n':
6596 check_instance_die(ctx->instance, "-n");
6597 add_func(&ctx->instance->notrace_funcs,
6598 ctx->instance->filter_mod, optarg);
6599 ctx->filtered = 1;
6600 break;
6601 case 'g':
6602 check_instance_die(ctx->instance, "-g");
6603 add_func(&graph_funcs, ctx->instance->filter_mod, optarg);
6604 ctx->filtered = 1;
6605 break;
6606 case 'p':
6607 check_instance_die(ctx->instance, "-p");
6608 if (ctx->instance->plugin)
6609 die("only one plugin allowed");
6610 for (plugin = optarg; isspace(*plugin); plugin++)
6611 ;
6612 ctx->instance->plugin = plugin;
6613 for (optarg += strlen(optarg) - 1;
6614 optarg > plugin && isspace(*optarg); optarg--)
6615 ;
6616 optarg++;
6617 optarg[0] = '\0';
6618 break;
6619 case 'D':
6620 ctx->total_disable = 1;
6621 /* fall through */
6622 case 'd':
6623 ctx->disable = 1;
6624 break;
6625 case 'o':
6626 cmd_check_die(ctx, CMD_set, *(argv+1), "-o");
6627 if (IS_RECORD_AGENT(ctx))
6628 die("-o incompatible with agent recording");
6629 if (host)
6630 die("-o incompatible with -N");
6631 if (IS_START(ctx))
6632 die("start does not take output\n"
6633 "Did you mean 'record'?");
6634 if (IS_STREAM(ctx))
6635 die("stream does not take output\n"
6636 "Did you mean 'record'?");
6637 if (ctx->output)
6638 die("only one output file allowed");
6639 ctx->output = optarg;
6640
6641 if (IS_PROFILE(ctx)) {
6642 int fd;
6643
6644 /* pipe the output to this file instead of stdout */
6645 save_stdout = dup(1);
6646 close(1);
6647 fd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0644);
6648 if (fd < 0)
6649 die("can't write to %s", optarg);
6650 if (fd != 1) {
6651 dup2(fd, 1);
6652 close(fd);
6653 }
6654 }
6655 break;
6656 case OPT_temp:
6657 if (ctx->temp)
6658 die("Only one temp directory can be listed");
6659 ctx->temp = optarg;
6660 break;
6661 case 'O':
6662 check_instance_die(ctx->instance, "-O");
6663 option = optarg;
6664 save_option(ctx->instance, option);
6665 break;
6666 case 'T':
6667 check_instance_die(ctx->instance, "-T");
6668 save_option(ctx->instance, "stacktrace");
6669 break;
6670 case 'H':
6671 cmd_check_die(ctx, CMD_set, *(argv+1), "-H");
6672 check_instance_die(ctx->instance, "-H");
6673 add_hook(ctx->instance, optarg);
6674 ctx->events = 1;
6675 break;
6676 case 's':
6677 cmd_check_die(ctx, CMD_set, *(argv+1), "-s");
6678 if (IS_EXTRACT(ctx)) {
6679 if (optarg)
6680 usage(argv);
6681 recorder_flags |= TRACECMD_RECORD_SNAPSHOT;
6682 break;
6683 }
6684 if (!optarg)
6685 usage(argv);
6686 sleep_time = atoi(optarg);
6687 break;
6688 case 'S':
6689 cmd_check_die(ctx, CMD_set, *(argv+1), "-S");
6690 ctx->manual = 1;
6691 /* User sets events for profiling */
6692 if (!event)
6693 ctx->events = 0;
6694 break;
6695 case 'r':
6696 cmd_check_die(ctx, CMD_set, *(argv+1), "-r");
6697 rt_prio = atoi(optarg);
6698 break;
6699 case 'N':
6700 cmd_check_die(ctx, CMD_set, *(argv+1), "-N");
6701 if (!IS_RECORD(ctx))
6702 die("-N only available with record");
6703 if (IS_RECORD_AGENT(ctx))
6704 die("-N incompatible with agent recording");
6705 if (ctx->output)
6706 die("-N incompatible with -o");
6707 host = optarg;
6708 break;
6709 case 'V':
6710 cmd_check_die(ctx, CMD_set, *(argv+1), "-V");
6711 if (!IS_RECORD(ctx))
6712 die("-V only available with record");
6713 if (IS_RECORD_AGENT(ctx))
6714 die("-V incompatible with agent recording");
6715 if (ctx->output)
6716 die("-V incompatible with -o");
6717 host = optarg;
6718 ctx->instance->port_type = USE_VSOCK;
6719 break;
6720 case 'm':
6721 if (max_kb)
6722 die("-m can only be specified once");
6723 if (!IS_RECORD(ctx))
6724 die("only record take 'm' option");
6725 max_kb = atoi(optarg);
6726 break;
6727 case 'M':
6728 check_instance_die(ctx->instance, "-M");
6729 ctx->instance->cpumask = alloc_mask_from_hex(ctx->instance, optarg);
6730 break;
6731 case 't':
6732 cmd_check_die(ctx, CMD_set, *(argv+1), "-t");
6733 if (IS_EXTRACT(ctx))
6734 ctx->topt = 1; /* Extract top instance also */
6735 else
6736 ctx->instance->port_type = USE_TCP;
6737 break;
6738 case 'b':
6739 check_instance_die(ctx->instance, "-b");
6740 ctx->instance->buffer_size = atoi(optarg);
6741 break;
6742 case 'B':
6743 /* Turn off proxy for the next options */
6744 is_proxy = false;
6745 ctx->instance = allocate_instance(optarg);
6746 if (!ctx->instance)
6747 die("Failed to create instance");
6748 if (IS_CMDSET(ctx))
6749 ctx->instance->delete = negative;
6750 negative = 0;
6751 if (ctx->instance->delete) {
6752 ctx->instance->next = del_list;
6753 del_list = ctx->instance;
6754 } else
6755 add_instance(ctx->instance, local_cpu_count);
6756 if (IS_PROFILE(ctx))
6757 ctx->instance->flags |= BUFFER_FL_PROFILE;
6758 break;
6759 case 'k':
6760 cmd_check_die(ctx, CMD_set, *(argv+1), "-k");
6761 keep = 1;
6762 break;
6763 case 'i':
6764 ignore_event_not_found = 1;
6765 break;
6766 case OPT_user:
6767 ctx->user = strdup(optarg);
6768 if (!ctx->user)
6769 die("Failed to allocate user name");
6770 break;
6771 case OPT_procmap:
6772 cmd_check_die(ctx, CMD_start, *(argv+1), "--proc-map");
6773 cmd_check_die(ctx, CMD_set, *(argv+1), "--proc-map");
6774 check_instance_die(ctx->instance, "--proc-map");
6775 ctx->instance->get_procmap = 1;
6776 break;
6777 case OPT_date:
6778 cmd_check_die(ctx, CMD_set, *(argv+1), "--date");
6779 ctx->date = 1;
6780 if (ctx->data_flags & DATA_FL_OFFSET)
6781 die("Can not use both --date and --ts-offset");
6782 ctx->data_flags |= DATA_FL_DATE;
6783 break;
6784 case OPT_funcstack:
6785 func_stack = 1;
6786 break;
6787 case OPT_nosplice:
6788 cmd_check_die(ctx, CMD_set, *(argv+1), "--nosplice");
6789 recorder_flags |= TRACECMD_RECORD_NOSPLICE;
6790 break;
6791 case OPT_nofifos:
6792 cmd_check_die(ctx, CMD_set, *(argv+1), "--nofifos");
6793 no_fifos = true;
6794 break;
6795 case OPT_profile:
6796 cmd_check_die(ctx, CMD_set, *(argv+1), "--profile");
6797 check_instance_die(ctx->instance, "--profile");
6798 handle_init = trace_init_profile;
6799 ctx->instance->flags |= BUFFER_FL_PROFILE;
6800 ctx->events = 1;
6801 break;
6802 case OPT_stderr:
6803 /* if -o was used (for profile), ignore this */
6804 if (save_stdout >= 0)
6805 break;
6806 save_stdout = dup(1);
6807 close(1);
6808 dup2(2, 1);
6809 break;
6810 case OPT_bycomm:
6811 cmd_check_die(ctx, CMD_set, *(argv+1), "--by-comm");
6812 trace_profile_set_merge_like_comms();
6813 break;
6814 case OPT_tsoffset:
6815 cmd_check_die(ctx, CMD_set, *(argv+1), "--ts-offset");
6816 ctx->date2ts = strdup(optarg);
6817 if (ctx->data_flags & DATA_FL_DATE)
6818 die("Can not use both --date and --ts-offset");
6819 ctx->data_flags |= DATA_FL_OFFSET;
6820 break;
6821 case OPT_max_graph_depth:
6822 check_instance_die(ctx->instance, "--max-graph-depth");
6823 free(ctx->instance->max_graph_depth);
6824 ctx->instance->max_graph_depth = strdup(optarg);
6825 if (!ctx->instance->max_graph_depth)
6826 die("Could not allocate option");
6827 break;
6828 case OPT_cmdlines_size:
6829 ctx->saved_cmdlines_size = atoi(optarg);
6830 break;
6831 case OPT_no_filter:
6832 cmd_check_die(ctx, CMD_set, *(argv+1), "--no-filter");
6833 no_filter = true;
6834 break;
6835 case OPT_debug:
6836 tracecmd_set_debug(true);
6837 break;
6838 case OPT_notimeout:
6839 tracecmd_set_notimeout(true);
6840 break;
6841 case OPT_module:
6842 check_instance_die(ctx->instance, "--module");
6843 if (ctx->instance->filter_mod)
6844 add_func(&ctx->instance->filter_funcs,
6845 ctx->instance->filter_mod, "*");
6846 ctx->instance->filter_mod = optarg;
6847 ctx->filtered = 0;
6848 break;
6849 case OPT_tsyncinterval:
6850 cmd_check_die(ctx, CMD_set, *(argv+1), "--tsync-interval");
6851 ctx->tsync_loop_interval = atoi(optarg);
6852 break;
6853 case OPT_fork:
6854 if (!IS_START(ctx))
6855 die("--fork option used for 'start' command only");
6856 fork_process = true;
6857 break;
6858 case OPT_daemonize:
6859 if (!IS_RECORD(ctx))
6860 die("--daemonize option used for 'record' command only");
6861 do_daemonize = true;
6862 break;
6863 case OPT_tsc2nsec:
6864 ret = get_tsc_nsec(&ctx->tsc2nsec.shift,
6865 &ctx->tsc2nsec.mult);
6866 if (ret)
6867 die("TSC to nanosecond is not supported");
6868 ctx->instance->flags |= BUFFER_FL_TSC2NSEC;
6869 break;
6870 case OPT_subbuf:
6871 check_instance_die(ctx->instance, "--subbuf-size");
6872 ctx->instance->subbuf_size = atoi(optarg);
6873 break;
6874 case OPT_poll:
6875 cmd_check_die(ctx, CMD_set, *(argv+1), "--poll");
6876 recorder_flags |= TRACECMD_RECORD_POLL;
6877 break;
6878 case OPT_compression:
6879 cmd_check_die(ctx, CMD_start, *(argv+1), "--compression");
6880 cmd_check_die(ctx, CMD_set, *(argv+1), "--compression");
6881 cmd_check_die(ctx, CMD_stream, *(argv+1), "--compression");
6882 cmd_check_die(ctx, CMD_profile, *(argv+1), "--compression");
6883 if (strcmp(optarg, "any") && strcmp(optarg, "none") &&
6884 !tracecmd_compress_is_supported(optarg, NULL))
6885 die("Compression algorithm %s is not supported", optarg);
6886 ctx->compression = strdup(optarg);
6887 break;
6888 case OPT_file_ver:
6889 if (ctx->curr_cmd != CMD_record && ctx->curr_cmd != CMD_record_agent)
6890 die("--file_version has no effect with the command %s\n",
6891 *(argv+1));
6892 ctx->file_version = atoi(optarg);
6893 if (ctx->file_version < FILE_VERSION_MIN ||
6894 ctx->file_version > FILE_VERSION_MAX)
6895 die("Unsupported file version %d, "
6896 "supported versions are from %d to %d",
6897 ctx->file_version, FILE_VERSION_MIN, FILE_VERSION_MAX);
6898 break;
6899 case OPT_quiet:
6900 case 'q':
6901 quiet = true;
6902 break;
6903 case OPT_verbose:
6904 if (trace_set_verbose(optarg) < 0)
6905 die("invalid verbose level %s", optarg);
6906 break;
6907 default:
6908 usage(argv);
6909 }
6910 }
6911
6912 remove_instances(del_list);
6913
6914 /* If --date is specified, prepend it to all guest VM flags */
6915 if (ctx->date) {
6916 struct buffer_instance *instance;
6917
6918 for_all_instances(instance) {
6919 if (is_guest(instance))
6920 add_argv(instance, "--date", true);
6921 }
6922 }
6923
6924 if (!ctx->filtered && ctx->instance->filter_mod)
6925 add_func(&ctx->instance->filter_funcs,
6926 ctx->instance->filter_mod, "*");
6927
6928 if (do_children && !filter_task && !fpids_count)
6929 die(" -c can only be used with -F (or -P with event-fork support)");
6930
6931 if ((argc - optind) >= 2) {
6932 if (IS_EXTRACT(ctx))
6933 die("Command extract does not take any commands\n"
6934 "Did you mean 'record'?");
6935 ctx->run_command = 1;
6936 }
6937 if (ctx->user && !ctx->run_command)
6938 warning("--user %s is ignored, no command is specified",
6939 ctx->user);
6940
6941 if (top_instance.get_procmap) {
6942 /* use ptrace to get procmap on the command exit */
6943 if (ctx->run_command) {
6944 do_ptrace = 1;
6945 } else if (!top_instance.nr_filter_pids) {
6946 warning("--proc-map is ignored for top instance, "
6947 "no command or filtered PIDs are specified.");
6948 top_instance.get_procmap = 0;
6949 }
6950 }
6951
6952 for_all_instances(instance) {
6953 if (instance->get_procmap && !instance->nr_filter_pids) {
6954 warning("--proc-map is ignored for instance %s, "
6955 "no filtered PIDs are specified.",
6956 tracefs_instance_get_name(instance->tracefs));
6957 instance->get_procmap = 0;
6958 }
6959 }
6960 }
6961
get_trace_cmd_type(enum trace_cmd cmd)6962 static enum trace_type get_trace_cmd_type(enum trace_cmd cmd)
6963 {
6964 const static struct {
6965 enum trace_cmd cmd;
6966 enum trace_type ttype;
6967 } trace_type_per_command[] = {
6968 {CMD_record, TRACE_TYPE_RECORD},
6969 {CMD_stream, TRACE_TYPE_STREAM},
6970 {CMD_extract, TRACE_TYPE_EXTRACT},
6971 {CMD_profile, TRACE_TYPE_STREAM},
6972 {CMD_start, TRACE_TYPE_START},
6973 {CMD_record_agent, TRACE_TYPE_RECORD},
6974 {CMD_set, TRACE_TYPE_SET}
6975 };
6976
6977 for (int i = 0; i < ARRAY_SIZE(trace_type_per_command); i++) {
6978 if (trace_type_per_command[i].cmd == cmd)
6979 return trace_type_per_command[i].ttype;
6980 }
6981
6982 die("Trace type UNKNOWN for the given cmd_fun");
6983 }
6984
finalize_record_trace(struct common_record_context * ctx)6985 static void finalize_record_trace(struct common_record_context *ctx)
6986 {
6987 struct buffer_instance *instance;
6988
6989 if (keep)
6990 return;
6991
6992 update_reset_files();
6993 update_reset_triggers();
6994 if (clear_function_filters)
6995 clear_func_filters();
6996
6997 set_plugin("nop");
6998
6999 tracecmd_remove_instances();
7000
7001 /* If tracing_on was enabled before we started, set it on now */
7002 for_all_instances(instance) {
7003 if (instance->flags & BUFFER_FL_KEEP)
7004 write_tracing_on(instance,
7005 instance->tracing_on_init_val);
7006 if (is_proxy_server(instance) && instance->network_handle) {
7007 /* Now wait for the recorder to be ready for us to send more */
7008 tracecmd_msg_wait(ctx->instance->msg_handle);
7009 if (ctx->tsc2nsec.mult)
7010 add_tsc2nsec(ctx->instance->network_handle, &ctx->tsc2nsec);
7011 tracecmd_write_guest_time_shift(ctx->instance->network_handle,
7012 ctx->instance->tsync);
7013 tracecmd_msg_send_options(ctx->instance->msg_handle,
7014 ctx->instance->network_handle);
7015 }
7016 if (is_agent(instance)) {
7017 tracecmd_msg_send_close_resp_msg(instance->msg_handle);
7018 tracecmd_output_close(instance->network_handle);
7019 }
7020 }
7021
7022 if (host)
7023 tracecmd_output_close(ctx->instance->network_handle);
7024 }
7025
has_local_instances(void)7026 static bool has_local_instances(void)
7027 {
7028 struct buffer_instance *instance;
7029
7030 for_all_instances(instance) {
7031 if (is_guest(instance))
7032 continue;
7033 if (host && instance->msg_handle)
7034 continue;
7035 return true;
7036 }
7037 return false;
7038 }
7039
set_tsync_params(struct common_record_context * ctx)7040 static void set_tsync_params(struct common_record_context *ctx)
7041 {
7042 struct buffer_instance *instance;
7043 int shift, mult;
7044 bool force_tsc = false;
7045 char *clock = NULL;
7046
7047 if (!ctx->clock) {
7048 /*
7049 * If no clock is configured &&
7050 * KVM time sync protocol is available &&
7051 * there is information of each guest PID process &&
7052 * tsc-x86 clock is supported &&
7053 * TSC to nsec multiplier and shift are available:
7054 * force using the x86-tsc clock for this host-guest tracing session
7055 * and store TSC to nsec multiplier and shift.
7056 */
7057 if (tsync_proto_is_supported("kvm") &&
7058 trace_have_guests_pid() &&
7059 clock_is_supported(NULL, TSC_CLOCK) &&
7060 !get_tsc_nsec(&shift, &mult) && mult) {
7061 clock = strdup(TSC_CLOCK);
7062 if (!clock)
7063 die("Cannot not allocate clock");
7064 ctx->tsc2nsec.mult = mult;
7065 ctx->tsc2nsec.shift = shift;
7066 force_tsc = true;
7067 } else { /* Use the current clock of the first host instance */
7068 clock = get_trace_clock(true);
7069 }
7070 } else {
7071 clock = strdup(ctx->clock);
7072 if (!clock)
7073 die("Cannot not allocate clock");
7074 }
7075
7076 if (!clock && !ctx->tsync_loop_interval)
7077 goto out;
7078 for_all_instances(instance) {
7079 if (clock && !(instance->flags & BUFFER_FL_HAS_CLOCK)) {
7080 /* use the same clock in all tracing peers */
7081 if (is_guest(instance)) {
7082 if (!instance->clock) {
7083 instance->clock = strdup(clock);
7084 if (!instance->clock)
7085 die("Can not allocate instance clock");
7086 }
7087 add_argv(instance, (char *)instance->clock, true);
7088 add_argv(instance, "-C", true);
7089 if (ctx->tsc2nsec.mult)
7090 instance->flags |= BUFFER_FL_TSC2NSEC;
7091 } else if (force_tsc && !instance->clock) {
7092 instance->clock = strdup(clock);
7093 if (!instance->clock)
7094 die("Can not allocate instance clock");
7095 }
7096 }
7097 instance->tsync_loop_interval = ctx->tsync_loop_interval;
7098 }
7099 out:
7100 free(clock);
7101 }
7102
record_trace(int argc,char ** argv,struct common_record_context * ctx)7103 static void record_trace(int argc, char **argv,
7104 struct common_record_context *ctx)
7105 {
7106 enum trace_type type = get_trace_cmd_type(ctx->curr_cmd);
7107 struct buffer_instance *instance;
7108 struct filter_pids *pid;
7109
7110 if (do_daemonize)
7111 daemonize_start();
7112
7113 /*
7114 * If top_instance doesn't have any plugins or events, then
7115 * remove it from being processed.
7116 */
7117 if (!__check_doing_something(&top_instance) && !filter_task)
7118 first_instance = buffer_instances;
7119 else
7120 ctx->topt = 1;
7121
7122 update_first_instance(ctx->instance, ctx->topt);
7123 if (!IS_CMDSET(ctx)) {
7124 check_doing_something();
7125 check_function_plugin();
7126 }
7127
7128 if (!ctx->output)
7129 ctx->output = DEFAULT_INPUT_FILE;
7130
7131 /* Make sure top_instance.output_file exists */
7132 if (!top_instance.output_file)
7133 top_instance.output_file = strdup(ctx->output);
7134
7135 if (ctx->data_flags & (DATA_FL_GUEST | DATA_FL_PROXY))
7136 set_tsync_params(ctx);
7137
7138 make_instances();
7139
7140 /* Save the state of tracing_on before starting */
7141 for_all_instances(instance) {
7142 if (ctx->temp)
7143 instance->temp_dir = ctx->temp;
7144 /* The -o could have been done after -B */
7145 if (!instance->output_file)
7146 instance->output_file = strdup(ctx->output);
7147 if (!instance->output_file)
7148 die("Failed to allocate output file name for instance");
7149 if (!ctx->manual && instance->flags & BUFFER_FL_PROFILE)
7150 enable_profile(instance);
7151
7152 instance->tracing_on_init_val = read_tracing_on(instance);
7153 /* Some instances may not be created yet */
7154 if (instance->tracing_on_init_val < 0)
7155 instance->tracing_on_init_val = 1;
7156 }
7157
7158 if (ctx->events)
7159 expand_event_list();
7160
7161 page_size = getpagesize();
7162
7163 if (!is_guest(ctx->instance))
7164 fset = set_ftrace(ctx->instance, !ctx->disable, ctx->total_disable);
7165 if (!IS_CMDSET(ctx))
7166 tracecmd_disable_all_tracing(1);
7167
7168 for_all_instances(instance)
7169 set_clock(ctx, instance);
7170
7171
7172 /* Record records the date first */
7173 if (ctx->date &&
7174 ((IS_RECORD(ctx) && has_local_instances()) || IS_RECORD_AGENT(ctx)))
7175 ctx->date2ts = get_date_to_ts();
7176
7177 for_all_instances(instance) {
7178 set_funcs(instance);
7179 set_mask(instance);
7180 }
7181
7182 if (ctx->events) {
7183 for_all_instances(instance)
7184 enable_events(instance);
7185 }
7186
7187 set_saved_cmdlines_size(ctx);
7188 set_buffer_size();
7189 update_plugins(type);
7190 set_options();
7191
7192 for_all_instances(instance) {
7193 if (instance->max_graph_depth) {
7194 set_max_graph_depth(instance, instance->max_graph_depth);
7195 free(instance->max_graph_depth);
7196 instance->max_graph_depth = NULL;
7197 }
7198 }
7199
7200 allocate_seq();
7201
7202 if (type & (TRACE_TYPE_RECORD | TRACE_TYPE_STREAM)) {
7203 signal(SIGINT, do_sig);
7204 signal(SIGTERM, do_sig);
7205 if (!latency)
7206 start_threads(type, ctx);
7207 }
7208
7209 if (ctx->run_command) {
7210 run_cmd(type, ctx->user, (argc - optind) - 1, &argv[optind + 1]);
7211 } else if (ctx->instance && is_agent(ctx->instance)) {
7212 update_task_filter();
7213 tracecmd_enable_tracing();
7214 tracecmd_msg_wait_close(ctx->instance->msg_handle);
7215 } else {
7216 bool pwait = false;
7217 bool wait_indefinitely = false;
7218
7219 update_task_filter();
7220
7221 if (!IS_CMDSET(ctx))
7222 tracecmd_enable_tracing();
7223
7224 if (type & (TRACE_TYPE_START | TRACE_TYPE_SET))
7225 exit(0);
7226
7227 /* We don't ptrace ourself */
7228 if (do_ptrace) {
7229 for_all_instances(instance) {
7230 for (pid = instance->filter_pids; pid; pid = pid->next) {
7231 if (!pid->exclude && instance->ptrace_child) {
7232 ptrace_attach(instance, pid->pid);
7233 pwait = true;
7234 }
7235 }
7236 }
7237 }
7238
7239 if (do_daemonize) {
7240 daemonize_finish();
7241 printf("Send SIGINT/SIGTERM to pid %d to stop recording\n", getpid());
7242 } else {
7243 /* sleep till we are woken with Ctrl^C */
7244 printf("Hit Ctrl^C to stop recording\n");
7245 }
7246
7247 for_all_instances(instance) {
7248 /* If an instance is not tracing individual processes
7249 * or there is an error while waiting for a process to
7250 * exit, fallback to waiting indefinitely.
7251 */
7252 if (!instance->nr_process_pids ||
7253 trace_wait_for_processes(instance))
7254 wait_indefinitely = true;
7255 }
7256 while (!finished && wait_indefinitely)
7257 trace_or_sleep(type, pwait);
7258 /* Streams need to be flushed one more time */
7259 if (type & TRACE_TYPE_STREAM)
7260 trace_stream_read(pids, recorder_threads, -1);
7261 }
7262
7263 tell_guests_to_stop(ctx);
7264 tracecmd_disable_tracing();
7265 if (!latency)
7266 stop_threads(type);
7267
7268 record_stats();
7269
7270 if (!latency)
7271 wait_threads();
7272
7273 if (is_proxy_server(ctx->instance) && ctx->instance->network_handle) {
7274 tracecmd_tsync_with_guest_stop(ctx->instance->tsync);
7275 trace_add_guest_info(ctx->instance->network_handle, ctx->instance);
7276 if (ctx->tsc2nsec.mult)
7277 add_tsc2nsec(ctx->instance->network_handle, &ctx->tsc2nsec);
7278 tracecmd_write_options(ctx->instance->network_handle);
7279 tracecmd_write_meta_strings(ctx->instance->network_handle);
7280 tracecmd_msg_finish_sending_data(ctx->instance->msg_handle);
7281 }
7282
7283 if (IS_RECORD(ctx)) {
7284 record_data(ctx);
7285 delete_thread_data();
7286 } else
7287 print_stats();
7288
7289 if (!keep)
7290 tracecmd_disable_all_tracing(0);
7291
7292 destroy_stats();
7293 finalize_record_trace(ctx);
7294
7295 if (created_pidfile)
7296 remove_pid_file(RECORD_PIDFILE);
7297 }
7298
7299 /*
7300 * This function contains common code for the following commands:
7301 * record, start, stream, profile.
7302 */
record_trace_command(int argc,char ** argv,struct common_record_context * ctx)7303 static void record_trace_command(int argc, char **argv,
7304 struct common_record_context *ctx)
7305 {
7306 tracecmd_tsync_init();
7307 record_trace(argc, argv, ctx);
7308 }
7309
trace_start(int argc,char ** argv)7310 void trace_start(int argc, char **argv)
7311 {
7312 struct common_record_context ctx;
7313
7314 parse_record_options(argc, argv, CMD_start, &ctx);
7315 record_trace_command(argc, argv, &ctx);
7316 exit(0);
7317 }
7318
trace_set(int argc,char ** argv)7319 void trace_set(int argc, char **argv)
7320 {
7321 struct common_record_context ctx;
7322
7323 parse_record_options(argc, argv, CMD_set, &ctx);
7324 record_trace_command(argc, argv, &ctx);
7325 exit(0);
7326 }
7327
trace_extract(int argc,char ** argv)7328 void trace_extract(int argc, char **argv)
7329 {
7330 struct common_record_context ctx;
7331 struct buffer_instance *instance;
7332 enum trace_type type;
7333
7334 parse_record_options(argc, argv, CMD_extract, &ctx);
7335
7336 type = get_trace_cmd_type(ctx.curr_cmd);
7337
7338 update_first_instance(ctx.instance, ctx.topt);
7339 check_function_plugin();
7340
7341 if (!ctx.output)
7342 ctx.output = DEFAULT_INPUT_FILE;
7343
7344 /* Save the state of tracing_on before starting */
7345 for_all_instances(instance) {
7346 instance->output_file = strdup(ctx.output);
7347 if (!instance->output_file)
7348 die("Failed to allocate output file name for instance");
7349
7350 if (!ctx.manual && instance->flags & BUFFER_FL_PROFILE)
7351 enable_profile(ctx.instance);
7352
7353 instance->tracing_on_init_val = read_tracing_on(instance);
7354 /* Some instances may not be created yet */
7355 if (instance->tracing_on_init_val < 0)
7356 instance->tracing_on_init_val = 1;
7357 }
7358
7359 /* Extracting data records all events in the system. */
7360 if (!ctx.record_all)
7361 record_all_events();
7362
7363 if (ctx.events)
7364 expand_event_list();
7365
7366 page_size = getpagesize();
7367 update_plugins(type);
7368 set_options();
7369
7370 for_all_instances(instance) {
7371 if (instance->max_graph_depth) {
7372 set_max_graph_depth(instance, instance->max_graph_depth);
7373 free(instance->max_graph_depth);
7374 instance->max_graph_depth = NULL;
7375 }
7376 }
7377
7378 allocate_seq();
7379 flush_threads();
7380 record_stats();
7381
7382 if (!keep)
7383 tracecmd_disable_all_tracing(0);
7384
7385 /* extract records the date after extraction */
7386 if (ctx.date) {
7387 /*
7388 * We need to start tracing, don't let other traces
7389 * screw with our trace_marker.
7390 */
7391 tracecmd_disable_all_tracing(1);
7392 ctx.date2ts = get_date_to_ts();
7393 }
7394
7395 record_data(&ctx);
7396 delete_thread_data();
7397 destroy_stats();
7398 finalize_record_trace(&ctx);
7399 exit(0);
7400 }
7401
trace_stream(int argc,char ** argv)7402 void trace_stream(int argc, char **argv)
7403 {
7404 struct common_record_context ctx;
7405
7406 /* Default sleep time is half a second for streaming */
7407 sleep_time = 500000;
7408
7409 parse_record_options(argc, argv, CMD_stream, &ctx);
7410 record_trace_command(argc, argv, &ctx);
7411 exit(0);
7412 }
7413
7414
trace_profile(int argc,char ** argv)7415 void trace_profile(int argc, char **argv)
7416 {
7417 struct common_record_context ctx;
7418
7419 parse_record_options(argc, argv, CMD_profile, &ctx);
7420
7421 handle_init = trace_init_profile;
7422 ctx.events = 1;
7423
7424 /*
7425 * If no instances were set, then enable profiling on the top instance.
7426 */
7427 if (!buffer_instances)
7428 top_instance.flags |= BUFFER_FL_PROFILE;
7429
7430 record_trace_command(argc, argv, &ctx);
7431 do_trace_profile();
7432 exit(0);
7433 }
7434
trace_record(int argc,char ** argv)7435 void trace_record(int argc, char **argv)
7436 {
7437 struct common_record_context ctx;
7438
7439 parse_record_options(argc, argv, CMD_record, &ctx);
7440 record_trace_command(argc, argv, &ctx);
7441 exit(0);
7442 }
7443
7444 /**
7445 * trace_record_agent - record command running from the agent
7446 * @msg_handle: The handle to communicate with the peer
7447 * @cpus: The number of CPUs the agent has to record
7448 * @fds: The array of file descriptors for the CPUs
7449 * @argc: The number of arguments to pass to the record session
7450 * @argv: The arguments to pass to the record session
7451 * @use_fifos: True if fifos are used instead of sockets.
7452 * @trace_id: The agent's trace_id
7453 * @rcid: Remote cid if the agent is a proxy, negative otherwise.
7454 * @host: Set if this is an IP connection and not a vsocket one
7455 *
7456 * This is used to enable tracing via the record command just
7457 * like trace-cmd record, but it is being done via the agent
7458 * and all the data is being transfered to the peer that is
7459 * connected on the other end of the sockets.
7460 *
7461 * Returns zero on success, negative otherwise.
7462 */
trace_record_agent(struct tracecmd_msg_handle * msg_handle,int cpus,int * fds,int argc,char ** argv,bool use_fifos,struct tracecmd_time_sync * tsync,unsigned long long trace_id,int rcid,const char * host)7463 int trace_record_agent(struct tracecmd_msg_handle *msg_handle,
7464 int cpus, int *fds,
7465 int argc, char **argv,
7466 bool use_fifos, struct tracecmd_time_sync *tsync,
7467 unsigned long long trace_id, int rcid, const char *host)
7468 {
7469 struct common_record_context ctx;
7470 char **argv_plus;
7471
7472 /* Reset optind for getopt_long */
7473 optind = 1;
7474 /*
7475 * argc is the number of elements in argv, but we need to convert
7476 * argc and argv into "trace-cmd", "record", argv.
7477 * where argc needs to grow by two.
7478 */
7479 argv_plus = calloc(argc + 2, sizeof(char *));
7480 if (!argv_plus)
7481 die("Failed to allocate record arguments");
7482
7483 argv_plus[0] = "trace-cmd";
7484 argv_plus[1] = "record";
7485 memmove(argv_plus + 2, argv, argc * sizeof(char *));
7486 argc += 2;
7487
7488 parse_record_options(argc, argv_plus, CMD_record_agent, &ctx);
7489 if (ctx.run_command)
7490 return -EINVAL;
7491
7492 ctx.instance->fds = fds;
7493 ctx.instance->use_fifos = use_fifos;
7494 ctx.instance->flags |= BUFFER_FL_AGENT;
7495 if (rcid >= 0)
7496 ctx.data_flags |= DATA_FL_PROXY;
7497 ctx.instance->msg_handle = msg_handle;
7498 ctx.instance->host = host;
7499 ctx.instance->tsync = tsync;
7500 ctx.instance->cid = rcid;
7501 msg_handle->version = V3_PROTOCOL;
7502 top_instance.trace_id = trace_id;
7503 record_trace(argc, argv, &ctx);
7504
7505 free(argv_plus);
7506 return 0;
7507 }
7508