]>
Commit | Line | Data |
---|---|---|
016e92fb FW |
1 | #include "data_map.h" |
2 | #include "symbol.h" | |
3 | #include "util.h" | |
4 | #include "debug.h" | |
5 | ||
6 | ||
7 | static struct perf_file_handler *curr_handler; | |
8 | static unsigned long mmap_window = 32; | |
9 | static char __cwd[PATH_MAX]; | |
10 | ||
62daacb5 | 11 | static int process_event_stub(event_t *event __used) |
016e92fb | 12 | { |
62daacb5 | 13 | dump_printf(": unhandled!\n"); |
016e92fb FW |
14 | return 0; |
15 | } | |
16 | ||
17 | void register_perf_file_handler(struct perf_file_handler *handler) | |
18 | { | |
19 | if (!handler->process_sample_event) | |
20 | handler->process_sample_event = process_event_stub; | |
21 | if (!handler->process_mmap_event) | |
22 | handler->process_mmap_event = process_event_stub; | |
23 | if (!handler->process_comm_event) | |
24 | handler->process_comm_event = process_event_stub; | |
25 | if (!handler->process_fork_event) | |
26 | handler->process_fork_event = process_event_stub; | |
27 | if (!handler->process_exit_event) | |
28 | handler->process_exit_event = process_event_stub; | |
29 | if (!handler->process_lost_event) | |
30 | handler->process_lost_event = process_event_stub; | |
31 | if (!handler->process_read_event) | |
32 | handler->process_read_event = process_event_stub; | |
33 | if (!handler->process_throttle_event) | |
34 | handler->process_throttle_event = process_event_stub; | |
35 | if (!handler->process_unthrottle_event) | |
36 | handler->process_unthrottle_event = process_event_stub; | |
37 | ||
38 | curr_handler = handler; | |
39 | } | |
40 | ||
62daacb5 ACM |
41 | static const char *event__name[] = { |
42 | [0] = "TOTAL", | |
43 | [PERF_RECORD_MMAP] = "MMAP", | |
44 | [PERF_RECORD_LOST] = "LOST", | |
45 | [PERF_RECORD_COMM] = "COMM", | |
46 | [PERF_RECORD_EXIT] = "EXIT", | |
47 | [PERF_RECORD_THROTTLE] = "THROTTLE", | |
48 | [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", | |
49 | [PERF_RECORD_FORK] = "FORK", | |
50 | [PERF_RECORD_READ] = "READ", | |
51 | [PERF_RECORD_SAMPLE] = "SAMPLE", | |
52 | }; | |
53 | ||
54 | unsigned long event__total[PERF_RECORD_MAX]; | |
55 | ||
56 | void event__print_totals(void) | |
57 | { | |
58 | int i; | |
59 | for (i = 0; i < PERF_RECORD_MAX; ++i) | |
60 | pr_info("%10s events: %10ld\n", | |
61 | event__name[i], event__total[i]); | |
62 | } | |
63 | ||
016e92fb FW |
64 | static int |
65 | process_event(event_t *event, unsigned long offset, unsigned long head) | |
66 | { | |
67 | trace_event(event); | |
68 | ||
62daacb5 ACM |
69 | if (event->header.type < PERF_RECORD_MAX) { |
70 | dump_printf("%p [%p]: PERF_RECORD_%s", | |
71 | (void *)(offset + head), | |
72 | (void *)(long)(event->header.size), | |
73 | event__name[event->header.type]); | |
74 | ++event__total[0]; | |
75 | ++event__total[event->header.type]; | |
76 | } | |
77 | ||
016e92fb FW |
78 | switch (event->header.type) { |
79 | case PERF_RECORD_SAMPLE: | |
62daacb5 | 80 | return curr_handler->process_sample_event(event); |
016e92fb | 81 | case PERF_RECORD_MMAP: |
62daacb5 | 82 | return curr_handler->process_mmap_event(event); |
016e92fb | 83 | case PERF_RECORD_COMM: |
62daacb5 | 84 | return curr_handler->process_comm_event(event); |
016e92fb | 85 | case PERF_RECORD_FORK: |
62daacb5 | 86 | return curr_handler->process_fork_event(event); |
016e92fb | 87 | case PERF_RECORD_EXIT: |
62daacb5 | 88 | return curr_handler->process_exit_event(event); |
016e92fb | 89 | case PERF_RECORD_LOST: |
62daacb5 | 90 | return curr_handler->process_lost_event(event); |
016e92fb | 91 | case PERF_RECORD_READ: |
62daacb5 | 92 | return curr_handler->process_read_event(event); |
016e92fb | 93 | case PERF_RECORD_THROTTLE: |
62daacb5 | 94 | return curr_handler->process_throttle_event(event); |
016e92fb | 95 | case PERF_RECORD_UNTHROTTLE: |
62daacb5 | 96 | return curr_handler->process_unthrottle_event(event); |
016e92fb FW |
97 | default: |
98 | curr_handler->total_unknown++; | |
99 | return -1; | |
100 | } | |
101 | } | |
102 | ||
716d69e4 | 103 | int perf_header__read_build_ids(int input, u64 offset, u64 size) |
8d06367f | 104 | { |
8d06367f ACM |
105 | struct build_id_event bev; |
106 | char filename[PATH_MAX]; | |
716d69e4 | 107 | u64 limit = offset + size; |
8d06367f ACM |
108 | int err = -1; |
109 | ||
9e827dd0 | 110 | while (offset < limit) { |
8d06367f ACM |
111 | struct dso *dso; |
112 | ssize_t len; | |
113 | ||
114 | if (read(input, &bev, sizeof(bev)) != sizeof(bev)) | |
115 | goto out; | |
116 | ||
117 | len = bev.header.size - sizeof(bev); | |
118 | if (read(input, filename, len) != len) | |
119 | goto out; | |
120 | ||
121 | dso = dsos__findnew(filename); | |
122 | if (dso != NULL) | |
123 | dso__set_build_id(dso, &bev.build_id); | |
124 | ||
125 | offset += bev.header.size; | |
126 | } | |
127 | err = 0; | |
128 | out: | |
129 | return err; | |
130 | } | |
131 | ||
94c744b6 ACM |
132 | int perf_session__process_events(struct perf_session *self, |
133 | int full_paths, int *cwdlen, char **cwd) | |
016e92fb | 134 | { |
6b0cb5f9 | 135 | int err; |
016e92fb FW |
136 | unsigned long head, shift; |
137 | unsigned long offset = 0; | |
016e92fb FW |
138 | size_t page_size; |
139 | u64 sample_type; | |
140 | event_t *event; | |
141 | uint32_t size; | |
016e92fb FW |
142 | char *buf; |
143 | ||
6b0cb5f9 ACM |
144 | if (curr_handler == NULL) { |
145 | pr_debug("Forgot to register perf file handler\n"); | |
146 | return -EINVAL; | |
147 | } | |
016e92fb FW |
148 | |
149 | page_size = getpagesize(); | |
150 | ||
94c744b6 ACM |
151 | head = self->header.data_offset; |
152 | sample_type = perf_header__sample_type(&self->header); | |
016e92fb | 153 | |
6b0cb5f9 ACM |
154 | err = -EINVAL; |
155 | if (curr_handler->sample_type_check && | |
156 | curr_handler->sample_type_check(sample_type) < 0) | |
94c744b6 | 157 | goto out_err; |
016e92fb | 158 | |
016e92fb FW |
159 | if (!full_paths) { |
160 | if (getcwd(__cwd, sizeof(__cwd)) == NULL) { | |
6b0cb5f9 ACM |
161 | pr_err("failed to get the current directory\n"); |
162 | err = -errno; | |
94c744b6 | 163 | goto out_err; |
016e92fb FW |
164 | } |
165 | *cwd = __cwd; | |
166 | *cwdlen = strlen(*cwd); | |
167 | } else { | |
168 | *cwd = NULL; | |
169 | *cwdlen = 0; | |
170 | } | |
171 | ||
172 | shift = page_size * (head / page_size); | |
173 | offset += shift; | |
174 | head -= shift; | |
175 | ||
176 | remap: | |
6b0cb5f9 | 177 | buf = mmap(NULL, page_size * mmap_window, PROT_READ, |
94c744b6 | 178 | MAP_SHARED, self->fd, offset); |
016e92fb | 179 | if (buf == MAP_FAILED) { |
6b0cb5f9 ACM |
180 | pr_err("failed to mmap file\n"); |
181 | err = -errno; | |
94c744b6 | 182 | goto out_err; |
016e92fb FW |
183 | } |
184 | ||
185 | more: | |
186 | event = (event_t *)(buf + head); | |
187 | ||
188 | size = event->header.size; | |
189 | if (!size) | |
190 | size = 8; | |
191 | ||
192 | if (head + event->header.size >= page_size * mmap_window) { | |
193 | int munmap_ret; | |
194 | ||
195 | shift = page_size * (head / page_size); | |
196 | ||
197 | munmap_ret = munmap(buf, page_size * mmap_window); | |
198 | assert(munmap_ret == 0); | |
199 | ||
200 | offset += shift; | |
201 | head -= shift; | |
202 | goto remap; | |
203 | } | |
204 | ||
205 | size = event->header.size; | |
206 | ||
207 | dump_printf("\n%p [%p]: event: %d\n", | |
208 | (void *)(offset + head), | |
209 | (void *)(long)event->header.size, | |
210 | event->header.type); | |
211 | ||
212 | if (!size || process_event(event, offset, head) < 0) { | |
213 | ||
214 | dump_printf("%p [%p]: skipping unknown header type: %d\n", | |
215 | (void *)(offset + head), | |
216 | (void *)(long)(event->header.size), | |
217 | event->header.type); | |
218 | ||
219 | /* | |
220 | * assume we lost track of the stream, check alignment, and | |
221 | * increment a single u64 in the hope to catch on again 'soon'. | |
222 | */ | |
223 | ||
224 | if (unlikely(head & 7)) | |
225 | head &= ~7ULL; | |
226 | ||
227 | size = 8; | |
228 | } | |
229 | ||
230 | head += size; | |
231 | ||
94c744b6 | 232 | if (offset + head >= self->header.data_offset + self->header.data_size) |
016e92fb FW |
233 | goto done; |
234 | ||
94c744b6 | 235 | if (offset + head < self->size) |
016e92fb FW |
236 | goto more; |
237 | ||
238 | done: | |
6b0cb5f9 | 239 | err = 0; |
94c744b6 | 240 | out_err: |
6b0cb5f9 | 241 | return err; |
016e92fb | 242 | } |