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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 #include <sys/types.h>
37 #include <linux/kernel.h>
40 #include "trace-event.h"
46 #define STR(x) _STR(x)
49 #define TRACE_CTRL "tracing_on"
51 #define AVAILABLE "available_tracers"
52 #define CURRENT "current_tracer"
53 #define ITER_CTRL "trace_options"
54 #define MAX_LATENCY "tracing_max_latency"
56 unsigned int page_size
;
58 static const char *output_file
= "trace.info";
62 struct event_list
*next
;
67 struct events
*sibling
;
68 struct events
*children
;
75 static void die(const char *fmt
, ...)
87 vfprintf(stderr
, fmt
, ap
);
90 fprintf(stderr
, "\n");
94 void *malloc_or_die(unsigned int size
)
104 static const char *find_debugfs(void)
106 const char *path
= debugfs_mount(NULL
);
109 die("Your kernel not support debugfs filesystem");
115 * Finds the path to the debugfs/tracing
116 * Allocates the string and stores it.
118 static const char *find_tracing_dir(void)
120 static char *tracing
;
121 static int tracing_found
;
127 debugfs
= find_debugfs();
129 tracing
= malloc_or_die(strlen(debugfs
) + 9);
131 sprintf(tracing
, "%s/tracing", debugfs
);
137 static char *get_tracing_file(const char *name
)
142 tracing
= find_tracing_dir();
146 file
= malloc_or_die(strlen(tracing
) + strlen(name
) + 2);
148 sprintf(file
, "%s/%s", tracing
, name
);
152 static void put_tracing_file(char *file
)
157 static ssize_t
write_or_die(const void *buf
, size_t len
)
161 ret
= write(output_fd
, buf
, len
);
163 die("writing to '%s'", output_file
);
170 unsigned char str
[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
173 ptr
= (unsigned int *)(void *)str
;
174 return *ptr
== 0x01020304;
177 static unsigned long long copy_file_fd(int fd
)
179 unsigned long long size
= 0;
184 r
= read(fd
, buf
, BUFSIZ
);
187 write_or_die(buf
, r
);
194 static unsigned long long copy_file(const char *file
)
196 unsigned long long size
= 0;
199 fd
= open(file
, O_RDONLY
);
201 die("Can't read '%s'", file
);
202 size
= copy_file_fd(fd
);
208 static unsigned long get_size_fd(int fd
)
210 unsigned long long size
= 0;
215 r
= read(fd
, buf
, BUFSIZ
);
220 lseek(fd
, 0, SEEK_SET
);
225 static unsigned long get_size(const char *file
)
227 unsigned long long size
= 0;
230 fd
= open(file
, O_RDONLY
);
232 die("Can't read '%s'", file
);
233 size
= get_size_fd(fd
);
239 static void read_header_files(void)
241 unsigned long long size
, check_size
;
245 path
= get_tracing_file("events/header_page");
246 fd
= open(path
, O_RDONLY
);
248 die("can't read '%s'", path
);
250 /* unfortunately, you can not stat debugfs files for size */
251 size
= get_size_fd(fd
);
253 write_or_die("header_page", 12);
254 write_or_die(&size
, 8);
255 check_size
= copy_file_fd(fd
);
256 if (size
!= check_size
)
257 die("wrong size for '%s' size=%lld read=%lld",
258 path
, size
, check_size
);
259 put_tracing_file(path
);
261 path
= get_tracing_file("events/header_event");
262 fd
= open(path
, O_RDONLY
);
264 die("can't read '%s'", path
);
266 size
= get_size_fd(fd
);
268 write_or_die("header_event", 13);
269 write_or_die(&size
, 8);
270 check_size
= copy_file_fd(fd
);
271 if (size
!= check_size
)
272 die("wrong size for '%s'", path
);
273 put_tracing_file(path
);
276 static bool name_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
279 if (!strcmp(sys
, tps
->name
))
287 static void copy_event_system(const char *sys
, struct tracepoint_path
*tps
)
289 unsigned long long size
, check_size
;
299 die("can't read directory '%s'", sys
);
301 while ((dent
= readdir(dir
))) {
302 if (dent
->d_type
!= DT_DIR
||
303 strcmp(dent
->d_name
, ".") == 0 ||
304 strcmp(dent
->d_name
, "..") == 0 ||
305 !name_in_tp_list(dent
->d_name
, tps
))
307 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
308 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
309 ret
= stat(format
, &st
);
316 write_or_die(&count
, 4);
319 while ((dent
= readdir(dir
))) {
320 if (dent
->d_type
!= DT_DIR
||
321 strcmp(dent
->d_name
, ".") == 0 ||
322 strcmp(dent
->d_name
, "..") == 0 ||
323 !name_in_tp_list(dent
->d_name
, tps
))
325 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
326 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
327 ret
= stat(format
, &st
);
330 /* unfortunately, you can not stat debugfs files for size */
331 size
= get_size(format
);
332 write_or_die(&size
, 8);
333 check_size
= copy_file(format
);
334 if (size
!= check_size
)
335 die("error in size of file '%s'", format
);
342 static void read_ftrace_files(struct tracepoint_path
*tps
)
346 path
= get_tracing_file("events/ftrace");
348 copy_event_system(path
, tps
);
350 put_tracing_file(path
);
353 static bool system_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
356 if (!strcmp(sys
, tps
->system
))
364 static void read_event_files(struct tracepoint_path
*tps
)
374 path
= get_tracing_file("events");
378 die("can't read directory '%s'", path
);
380 while ((dent
= readdir(dir
))) {
381 if (dent
->d_type
!= DT_DIR
||
382 strcmp(dent
->d_name
, ".") == 0 ||
383 strcmp(dent
->d_name
, "..") == 0 ||
384 strcmp(dent
->d_name
, "ftrace") == 0 ||
385 !system_in_tp_list(dent
->d_name
, tps
))
390 write_or_die(&count
, 4);
393 while ((dent
= readdir(dir
))) {
394 if (dent
->d_type
!= DT_DIR
||
395 strcmp(dent
->d_name
, ".") == 0 ||
396 strcmp(dent
->d_name
, "..") == 0 ||
397 strcmp(dent
->d_name
, "ftrace") == 0 ||
398 !system_in_tp_list(dent
->d_name
, tps
))
400 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
401 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
402 ret
= stat(sys
, &st
);
404 write_or_die(dent
->d_name
, strlen(dent
->d_name
) + 1);
405 copy_event_system(sys
, tps
);
410 put_tracing_file(path
);
413 static void read_proc_kallsyms(void)
415 unsigned int size
, check_size
;
416 const char *path
= "/proc/kallsyms";
420 ret
= stat(path
, &st
);
424 write_or_die(&size
, 4);
427 size
= get_size(path
);
428 write_or_die(&size
, 4);
429 check_size
= copy_file(path
);
430 if (size
!= check_size
)
431 die("error in size of file '%s'", path
);
435 static void read_ftrace_printk(void)
437 unsigned int size
, check_size
;
442 path
= get_tracing_file("printk_formats");
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
);
456 put_tracing_file(path
);
459 static struct tracepoint_path
*
460 get_tracepoints_path(struct perf_event_attr
*pattrs
, int nb_events
)
462 struct tracepoint_path path
, *ppath
= &path
;
463 int i
, nr_tracepoints
= 0;
465 for (i
= 0; i
< nb_events
; i
++) {
466 if (pattrs
[i
].type
!= PERF_TYPE_TRACEPOINT
)
469 ppath
->next
= tracepoint_id_to_path(pattrs
[i
].config
);
471 die("%s\n", "No memory to alloc tracepoints list");
475 return nr_tracepoints
> 0 ? path
.next
: NULL
;
478 int read_tracing_data(int fd
, struct perf_event_attr
*pattrs
, int nb_events
)
481 struct tracepoint_path
*tps
= get_tracepoints_path(pattrs
, nb_events
);
484 * What? No tracepoints? No sense writing anything here, bail out.
494 memcpy(buf
+ 3, "tracing", 7);
496 write_or_die(buf
, 10);
498 write_or_die(VERSION
, strlen(VERSION
) + 1);
506 write_or_die(buf
, 1);
508 /* save size of long */
509 buf
[0] = sizeof(long);
510 write_or_die(buf
, 1);
513 page_size
= getpagesize();
514 write_or_die(&page_size
, 4);
517 read_ftrace_files(tps
);
518 read_event_files(tps
);
519 read_proc_kallsyms();
520 read_ftrace_printk();