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 perf_header__read_build_ids(int input
, off_t offset
, off_t size
)
75 struct build_id_event bev
;
76 char filename
[PATH_MAX
];
77 off_t limit
= offset
+ size
;
80 while (offset
< limit
) {
84 if (read(input
, &bev
, sizeof(bev
)) != sizeof(bev
))
87 len
= bev
.header
.size
- sizeof(bev
);
88 if (read(input
, filename
, len
) != len
)
91 dso
= dsos__findnew(filename
);
93 dso__set_build_id(dso
, &bev
.build_id
);
95 offset
+= bev
.header
.size
;
102 int mmap_dispatch_perf_file(struct perf_header
**pheader
,
103 const char *input_name
,
110 struct perf_header
*header
;
111 unsigned long head
, shift
;
112 unsigned long offset
= 0;
113 struct stat input_stat
;
121 if (curr_handler
== NULL
) {
122 pr_debug("Forgot to register perf file handler\n");
126 page_size
= getpagesize();
128 input
= open(input_name
, O_RDONLY
);
130 pr_err("Failed to open file: %s", input_name
);
131 if (!strcmp(input_name
, "perf.data"))
132 pr_err(" (try 'perf record' first)");
137 if (fstat(input
, &input_stat
) < 0) {
138 pr_err("failed to stat file");
144 if (!force
&& input_stat
.st_uid
&& (input_stat
.st_uid
!= geteuid())) {
145 pr_err("file: %s not owned by current user or root\n",
150 if (input_stat
.st_size
== 0) {
151 pr_info("zero-sized file, nothing to do!\n");
156 header
= perf_header__new();
160 err
= perf_header__read(header
, input
);
164 head
= header
->data_offset
;
166 sample_type
= perf_header__sample_type(header
);
169 if (curr_handler
->sample_type_check
&&
170 curr_handler
->sample_type_check(sample_type
) < 0)
174 if (kernel_maps__init(true) < 0) {
175 pr_err("failed to setup the kernel maps to resolve symbols\n");
180 if (getcwd(__cwd
, sizeof(__cwd
)) == NULL
) {
181 pr_err("failed to get the current directory\n");
186 *cwdlen
= strlen(*cwd
);
192 shift
= page_size
* (head
/ page_size
);
197 buf
= mmap(NULL
, page_size
* mmap_window
, PROT_READ
,
198 MAP_SHARED
, input
, offset
);
199 if (buf
== MAP_FAILED
) {
200 pr_err("failed to mmap file\n");
206 event
= (event_t
*)(buf
+ head
);
208 size
= event
->header
.size
;
212 if (head
+ event
->header
.size
>= page_size
* mmap_window
) {
215 shift
= page_size
* (head
/ page_size
);
217 munmap_ret
= munmap(buf
, page_size
* mmap_window
);
218 assert(munmap_ret
== 0);
225 size
= event
->header
.size
;
227 dump_printf("\n%p [%p]: event: %d\n",
228 (void *)(offset
+ head
),
229 (void *)(long)event
->header
.size
,
232 if (!size
|| process_event(event
, offset
, head
) < 0) {
234 dump_printf("%p [%p]: skipping unknown header type: %d\n",
235 (void *)(offset
+ head
),
236 (void *)(long)(event
->header
.size
),
240 * assume we lost track of the stream, check alignment, and
241 * increment a single u64 in the hope to catch on again 'soon'.
244 if (unlikely(head
& 7))
252 if (offset
+ head
>= header
->data_offset
+ header
->data_size
)
255 if (offset
+ head
< (unsigned long)input_stat
.st_size
)
265 perf_header__delete(header
);