2 * Copyright (C) 2008,2009, Steven Rostedt <srostedt@redhat.com>
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License (not later!)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 #include <sys/types.h>
36 #include <linux/kernel.h>
39 #include "trace-event.h"
44 #define STR(x) _STR(x)
47 #define TRACE_CTRL "tracing_on"
49 #define AVAILABLE "available_tracers"
50 #define CURRENT "current_tracer"
51 #define ITER_CTRL "trace_options"
52 #define MAX_LATENCY "tracing_max_latency"
54 unsigned int page_size
;
56 static const char *output_file
= "trace.info";
60 struct event_list
*next
;
65 struct events
*sibling
;
66 struct events
*children
;
73 static void die(const char *fmt
, ...)
85 vfprintf(stderr
, fmt
, ap
);
88 fprintf(stderr
, "\n");
92 void *malloc_or_die(unsigned int size
)
102 static const char *find_debugfs(void)
104 static char debugfs
[MAX_PATH
+1];
105 static int debugfs_found
;
112 if ((fp
= fopen("/proc/mounts","r")) == NULL
)
113 die("Can't open /proc/mounts for read");
115 while (fscanf(fp
, "%*s %"
117 "s %99s %*s %*d %*d\n",
118 debugfs
, type
) == 2) {
119 if (strcmp(type
, "debugfs") == 0)
124 if (strcmp(type
, "debugfs") != 0)
125 die("debugfs not mounted, please mount");
133 * Finds the path to the debugfs/tracing
134 * Allocates the string and stores it.
136 static const char *find_tracing_dir(void)
138 static char *tracing
;
139 static int tracing_found
;
145 debugfs
= find_debugfs();
147 tracing
= malloc_or_die(strlen(debugfs
) + 9);
149 sprintf(tracing
, "%s/tracing", debugfs
);
155 static char *get_tracing_file(const char *name
)
160 tracing
= find_tracing_dir();
164 file
= malloc_or_die(strlen(tracing
) + strlen(name
) + 2);
166 sprintf(file
, "%s/%s", tracing
, name
);
170 static void put_tracing_file(char *file
)
175 static ssize_t
write_or_die(const void *buf
, size_t len
)
179 ret
= write(output_fd
, buf
, len
);
181 die("writing to '%s'", output_file
);
188 unsigned char str
[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
191 ptr
= (unsigned int *)(void *)str
;
192 return *ptr
== 0x01020304;
195 static unsigned long long copy_file_fd(int fd
)
197 unsigned long long size
= 0;
202 r
= read(fd
, buf
, BUFSIZ
);
205 write_or_die(buf
, r
);
212 static unsigned long long copy_file(const char *file
)
214 unsigned long long size
= 0;
217 fd
= open(file
, O_RDONLY
);
219 die("Can't read '%s'", file
);
220 size
= copy_file_fd(fd
);
226 static unsigned long get_size_fd(int fd
)
228 unsigned long long size
= 0;
233 r
= read(fd
, buf
, BUFSIZ
);
238 lseek(fd
, 0, SEEK_SET
);
243 static unsigned long get_size(const char *file
)
245 unsigned long long size
= 0;
248 fd
= open(file
, O_RDONLY
);
250 die("Can't read '%s'", file
);
251 size
= get_size_fd(fd
);
257 static void read_header_files(void)
259 unsigned long long size
, check_size
;
263 path
= get_tracing_file("events/header_page");
264 fd
= open(path
, O_RDONLY
);
266 die("can't read '%s'", path
);
268 /* unfortunately, you can not stat debugfs files for size */
269 size
= get_size_fd(fd
);
271 write_or_die("header_page", 12);
272 write_or_die(&size
, 8);
273 check_size
= copy_file_fd(fd
);
274 if (size
!= check_size
)
275 die("wrong size for '%s' size=%lld read=%lld",
276 path
, size
, check_size
);
277 put_tracing_file(path
);
279 path
= get_tracing_file("events/header_event");
280 fd
= open(path
, O_RDONLY
);
282 die("can't read '%s'", path
);
284 size
= get_size_fd(fd
);
286 write_or_die("header_event", 13);
287 write_or_die(&size
, 8);
288 check_size
= copy_file_fd(fd
);
289 if (size
!= check_size
)
290 die("wrong size for '%s'", path
);
291 put_tracing_file(path
);
294 static bool name_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
297 if (!strcmp(sys
, tps
->name
))
305 static void copy_event_system(const char *sys
, struct tracepoint_path
*tps
)
307 unsigned long long size
, check_size
;
317 die("can't read directory '%s'", sys
);
319 while ((dent
= readdir(dir
))) {
320 if (strcmp(dent
->d_name
, ".") == 0 ||
321 strcmp(dent
->d_name
, "..") == 0 ||
322 !name_in_tp_list(dent
->d_name
, tps
))
324 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
325 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
326 ret
= stat(format
, &st
);
333 write_or_die(&count
, 4);
336 while ((dent
= readdir(dir
))) {
337 if (strcmp(dent
->d_name
, ".") == 0 ||
338 strcmp(dent
->d_name
, "..") == 0 ||
339 !name_in_tp_list(dent
->d_name
, tps
))
341 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
342 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
343 ret
= stat(format
, &st
);
346 /* unfortunately, you can not stat debugfs files for size */
347 size
= get_size(format
);
348 write_or_die(&size
, 8);
349 check_size
= copy_file(format
);
350 if (size
!= check_size
)
351 die("error in size of file '%s'", format
);
358 static void read_ftrace_files(struct tracepoint_path
*tps
)
362 path
= get_tracing_file("events/ftrace");
364 copy_event_system(path
, tps
);
366 put_tracing_file(path
);
369 static bool system_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
372 if (!strcmp(sys
, tps
->system
))
380 static void read_event_files(struct tracepoint_path
*tps
)
390 path
= get_tracing_file("events");
394 die("can't read directory '%s'", path
);
396 while ((dent
= readdir(dir
))) {
397 if (strcmp(dent
->d_name
, ".") == 0 ||
398 strcmp(dent
->d_name
, "..") == 0 ||
399 strcmp(dent
->d_name
, "ftrace") == 0 ||
400 !system_in_tp_list(dent
->d_name
, tps
))
402 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
403 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
404 ret
= stat(sys
, &st
);
408 if (S_ISDIR(st
.st_mode
))
412 write_or_die(&count
, 4);
415 while ((dent
= readdir(dir
))) {
416 if (strcmp(dent
->d_name
, ".") == 0 ||
417 strcmp(dent
->d_name
, "..") == 0 ||
418 strcmp(dent
->d_name
, "ftrace") == 0 ||
419 !system_in_tp_list(dent
->d_name
, tps
))
421 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
422 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
423 ret
= stat(sys
, &st
);
425 if (S_ISDIR(st
.st_mode
)) {
426 write_or_die(dent
->d_name
, strlen(dent
->d_name
) + 1);
427 copy_event_system(sys
, tps
);
433 put_tracing_file(path
);
436 static void read_proc_kallsyms(void)
438 unsigned int size
, check_size
;
439 const char *path
= "/proc/kallsyms";
443 ret
= stat(path
, &st
);
447 write_or_die(&size
, 4);
450 size
= get_size(path
);
451 write_or_die(&size
, 4);
452 check_size
= copy_file(path
);
453 if (size
!= check_size
)
454 die("error in size of file '%s'", path
);
458 static void read_ftrace_printk(void)
460 unsigned int size
, check_size
;
465 path
= get_tracing_file("printk_formats");
466 ret
= stat(path
, &st
);
470 write_or_die(&size
, 4);
473 size
= get_size(path
);
474 write_or_die(&size
, 4);
475 check_size
= copy_file(path
);
476 if (size
!= check_size
)
477 die("error in size of file '%s'", path
);
479 put_tracing_file(path
);
482 static struct tracepoint_path
*
483 get_tracepoints_path(struct perf_event_attr
*pattrs
, int nb_events
)
485 struct tracepoint_path path
, *ppath
= &path
;
486 int i
, nr_tracepoints
= 0;
488 for (i
= 0; i
< nb_events
; i
++) {
489 if (pattrs
[i
].type
!= PERF_TYPE_TRACEPOINT
)
492 ppath
->next
= tracepoint_id_to_path(pattrs
[i
].config
);
494 die("%s\n", "No memory to alloc tracepoints list");
498 return nr_tracepoints
> 0 ? path
.next
: NULL
;
501 int read_tracing_data(int fd
, struct perf_event_attr
*pattrs
, int nb_events
)
504 struct tracepoint_path
*tps
= get_tracepoints_path(pattrs
, nb_events
);
507 * What? No tracepoints? No sense writing anything here, bail out.
517 memcpy(buf
+ 3, "tracing", 7);
519 write_or_die(buf
, 10);
521 write_or_die(VERSION
, strlen(VERSION
) + 1);
529 write_or_die(buf
, 1);
531 /* save size of long */
532 buf
[0] = sizeof(long);
533 write_or_die(buf
, 1);
536 page_size
= getpagesize();
537 write_or_die(&page_size
, 4);
540 read_ftrace_files(tps
);
541 read_event_files(tps
);
542 read_proc_kallsyms();
543 read_ftrace_printk();