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 calc_data_size
;
159 static ssize_t
write_or_die(const void *buf
, size_t len
)
163 if (calc_data_size
) {
164 calc_data_size
+= len
;
168 ret
= write(output_fd
, buf
, len
);
170 die("writing to '%s'", output_file
);
177 unsigned char str
[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
180 ptr
= (unsigned int *)(void *)str
;
181 return *ptr
== 0x01020304;
184 static unsigned long long copy_file_fd(int fd
)
186 unsigned long long size
= 0;
191 r
= read(fd
, buf
, BUFSIZ
);
194 write_or_die(buf
, r
);
201 static unsigned long long copy_file(const char *file
)
203 unsigned long long size
= 0;
206 fd
= open(file
, O_RDONLY
);
208 die("Can't read '%s'", file
);
209 size
= copy_file_fd(fd
);
215 static unsigned long get_size_fd(int fd
)
217 unsigned long long size
= 0;
222 r
= read(fd
, buf
, BUFSIZ
);
227 lseek(fd
, 0, SEEK_SET
);
232 static unsigned long get_size(const char *file
)
234 unsigned long long size
= 0;
237 fd
= open(file
, O_RDONLY
);
239 die("Can't read '%s'", file
);
240 size
= get_size_fd(fd
);
246 static void read_header_files(void)
248 unsigned long long size
, check_size
;
252 path
= get_tracing_file("events/header_page");
253 fd
= open(path
, O_RDONLY
);
255 die("can't read '%s'", path
);
257 /* unfortunately, you can not stat debugfs files for size */
258 size
= get_size_fd(fd
);
260 write_or_die("header_page", 12);
261 write_or_die(&size
, 8);
262 check_size
= copy_file_fd(fd
);
265 if (size
!= check_size
)
266 die("wrong size for '%s' size=%lld read=%lld",
267 path
, size
, check_size
);
268 put_tracing_file(path
);
270 path
= get_tracing_file("events/header_event");
271 fd
= open(path
, O_RDONLY
);
273 die("can't read '%s'", path
);
275 size
= get_size_fd(fd
);
277 write_or_die("header_event", 13);
278 write_or_die(&size
, 8);
279 check_size
= copy_file_fd(fd
);
280 if (size
!= check_size
)
281 die("wrong size for '%s'", path
);
282 put_tracing_file(path
);
286 static bool name_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
289 if (!strcmp(sys
, tps
->name
))
297 static void copy_event_system(const char *sys
, struct tracepoint_path
*tps
)
299 unsigned long long size
, check_size
;
309 die("can't read directory '%s'", sys
);
311 while ((dent
= readdir(dir
))) {
312 if (dent
->d_type
!= DT_DIR
||
313 strcmp(dent
->d_name
, ".") == 0 ||
314 strcmp(dent
->d_name
, "..") == 0 ||
315 !name_in_tp_list(dent
->d_name
, tps
))
317 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
318 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
319 ret
= stat(format
, &st
);
326 write_or_die(&count
, 4);
329 while ((dent
= readdir(dir
))) {
330 if (dent
->d_type
!= DT_DIR
||
331 strcmp(dent
->d_name
, ".") == 0 ||
332 strcmp(dent
->d_name
, "..") == 0 ||
333 !name_in_tp_list(dent
->d_name
, tps
))
335 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
336 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
337 ret
= stat(format
, &st
);
340 /* unfortunately, you can not stat debugfs files for size */
341 size
= get_size(format
);
342 write_or_die(&size
, 8);
343 check_size
= copy_file(format
);
344 if (size
!= check_size
)
345 die("error in size of file '%s'", format
);
353 static void read_ftrace_files(struct tracepoint_path
*tps
)
357 path
= get_tracing_file("events/ftrace");
359 copy_event_system(path
, tps
);
361 put_tracing_file(path
);
364 static bool system_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
367 if (!strcmp(sys
, tps
->system
))
375 static void read_event_files(struct tracepoint_path
*tps
)
385 path
= get_tracing_file("events");
389 die("can't read directory '%s'", path
);
391 while ((dent
= readdir(dir
))) {
392 if (dent
->d_type
!= DT_DIR
||
393 strcmp(dent
->d_name
, ".") == 0 ||
394 strcmp(dent
->d_name
, "..") == 0 ||
395 strcmp(dent
->d_name
, "ftrace") == 0 ||
396 !system_in_tp_list(dent
->d_name
, tps
))
401 write_or_die(&count
, 4);
404 while ((dent
= readdir(dir
))) {
405 if (dent
->d_type
!= DT_DIR
||
406 strcmp(dent
->d_name
, ".") == 0 ||
407 strcmp(dent
->d_name
, "..") == 0 ||
408 strcmp(dent
->d_name
, "ftrace") == 0 ||
409 !system_in_tp_list(dent
->d_name
, tps
))
411 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
412 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
413 ret
= stat(sys
, &st
);
415 write_or_die(dent
->d_name
, strlen(dent
->d_name
) + 1);
416 copy_event_system(sys
, tps
);
422 put_tracing_file(path
);
425 static void read_proc_kallsyms(void)
427 unsigned int size
, check_size
;
428 const char *path
= "/proc/kallsyms";
432 ret
= stat(path
, &st
);
436 write_or_die(&size
, 4);
439 size
= get_size(path
);
440 write_or_die(&size
, 4);
441 check_size
= copy_file(path
);
442 if (size
!= check_size
)
443 die("error in size of file '%s'", path
);
447 static void read_ftrace_printk(void)
449 unsigned int size
, check_size
;
454 path
= get_tracing_file("printk_formats");
455 ret
= stat(path
, &st
);
459 write_or_die(&size
, 4);
462 size
= get_size(path
);
463 write_or_die(&size
, 4);
464 check_size
= copy_file(path
);
465 if (size
!= check_size
)
466 die("error in size of file '%s'", path
);
468 put_tracing_file(path
);
471 static struct tracepoint_path
*
472 get_tracepoints_path(struct perf_event_attr
*pattrs
, int nb_events
)
474 struct tracepoint_path path
, *ppath
= &path
;
475 int i
, nr_tracepoints
= 0;
477 for (i
= 0; i
< nb_events
; i
++) {
478 if (pattrs
[i
].type
!= PERF_TYPE_TRACEPOINT
)
481 ppath
->next
= tracepoint_id_to_path(pattrs
[i
].config
);
483 die("%s\n", "No memory to alloc tracepoints list");
487 return nr_tracepoints
> 0 ? path
.next
: NULL
;
490 bool have_tracepoints(struct perf_event_attr
*pattrs
, int nb_events
)
494 for (i
= 0; i
< nb_events
; i
++)
495 if (pattrs
[i
].type
== PERF_TYPE_TRACEPOINT
)
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
= sysconf(_SC_PAGESIZE
);
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();
548 ssize_t
read_tracing_data_size(int fd
, struct perf_event_attr
*pattrs
,
555 err
= read_tracing_data(fd
, pattrs
, nb_events
);
556 size
= calc_data_size
- 1;