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 /* unfortunately, you can not stat debugfs or proc files for size */
187 static void record_file(const char *file
, size_t hdr_sz
)
189 unsigned long long size
= 0;
190 char buf
[BUFSIZ
], *sizep
;
191 off_t hdr_pos
= lseek(output_fd
, 0, SEEK_CUR
);
194 fd
= open(file
, O_RDONLY
);
196 die("Can't read '%s'", file
);
198 /* put in zeros for file size, then fill true size later */
199 write_or_die(&size
, hdr_sz
);
202 r
= read(fd
, buf
, BUFSIZ
);
205 write_or_die(buf
, r
);
210 /* ugh, handle big-endian hdr_size == 4 */
211 sizep
= (char*)&size
;
213 sizep
+= sizeof(u64
) - hdr_sz
;
215 if (pwrite(output_fd
, sizep
, hdr_sz
, hdr_pos
) < 0)
216 die("writing to %s", output_file
);
219 static void read_header_files(void)
224 path
= get_tracing_file("events/header_page");
225 if (stat(path
, &st
) < 0)
226 die("can't read '%s'", path
);
228 write_or_die("header_page", 12);
229 record_file(path
, 8);
230 put_tracing_file(path
);
232 path
= get_tracing_file("events/header_event");
233 if (stat(path
, &st
) < 0)
234 die("can't read '%s'", path
);
236 write_or_die("header_event", 13);
237 record_file(path
, 8);
238 put_tracing_file(path
);
241 static bool name_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
244 if (!strcmp(sys
, tps
->name
))
252 static void copy_event_system(const char *sys
, struct tracepoint_path
*tps
)
263 die("can't read directory '%s'", sys
);
265 while ((dent
= readdir(dir
))) {
266 if (dent
->d_type
!= DT_DIR
||
267 strcmp(dent
->d_name
, ".") == 0 ||
268 strcmp(dent
->d_name
, "..") == 0 ||
269 !name_in_tp_list(dent
->d_name
, tps
))
271 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
272 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
273 ret
= stat(format
, &st
);
280 write_or_die(&count
, 4);
283 while ((dent
= readdir(dir
))) {
284 if (dent
->d_type
!= DT_DIR
||
285 strcmp(dent
->d_name
, ".") == 0 ||
286 strcmp(dent
->d_name
, "..") == 0 ||
287 !name_in_tp_list(dent
->d_name
, tps
))
289 format
= malloc_or_die(strlen(sys
) + strlen(dent
->d_name
) + 10);
290 sprintf(format
, "%s/%s/format", sys
, dent
->d_name
);
291 ret
= stat(format
, &st
);
294 record_file(format
, 8);
301 static void read_ftrace_files(struct tracepoint_path
*tps
)
305 path
= get_tracing_file("events/ftrace");
307 copy_event_system(path
, tps
);
309 put_tracing_file(path
);
312 static bool system_in_tp_list(char *sys
, struct tracepoint_path
*tps
)
315 if (!strcmp(sys
, tps
->system
))
323 static void read_event_files(struct tracepoint_path
*tps
)
333 path
= get_tracing_file("events");
337 die("can't read directory '%s'", path
);
339 while ((dent
= readdir(dir
))) {
340 if (dent
->d_type
!= DT_DIR
||
341 strcmp(dent
->d_name
, ".") == 0 ||
342 strcmp(dent
->d_name
, "..") == 0 ||
343 strcmp(dent
->d_name
, "ftrace") == 0 ||
344 !system_in_tp_list(dent
->d_name
, tps
))
349 write_or_die(&count
, 4);
352 while ((dent
= readdir(dir
))) {
353 if (dent
->d_type
!= DT_DIR
||
354 strcmp(dent
->d_name
, ".") == 0 ||
355 strcmp(dent
->d_name
, "..") == 0 ||
356 strcmp(dent
->d_name
, "ftrace") == 0 ||
357 !system_in_tp_list(dent
->d_name
, tps
))
359 sys
= malloc_or_die(strlen(path
) + strlen(dent
->d_name
) + 2);
360 sprintf(sys
, "%s/%s", path
, dent
->d_name
);
361 ret
= stat(sys
, &st
);
363 write_or_die(dent
->d_name
, strlen(dent
->d_name
) + 1);
364 copy_event_system(sys
, tps
);
370 put_tracing_file(path
);
373 static void read_proc_kallsyms(void)
376 const char *path
= "/proc/kallsyms";
380 ret
= stat(path
, &st
);
384 write_or_die(&size
, 4);
387 record_file(path
, 4);
390 static void read_ftrace_printk(void)
397 path
= get_tracing_file("printk_formats");
398 ret
= stat(path
, &st
);
402 write_or_die(&size
, 4);
405 record_file(path
, 4);
408 put_tracing_file(path
);
411 static struct tracepoint_path
*
412 get_tracepoints_path(struct list_head
*pattrs
)
414 struct tracepoint_path path
, *ppath
= &path
;
415 struct perf_evsel
*pos
;
416 int nr_tracepoints
= 0;
418 list_for_each_entry(pos
, pattrs
, node
) {
419 if (pos
->attr
.type
!= PERF_TYPE_TRACEPOINT
)
422 ppath
->next
= tracepoint_id_to_path(pos
->attr
.config
);
424 die("%s\n", "No memory to alloc tracepoints list");
428 return nr_tracepoints
> 0 ? path
.next
: NULL
;
431 bool have_tracepoints(struct list_head
*pattrs
)
433 struct perf_evsel
*pos
;
435 list_for_each_entry(pos
, pattrs
, node
)
436 if (pos
->attr
.type
== PERF_TYPE_TRACEPOINT
)
442 int read_tracing_data(int fd
, struct list_head
*pattrs
)
445 struct tracepoint_path
*tps
= get_tracepoints_path(pattrs
);
448 * What? No tracepoints? No sense writing anything here, bail out.
458 memcpy(buf
+ 3, "tracing", 7);
460 write_or_die(buf
, 10);
462 write_or_die(VERSION
, strlen(VERSION
) + 1);
470 write_or_die(buf
, 1);
472 /* save size of long */
473 buf
[0] = sizeof(long);
474 write_or_die(buf
, 1);
477 page_size
= sysconf(_SC_PAGESIZE
);
478 write_or_die(&page_size
, 4);
481 read_ftrace_files(tps
);
482 read_event_files(tps
);
483 read_proc_kallsyms();
484 read_ftrace_printk();
489 ssize_t
read_tracing_data_size(int fd
, struct list_head
*pattrs
)
495 err
= read_tracing_data(fd
, pattrs
);
496 size
= calc_data_size
- 1;