4 #include "util/cache.h"
5 #include "util/symbol.h"
6 #include "util/thread.h"
7 #include "util/header.h"
9 #include "util/parse-options.h"
12 #include "util/debug.h"
14 #include "util/trace-event.h"
16 static char const *input_name
= "perf.data";
18 static unsigned long page_size
;
19 static unsigned long mmap_window
= 32;
21 static unsigned long total
= 0;
22 static unsigned long total_comm
= 0;
24 static struct rb_root threads
;
25 static struct thread
*last_match
;
27 static struct perf_header
*header
;
28 static u64 sample_type
;
32 process_comm_event(event_t
*event
, unsigned long offset
, unsigned long head
)
34 struct thread
*thread
;
36 thread
= threads__findnew(event
->comm
.pid
, &threads
, &last_match
);
38 dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
39 (void *)(offset
+ head
),
40 (void *)(long)(event
->header
.size
),
41 event
->comm
.comm
, event
->comm
.pid
);
44 thread__set_comm(thread
, event
->comm
.comm
)) {
45 dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
54 process_sample_event(event_t
*event
, unsigned long offset
, unsigned long head
)
58 struct dso
*dso
= NULL
;
59 struct thread
*thread
;
60 u64 ip
= event
->ip
.ip
;
62 void *more_data
= event
->ip
.__more_data
;
65 thread
= threads__findnew(event
->ip
.pid
, &threads
, &last_match
);
67 if (sample_type
& PERF_SAMPLE_PERIOD
) {
68 period
= *(u64
*)more_data
;
69 more_data
+= sizeof(u64
);
72 dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
73 (void *)(offset
+ head
),
74 (void *)(long)(event
->header
.size
),
76 event
->ip
.pid
, event
->ip
.tid
,
80 dump_printf(" ... thread: %s:%d\n", thread
->comm
, thread
->pid
);
83 eprintf("problem processing %d event, skipping it.\n",
88 cpumode
= event
->header
.misc
& PERF_EVENT_MISC_CPUMODE_MASK
;
90 if (cpumode
== PERF_EVENT_MISC_KERNEL
) {
96 dump_printf(" ...... dso: %s\n", dso
->name
);
98 } else if (cpumode
== PERF_EVENT_MISC_USER
) {
107 dso
= hypervisor_dso
;
109 dump_printf(" ...... dso: [hypervisor]\n");
112 if (sample_type
& PERF_SAMPLE_RAW
) {
119 * FIXME: better resolve from pid from the struct trace_entry
120 * field, although it should be the same than this perf
123 print_event(0, raw
->data
, raw
->size
, 0, thread
->comm
);
131 process_event(event_t
*event
, unsigned long offset
, unsigned long head
)
135 switch (event
->header
.type
) {
136 case PERF_EVENT_MMAP
... PERF_EVENT_LOST
:
139 case PERF_EVENT_COMM
:
140 return process_comm_event(event
, offset
, head
);
142 case PERF_EVENT_EXIT
... PERF_EVENT_READ
:
145 case PERF_EVENT_SAMPLE
:
146 return process_sample_event(event
, offset
, head
);
156 static int __cmd_trace(void)
158 int ret
, rc
= EXIT_FAILURE
;
159 unsigned long offset
= 0;
160 unsigned long head
= 0;
161 struct stat perf_stat
;
168 input
= open(input_name
, O_RDONLY
);
170 perror("failed to open file");
174 ret
= fstat(input
, &perf_stat
);
176 perror("failed to stat file");
180 if (!perf_stat
.st_size
) {
181 fprintf(stderr
, "zero-sized file, nothing to do!\n");
184 header
= perf_header__read(input
);
185 sample_type
= perf_header__sample_type(header
);
187 if (!(sample_type
& PERF_SAMPLE_RAW
))
188 die("No trace sample to read. Did you call perf record "
191 if (load_kernel() < 0) {
192 perror("failed to load kernel symbols");
197 buf
= (char *)mmap(NULL
, page_size
* mmap_window
, PROT_READ
,
198 MAP_SHARED
, input
, offset
);
199 if (buf
== MAP_FAILED
) {
200 perror("failed to mmap file");
205 event
= (event_t
*)(buf
+ head
);
207 size
= event
->header
.size
;
211 if (head
+ event
->header
.size
>= page_size
* mmap_window
) {
212 unsigned long shift
= page_size
* (head
/ page_size
);
215 res
= munmap(buf
, page_size
* mmap_window
);
223 size
= event
->header
.size
;
226 if (!size
|| process_event(event
, offset
, head
) < 0) {
229 * assume we lost track of the stream, check alignment, and
230 * increment a single u64 in the hope to catch on again 'soon'.
233 if (unlikely(head
& 7))
241 if (offset
+ head
< (unsigned long)perf_stat
.st_size
)
250 static const char * const annotate_usage
[] = {
251 "perf trace [<options>] <command>",
255 static const struct option options
[] = {
256 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace
,
257 "dump raw trace in ASCII"),
258 OPT_BOOLEAN('v', "verbose", &verbose
,
259 "be more verbose (show symbol address, etc)"),
263 int cmd_trace(int argc
, const char **argv
, const char *prefix __used
)
266 page_size
= getpagesize();
268 argc
= parse_options(argc
, argv
, options
, annotate_usage
, 0);
271 * Special case: if there's an argument left then assume tha
272 * it's a symbol filter:
275 usage_with_options(annotate_usage
, options
);
281 return __cmd_trace();