7 static struct perf_file_handler
*curr_handler
;
8 static unsigned long mmap_window
= 32;
9 static char __cwd
[PATH_MAX
];
12 process_event_stub(event_t
*event __used
,
13 unsigned long offset __used
,
14 unsigned long head __used
)
19 void register_perf_file_handler(struct perf_file_handler
*handler
)
21 if (!handler
->process_sample_event
)
22 handler
->process_sample_event
= process_event_stub
;
23 if (!handler
->process_mmap_event
)
24 handler
->process_mmap_event
= process_event_stub
;
25 if (!handler
->process_comm_event
)
26 handler
->process_comm_event
= process_event_stub
;
27 if (!handler
->process_fork_event
)
28 handler
->process_fork_event
= process_event_stub
;
29 if (!handler
->process_exit_event
)
30 handler
->process_exit_event
= process_event_stub
;
31 if (!handler
->process_lost_event
)
32 handler
->process_lost_event
= process_event_stub
;
33 if (!handler
->process_read_event
)
34 handler
->process_read_event
= process_event_stub
;
35 if (!handler
->process_throttle_event
)
36 handler
->process_throttle_event
= process_event_stub
;
37 if (!handler
->process_unthrottle_event
)
38 handler
->process_unthrottle_event
= process_event_stub
;
40 curr_handler
= handler
;
44 process_event(event_t
*event
, unsigned long offset
, unsigned long head
)
48 switch (event
->header
.type
) {
49 case PERF_RECORD_SAMPLE
:
50 return curr_handler
->process_sample_event(event
, offset
, head
);
51 case PERF_RECORD_MMAP
:
52 return curr_handler
->process_mmap_event(event
, offset
, head
);
53 case PERF_RECORD_COMM
:
54 return curr_handler
->process_comm_event(event
, offset
, head
);
55 case PERF_RECORD_FORK
:
56 return curr_handler
->process_fork_event(event
, offset
, head
);
57 case PERF_RECORD_EXIT
:
58 return curr_handler
->process_exit_event(event
, offset
, head
);
59 case PERF_RECORD_LOST
:
60 return curr_handler
->process_lost_event(event
, offset
, head
);
61 case PERF_RECORD_READ
:
62 return curr_handler
->process_read_event(event
, offset
, head
);
63 case PERF_RECORD_THROTTLE
:
64 return curr_handler
->process_throttle_event(event
, offset
, head
);
65 case PERF_RECORD_UNTHROTTLE
:
66 return curr_handler
->process_unthrottle_event(event
, offset
, head
);
68 curr_handler
->total_unknown
++;
73 int mmap_dispatch_perf_file(struct perf_header
**pheader
,
74 const char *input_name
,
80 int ret
, rc
= EXIT_FAILURE
;
81 struct perf_header
*header
;
82 unsigned long head
, shift
;
83 unsigned long offset
= 0;
84 struct stat input_stat
;
93 die("Forgot to register perf file handler");
95 page_size
= getpagesize();
97 input
= open(input_name
, O_RDONLY
);
99 fprintf(stderr
, " failed to open file: %s", input_name
);
100 if (!strcmp(input_name
, "perf.data"))
101 fprintf(stderr
, " (try 'perf record' first)");
102 fprintf(stderr
, "\n");
106 ret
= fstat(input
, &input_stat
);
108 perror("failed to stat file");
112 if (!force
&& input_stat
.st_uid
&& (input_stat
.st_uid
!= geteuid())) {
113 fprintf(stderr
, "file: %s not owned by current user or root\n",
118 if (!input_stat
.st_size
) {
119 fprintf(stderr
, "zero-sized file, nothing to do!\n");
123 *pheader
= perf_header__read(input
);
125 head
= header
->data_offset
;
127 sample_type
= perf_header__sample_type(header
);
129 if (curr_handler
->sample_type_check
)
130 if (curr_handler
->sample_type_check(sample_type
) < 0)
133 if (load_kernel() < 0) {
134 perror("failed to load kernel symbols");
139 if (getcwd(__cwd
, sizeof(__cwd
)) == NULL
) {
140 perror("failed to get the current directory");
144 *cwdlen
= strlen(*cwd
);
150 shift
= page_size
* (head
/ page_size
);
155 buf
= (char *)mmap(NULL
, page_size
* mmap_window
, PROT_READ
,
156 MAP_SHARED
, input
, offset
);
157 if (buf
== MAP_FAILED
) {
158 perror("failed to mmap file");
163 event
= (event_t
*)(buf
+ head
);
165 size
= event
->header
.size
;
169 if (head
+ event
->header
.size
>= page_size
* mmap_window
) {
172 shift
= page_size
* (head
/ page_size
);
174 munmap_ret
= munmap(buf
, page_size
* mmap_window
);
175 assert(munmap_ret
== 0);
182 size
= event
->header
.size
;
184 dump_printf("\n%p [%p]: event: %d\n",
185 (void *)(offset
+ head
),
186 (void *)(long)event
->header
.size
,
189 if (!size
|| process_event(event
, offset
, head
) < 0) {
191 dump_printf("%p [%p]: skipping unknown header type: %d\n",
192 (void *)(offset
+ head
),
193 (void *)(long)(event
->header
.size
),
197 * assume we lost track of the stream, check alignment, and
198 * increment a single u64 in the hope to catch on again 'soon'.
201 if (unlikely(head
& 7))
209 if (offset
+ head
>= header
->data_offset
+ header
->data_size
)
212 if (offset
+ head
< (unsigned long)input_stat
.st_size
)