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/list.h>
38 #include <linux/kernel.h>
41 #include "trace-event.h"
48 #define STR(x) _STR(x)
51 #define TRACE_CTRL "tracing_on"
53 #define AVAILABLE "available_tracers"
54 #define CURRENT "current_tracer"
55 #define ITER_CTRL "trace_options"
56 #define MAX_LATENCY "tracing_max_latency"
58 unsigned int page_size
;
60 static const char *output_file
= "trace.info";
64 struct event_list
*next
;
69 struct events
*sibling
;
70 struct events
*children
;
77 static void die(const char *fmt
, ...)
89 vfprintf(stderr
, fmt
, ap
);
92 fprintf(stderr
, "\n");
96 void *malloc_or_die(unsigned int size
)
106 static const char *find_debugfs(void)
108 const char *path
= debugfs_mount(NULL
);
111 die("Your kernel not support debugfs filesystem");
117 * Finds the path to the debugfs/tracing
118 * Allocates the string and stores it.
120 static const char *find_tracing_dir(void)
122 static char *tracing
;
123 static int tracing_found
;
129 debugfs
= find_debugfs();
131 tracing
= malloc_or_die(strlen(debugfs
) + 9);
133 sprintf(tracing
, "%s/tracing", debugfs
);
139 static char *get_tracing_file(const char *name
)
144 tracing
= find_tracing_dir();
148 file
= malloc_or_die(strlen(tracing
) + strlen(name
) + 2);
150 sprintf(file
, "%s/%s", tracing
, name
);
154 static void put_tracing_file(char *file
)
159 static ssize_t calc_data_size
;
161 static ssize_t
write_or_die(const void *buf
, size_t len
)
165 if (calc_data_size
) {
166 calc_data_size
+= len
;
170 ret
= write(output_fd
, buf
, len
);
172 die("writing to '%s'", output_file
);
179 unsigned char str
[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0};
182 ptr
= (unsigned int *)(void *)str
;
183 return *ptr
== 0x01020304;
186 static unsigned long long copy_file_fd(int fd
)
188 unsigned long long size
= 0;
193 r
= read(fd
, buf
, BUFSIZ
);
196 write_or_die(buf
, r
);
203 static unsigned long long copy_file(const char *file
)
205 unsigned long long size
= 0;
208 fd
= open(file
, O_RDONLY
);
210 die("Can't read '%s'", file
);
211 size
= copy_file_fd(fd
);
217 static unsigned long get_size_fd(int fd
)
219 unsigned long long size
= 0;
224 r
= read(fd
, buf
, BUFSIZ
);
229 lseek(fd
, 0, SEEK_SET
);
234 static unsigned long get_size(const char *file
)
236 unsigned long long size
= 0;
239 fd
= open(file
, O_RDONLY
);
241 die("Can't read '%s'", file
);
242 size
= get_size_fd(fd
);
248 static void read_header_files(void)
250 unsigned long long size
, check_size
;
254 path
= get_tracing_file("events/header_page");
255 fd
= open(path
, O_RDONLY
);
257 die("can't read '%s'", path
);
259 /* unfortunately, you can not stat debugfs files for size */
260 size
= get_size_fd(fd
);
262 write_or_die("header_page", 12);
263 write_or_die(&size
, 8);
264 check_size
= copy_file_fd(fd
);
267 if (size
!= check_size
)
268 die("wrong size for '%s' size=%lld read=%lld",
269 path
, size
, check_size
);
270 put_tracing_file(path
);
272 path
= get_tracing_file("events/header_event");
273 fd
= open(path
, O_RDONLY
);
275 die("can't read '%s'", path
);
277 size
= get_size_fd(fd
);
279 write_or_die("header_event", 13);
280 write_or_die(&size
, 8);
281 check_size
= copy_file_fd(fd
);
282 if (size
!= check_size
)
283 die("wrong size for '%s'", path
);
284 put_tracing_file(path
);
288 static bool name_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
291 if (!strcmp(sys
, tps
->name
))
299 static void copy_event_system(const char *sys
, struct tracepoint_path
*tps
)
301 unsigned long long size
, check_size
;
311 die("can't read directory '%s'", sys
);
313 while ((dent
= readdir(dir
))) {
314 if (dent
->d_type
!= DT_DIR
||
315 strcmp(dent
->d_name
, ".") == 0 ||
316 strcmp(dent
->d_name
, "..") == 0 ||
317 !name_in_tp_list(dent
->d_name
, tps
))
319 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
320 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
321 ret
= stat(format
, &st
);
328 write_or_die(&count
, 4);
331 while ((dent
= readdir(dir
))) {
332 if (dent
->d_type
!= DT_DIR
||
333 strcmp(dent
->d_name
, ".") == 0 ||
334 strcmp(dent
->d_name
, "..") == 0 ||
335 !name_in_tp_list(dent
->d_name
, tps
))
337 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
338 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
339 ret
= stat(format
, &st
);
342 /* unfortunately, you can not stat debugfs files for size */
343 size
= get_size(format
);
344 write_or_die(&size
, 8);
345 check_size
= copy_file(format
);
346 if (size
!= check_size
)
347 die("error in size of file '%s'", format
);
355 static void read_ftrace_files(struct tracepoint_path
*tps
)
359 path
= get_tracing_file("events/ftrace");
361 copy_event_system(path
, tps
);
363 put_tracing_file(path
);
366 static bool system_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
369 if (!strcmp(sys
, tps
->system
))
377 static void read_event_files(struct tracepoint_path
*tps
)
387 path
= get_tracing_file("events");
391 die("can't read directory '%s'", path
);
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
))
403 write_or_die(&count
, 4);
406 while ((dent
= readdir(dir
))) {
407 if (dent
->d_type
!= DT_DIR
||
408 strcmp(dent
->d_name
, ".") == 0 ||
409 strcmp(dent
->d_name
, "..") == 0 ||
410 strcmp(dent
->d_name
, "ftrace") == 0 ||
411 !system_in_tp_list(dent
->d_name
, tps
))
413 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
414 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
415 ret
= stat(sys
, &st
);
417 write_or_die(dent
->d_name
, strlen(dent
->d_name
) + 1);
418 copy_event_system(sys
, tps
);
424 put_tracing_file(path
);
427 static void read_proc_kallsyms(void)
429 unsigned int size
, check_size
;
430 const char *path
= "/proc/kallsyms";
434 ret
= stat(path
, &st
);
438 write_or_die(&size
, 4);
441 size
= get_size(path
);
442 write_or_die(&size
, 4);
443 check_size
= copy_file(path
);
444 if (size
!= check_size
)
445 die("error in size of file '%s'", path
);
449 static void read_ftrace_printk(void)
451 unsigned int size
, check_size
;
456 path
= get_tracing_file("printk_formats");
457 ret
= stat(path
, &st
);
461 write_or_die(&size
, 4);
464 size
= get_size(path
);
465 write_or_die(&size
, 4);
466 check_size
= copy_file(path
);
467 if (size
!= check_size
)
468 die("error in size of file '%s'", path
);
470 put_tracing_file(path
);
473 static struct tracepoint_path
*
474 get_tracepoints_path(struct list_head
*pattrs
)
476 struct tracepoint_path path
, *ppath
= &path
;
477 struct perf_evsel
*pos
;
478 int nr_tracepoints
= 0;
480 list_for_each_entry(pos
, pattrs
, node
) {
481 if (pos
->attr
.type
!= PERF_TYPE_TRACEPOINT
)
484 ppath
->next
= tracepoint_id_to_path(pos
->attr
.config
);
486 die("%s\n", "No memory to alloc tracepoints list");
490 return nr_tracepoints
> 0 ? path
.next
: NULL
;
493 bool have_tracepoints(struct list_head
*pattrs
)
495 struct perf_evsel
*pos
;
497 list_for_each_entry(pos
, pattrs
, node
)
498 if (pos
->attr
.type
== PERF_TYPE_TRACEPOINT
)
504 int read_tracing_data(int fd
, struct list_head
*pattrs
)
507 struct tracepoint_path
*tps
= get_tracepoints_path(pattrs
);
510 * What? No tracepoints? No sense writing anything here, bail out.
520 memcpy(buf
+ 3, "tracing", 7);
522 write_or_die(buf
, 10);
524 write_or_die(VERSION
, strlen(VERSION
) + 1);
532 write_or_die(buf
, 1);
534 /* save size of long */
535 buf
[0] = sizeof(long);
536 write_or_die(buf
, 1);
539 page_size
= sysconf(_SC_PAGESIZE
);
540 write_or_die(&page_size
, 4);
543 read_ftrace_files(tps
);
544 read_event_files(tps
);
545 read_proc_kallsyms();
546 read_ftrace_printk();
551 ssize_t
read_tracing_data_size(int fd
, struct list_head
*pattrs
)
557 err
= read_tracing_data(fd
, pattrs
);
558 size
= calc_data_size
- 1;