diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /tools/perf/util/event.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r-- | tools/perf/util/event.c | 596 |
1 files changed, 281 insertions, 315 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index dab9e754a281..3c1b8a632101 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -6,29 +6,48 @@ | |||
6 | #include "string.h" | 6 | #include "string.h" |
7 | #include "strlist.h" | 7 | #include "strlist.h" |
8 | #include "thread.h" | 8 | #include "thread.h" |
9 | #include "thread_map.h" | ||
10 | |||
11 | static const char *perf_event__names[] = { | ||
12 | [0] = "TOTAL", | ||
13 | [PERF_RECORD_MMAP] = "MMAP", | ||
14 | [PERF_RECORD_LOST] = "LOST", | ||
15 | [PERF_RECORD_COMM] = "COMM", | ||
16 | [PERF_RECORD_EXIT] = "EXIT", | ||
17 | [PERF_RECORD_THROTTLE] = "THROTTLE", | ||
18 | [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", | ||
19 | [PERF_RECORD_FORK] = "FORK", | ||
20 | [PERF_RECORD_READ] = "READ", | ||
21 | [PERF_RECORD_SAMPLE] = "SAMPLE", | ||
22 | [PERF_RECORD_HEADER_ATTR] = "ATTR", | ||
23 | [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", | ||
24 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", | ||
25 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | ||
26 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", | ||
27 | }; | ||
28 | |||
29 | const char *perf_event__name(unsigned int id) | ||
30 | { | ||
31 | if (id >= ARRAY_SIZE(perf_event__names)) | ||
32 | return "INVALID"; | ||
33 | if (!perf_event__names[id]) | ||
34 | return "UNKNOWN"; | ||
35 | return perf_event__names[id]; | ||
36 | } | ||
9 | 37 | ||
10 | const char *event__name[] = { | 38 | static struct perf_sample synth_sample = { |
11 | [0] = "TOTAL", | 39 | .pid = -1, |
12 | [PERF_RECORD_MMAP] = "MMAP", | 40 | .tid = -1, |
13 | [PERF_RECORD_LOST] = "LOST", | 41 | .time = -1, |
14 | [PERF_RECORD_COMM] = "COMM", | 42 | .stream_id = -1, |
15 | [PERF_RECORD_EXIT] = "EXIT", | 43 | .cpu = -1, |
16 | [PERF_RECORD_THROTTLE] = "THROTTLE", | 44 | .period = 1, |
17 | [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", | ||
18 | [PERF_RECORD_FORK] = "FORK", | ||
19 | [PERF_RECORD_READ] = "READ", | ||
20 | [PERF_RECORD_SAMPLE] = "SAMPLE", | ||
21 | [PERF_RECORD_HEADER_ATTR] = "ATTR", | ||
22 | [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", | ||
23 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", | ||
24 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | ||
25 | }; | 45 | }; |
26 | 46 | ||
27 | static pid_t event__synthesize_comm(pid_t pid, int full, | 47 | static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, |
28 | event__handler_t process, | 48 | int full, perf_event__handler_t process, |
29 | struct perf_session *session) | 49 | struct perf_session *session) |
30 | { | 50 | { |
31 | event_t ev; | ||
32 | char filename[PATH_MAX]; | 51 | char filename[PATH_MAX]; |
33 | char bf[BUFSIZ]; | 52 | char bf[BUFSIZ]; |
34 | FILE *fp; | 53 | FILE *fp; |
@@ -49,34 +68,39 @@ out_race: | |||
49 | return 0; | 68 | return 0; |
50 | } | 69 | } |
51 | 70 | ||
52 | memset(&ev.comm, 0, sizeof(ev.comm)); | 71 | memset(&event->comm, 0, sizeof(event->comm)); |
53 | while (!ev.comm.comm[0] || !ev.comm.pid) { | 72 | |
54 | if (fgets(bf, sizeof(bf), fp) == NULL) | 73 | while (!event->comm.comm[0] || !event->comm.pid) { |
55 | goto out_failure; | 74 | if (fgets(bf, sizeof(bf), fp) == NULL) { |
75 | pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); | ||
76 | goto out; | ||
77 | } | ||
56 | 78 | ||
57 | if (memcmp(bf, "Name:", 5) == 0) { | 79 | if (memcmp(bf, "Name:", 5) == 0) { |
58 | char *name = bf + 5; | 80 | char *name = bf + 5; |
59 | while (*name && isspace(*name)) | 81 | while (*name && isspace(*name)) |
60 | ++name; | 82 | ++name; |
61 | size = strlen(name) - 1; | 83 | size = strlen(name) - 1; |
62 | memcpy(ev.comm.comm, name, size++); | 84 | memcpy(event->comm.comm, name, size++); |
63 | } else if (memcmp(bf, "Tgid:", 5) == 0) { | 85 | } else if (memcmp(bf, "Tgid:", 5) == 0) { |
64 | char *tgids = bf + 5; | 86 | char *tgids = bf + 5; |
65 | while (*tgids && isspace(*tgids)) | 87 | while (*tgids && isspace(*tgids)) |
66 | ++tgids; | 88 | ++tgids; |
67 | tgid = ev.comm.pid = atoi(tgids); | 89 | tgid = event->comm.pid = atoi(tgids); |
68 | } | 90 | } |
69 | } | 91 | } |
70 | 92 | ||
71 | ev.comm.header.type = PERF_RECORD_COMM; | 93 | event->comm.header.type = PERF_RECORD_COMM; |
72 | size = ALIGN(size, sizeof(u64)); | 94 | size = ALIGN(size, sizeof(u64)); |
73 | ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); | 95 | memset(event->comm.comm + size, 0, session->id_hdr_size); |
74 | 96 | event->comm.header.size = (sizeof(event->comm) - | |
97 | (sizeof(event->comm.comm) - size) + | ||
98 | session->id_hdr_size); | ||
75 | if (!full) { | 99 | if (!full) { |
76 | ev.comm.tid = pid; | 100 | event->comm.tid = pid; |
77 | 101 | ||
78 | process(&ev, session); | 102 | process(event, &synth_sample, session); |
79 | goto out_fclose; | 103 | goto out; |
80 | } | 104 | } |
81 | 105 | ||
82 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | 106 | snprintf(filename, sizeof(filename), "/proc/%d/task", pid); |
@@ -91,24 +115,22 @@ out_race: | |||
91 | if (*end) | 115 | if (*end) |
92 | continue; | 116 | continue; |
93 | 117 | ||
94 | ev.comm.tid = pid; | 118 | event->comm.tid = pid; |
95 | 119 | ||
96 | process(&ev, session); | 120 | process(event, &synth_sample, session); |
97 | } | 121 | } |
98 | closedir(tasks); | ||
99 | 122 | ||
100 | out_fclose: | 123 | closedir(tasks); |
124 | out: | ||
101 | fclose(fp); | 125 | fclose(fp); |
102 | return tgid; | ||
103 | 126 | ||
104 | out_failure: | 127 | return tgid; |
105 | pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); | ||
106 | return -1; | ||
107 | } | 128 | } |
108 | 129 | ||
109 | static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | 130 | static int perf_event__synthesize_mmap_events(union perf_event *event, |
110 | event__handler_t process, | 131 | pid_t pid, pid_t tgid, |
111 | struct perf_session *session) | 132 | perf_event__handler_t process, |
133 | struct perf_session *session) | ||
112 | { | 134 | { |
113 | char filename[PATH_MAX]; | 135 | char filename[PATH_MAX]; |
114 | FILE *fp; | 136 | FILE *fp; |
@@ -124,29 +146,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
124 | return -1; | 146 | return -1; |
125 | } | 147 | } |
126 | 148 | ||
149 | event->header.type = PERF_RECORD_MMAP; | ||
150 | /* | ||
151 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | ||
152 | */ | ||
153 | event->header.misc = PERF_RECORD_MISC_USER; | ||
154 | |||
127 | while (1) { | 155 | while (1) { |
128 | char bf[BUFSIZ], *pbf = bf; | 156 | char bf[BUFSIZ], *pbf = bf; |
129 | event_t ev = { | ||
130 | .header = { | ||
131 | .type = PERF_RECORD_MMAP, | ||
132 | /* | ||
133 | * Just like the kernel, see __perf_event_mmap | ||
134 | * in kernel/perf_event.c | ||
135 | */ | ||
136 | .misc = PERF_RECORD_MISC_USER, | ||
137 | }, | ||
138 | }; | ||
139 | int n; | 157 | int n; |
140 | size_t size; | 158 | size_t size; |
141 | if (fgets(bf, sizeof(bf), fp) == NULL) | 159 | if (fgets(bf, sizeof(bf), fp) == NULL) |
142 | break; | 160 | break; |
143 | 161 | ||
144 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ | 162 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ |
145 | n = hex2u64(pbf, &ev.mmap.start); | 163 | n = hex2u64(pbf, &event->mmap.start); |
146 | if (n < 0) | 164 | if (n < 0) |
147 | continue; | 165 | continue; |
148 | pbf += n + 1; | 166 | pbf += n + 1; |
149 | n = hex2u64(pbf, &ev.mmap.len); | 167 | n = hex2u64(pbf, &event->mmap.len); |
150 | if (n < 0) | 168 | if (n < 0) |
151 | continue; | 169 | continue; |
152 | pbf += n + 3; | 170 | pbf += n + 3; |
@@ -161,19 +179,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
161 | continue; | 179 | continue; |
162 | 180 | ||
163 | pbf += 3; | 181 | pbf += 3; |
164 | n = hex2u64(pbf, &ev.mmap.pgoff); | 182 | n = hex2u64(pbf, &event->mmap.pgoff); |
165 | 183 | ||
166 | size = strlen(execname); | 184 | size = strlen(execname); |
167 | execname[size - 1] = '\0'; /* Remove \n */ | 185 | execname[size - 1] = '\0'; /* Remove \n */ |
168 | memcpy(ev.mmap.filename, execname, size); | 186 | memcpy(event->mmap.filename, execname, size); |
169 | size = ALIGN(size, sizeof(u64)); | 187 | size = ALIGN(size, sizeof(u64)); |
170 | ev.mmap.len -= ev.mmap.start; | 188 | event->mmap.len -= event->mmap.start; |
171 | ev.mmap.header.size = (sizeof(ev.mmap) - | 189 | event->mmap.header.size = (sizeof(event->mmap) - |
172 | (sizeof(ev.mmap.filename) - size)); | 190 | (sizeof(event->mmap.filename) - size)); |
173 | ev.mmap.pid = tgid; | 191 | memset(event->mmap.filename + size, 0, session->id_hdr_size); |
174 | ev.mmap.tid = pid; | 192 | event->mmap.header.size += session->id_hdr_size; |
175 | 193 | event->mmap.pid = tgid; | |
176 | process(&ev, session); | 194 | event->mmap.tid = pid; |
195 | |||
196 | process(event, &synth_sample, session); | ||
177 | } | 197 | } |
178 | } | 198 | } |
179 | 199 | ||
@@ -181,26 +201,33 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
181 | return 0; | 201 | return 0; |
182 | } | 202 | } |
183 | 203 | ||
184 | int event__synthesize_modules(event__handler_t process, | 204 | int perf_event__synthesize_modules(perf_event__handler_t process, |
185 | struct perf_session *session, | 205 | struct perf_session *session, |
186 | struct machine *machine) | 206 | struct machine *machine) |
187 | { | 207 | { |
188 | struct rb_node *nd; | 208 | struct rb_node *nd; |
189 | struct map_groups *kmaps = &machine->kmaps; | 209 | struct map_groups *kmaps = &machine->kmaps; |
190 | u16 misc; | 210 | union perf_event *event = zalloc((sizeof(event->mmap) + |
211 | session->id_hdr_size)); | ||
212 | if (event == NULL) { | ||
213 | pr_debug("Not enough memory synthesizing mmap event " | ||
214 | "for kernel modules\n"); | ||
215 | return -1; | ||
216 | } | ||
217 | |||
218 | event->header.type = PERF_RECORD_MMAP; | ||
191 | 219 | ||
192 | /* | 220 | /* |
193 | * kernel uses 0 for user space maps, see kernel/perf_event.c | 221 | * kernel uses 0 for user space maps, see kernel/perf_event.c |
194 | * __perf_event_mmap | 222 | * __perf_event_mmap |
195 | */ | 223 | */ |
196 | if (machine__is_host(machine)) | 224 | if (machine__is_host(machine)) |
197 | misc = PERF_RECORD_MISC_KERNEL; | 225 | event->header.misc = PERF_RECORD_MISC_KERNEL; |
198 | else | 226 | else |
199 | misc = PERF_RECORD_MISC_GUEST_KERNEL; | 227 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
200 | 228 | ||
201 | for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); | 229 | for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); |
202 | nd; nd = rb_next(nd)) { | 230 | nd; nd = rb_next(nd)) { |
203 | event_t ev; | ||
204 | size_t size; | 231 | size_t size; |
205 | struct map *pos = rb_entry(nd, struct map, rb_node); | 232 | struct map *pos = rb_entry(nd, struct map, rb_node); |
206 | 233 | ||
@@ -208,39 +235,87 @@ int event__synthesize_modules(event__handler_t process, | |||
208 | continue; | 235 | continue; |
209 | 236 | ||
210 | size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); | 237 | size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); |
211 | memset(&ev, 0, sizeof(ev)); | 238 | event->mmap.header.type = PERF_RECORD_MMAP; |
212 | ev.mmap.header.misc = misc; | 239 | event->mmap.header.size = (sizeof(event->mmap) - |
213 | ev.mmap.header.type = PERF_RECORD_MMAP; | 240 | (sizeof(event->mmap.filename) - size)); |
214 | ev.mmap.header.size = (sizeof(ev.mmap) - | 241 | memset(event->mmap.filename + size, 0, session->id_hdr_size); |
215 | (sizeof(ev.mmap.filename) - size)); | 242 | event->mmap.header.size += session->id_hdr_size; |
216 | ev.mmap.start = pos->start; | 243 | event->mmap.start = pos->start; |
217 | ev.mmap.len = pos->end - pos->start; | 244 | event->mmap.len = pos->end - pos->start; |
218 | ev.mmap.pid = machine->pid; | 245 | event->mmap.pid = machine->pid; |
219 | 246 | ||
220 | memcpy(ev.mmap.filename, pos->dso->long_name, | 247 | memcpy(event->mmap.filename, pos->dso->long_name, |
221 | pos->dso->long_name_len + 1); | 248 | pos->dso->long_name_len + 1); |
222 | process(&ev, session); | 249 | process(event, &synth_sample, session); |
223 | } | 250 | } |
224 | 251 | ||
252 | free(event); | ||
225 | return 0; | 253 | return 0; |
226 | } | 254 | } |
227 | 255 | ||
228 | int event__synthesize_thread(pid_t pid, event__handler_t process, | 256 | static int __event__synthesize_thread(union perf_event *comm_event, |
229 | struct perf_session *session) | 257 | union perf_event *mmap_event, |
258 | pid_t pid, perf_event__handler_t process, | ||
259 | struct perf_session *session) | ||
230 | { | 260 | { |
231 | pid_t tgid = event__synthesize_comm(pid, 1, process, session); | 261 | pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, |
262 | session); | ||
232 | if (tgid == -1) | 263 | if (tgid == -1) |
233 | return -1; | 264 | return -1; |
234 | return event__synthesize_mmap_events(pid, tgid, process, session); | 265 | return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, |
266 | process, session); | ||
267 | } | ||
268 | |||
269 | int perf_event__synthesize_thread_map(struct thread_map *threads, | ||
270 | perf_event__handler_t process, | ||
271 | struct perf_session *session) | ||
272 | { | ||
273 | union perf_event *comm_event, *mmap_event; | ||
274 | int err = -1, thread; | ||
275 | |||
276 | comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); | ||
277 | if (comm_event == NULL) | ||
278 | goto out; | ||
279 | |||
280 | mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); | ||
281 | if (mmap_event == NULL) | ||
282 | goto out_free_comm; | ||
283 | |||
284 | err = 0; | ||
285 | for (thread = 0; thread < threads->nr; ++thread) { | ||
286 | if (__event__synthesize_thread(comm_event, mmap_event, | ||
287 | threads->map[thread], | ||
288 | process, session)) { | ||
289 | err = -1; | ||
290 | break; | ||
291 | } | ||
292 | } | ||
293 | free(mmap_event); | ||
294 | out_free_comm: | ||
295 | free(comm_event); | ||
296 | out: | ||
297 | return err; | ||
235 | } | 298 | } |
236 | 299 | ||
237 | void event__synthesize_threads(event__handler_t process, | 300 | int perf_event__synthesize_threads(perf_event__handler_t process, |
238 | struct perf_session *session) | 301 | struct perf_session *session) |
239 | { | 302 | { |
240 | DIR *proc; | 303 | DIR *proc; |
241 | struct dirent dirent, *next; | 304 | struct dirent dirent, *next; |
305 | union perf_event *comm_event, *mmap_event; | ||
306 | int err = -1; | ||
307 | |||
308 | comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); | ||
309 | if (comm_event == NULL) | ||
310 | goto out; | ||
311 | |||
312 | mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); | ||
313 | if (mmap_event == NULL) | ||
314 | goto out_free_comm; | ||
242 | 315 | ||
243 | proc = opendir("/proc"); | 316 | proc = opendir("/proc"); |
317 | if (proc == NULL) | ||
318 | goto out_free_mmap; | ||
244 | 319 | ||
245 | while (!readdir_r(proc, &dirent, &next) && next) { | 320 | while (!readdir_r(proc, &dirent, &next) && next) { |
246 | char *end; | 321 | char *end; |
@@ -249,10 +324,18 @@ void event__synthesize_threads(event__handler_t process, | |||
249 | if (*end) /* only interested in proper numerical dirents */ | 324 | if (*end) /* only interested in proper numerical dirents */ |
250 | continue; | 325 | continue; |
251 | 326 | ||
252 | event__synthesize_thread(pid, process, session); | 327 | __event__synthesize_thread(comm_event, mmap_event, pid, |
328 | process, session); | ||
253 | } | 329 | } |
254 | 330 | ||
255 | closedir(proc); | 331 | closedir(proc); |
332 | err = 0; | ||
333 | out_free_mmap: | ||
334 | free(mmap_event); | ||
335 | out_free_comm: | ||
336 | free(comm_event); | ||
337 | out: | ||
338 | return err; | ||
256 | } | 339 | } |
257 | 340 | ||
258 | struct process_symbol_args { | 341 | struct process_symbol_args { |
@@ -260,7 +343,8 @@ struct process_symbol_args { | |||
260 | u64 start; | 343 | u64 start; |
261 | }; | 344 | }; |
262 | 345 | ||
263 | static int find_symbol_cb(void *arg, const char *name, char type, u64 start) | 346 | static int find_symbol_cb(void *arg, const char *name, char type, |
347 | u64 start, u64 end __used) | ||
264 | { | 348 | { |
265 | struct process_symbol_args *args = arg; | 349 | struct process_symbol_args *args = arg; |
266 | 350 | ||
@@ -276,28 +360,30 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start) | |||
276 | return 1; | 360 | return 1; |
277 | } | 361 | } |
278 | 362 | ||
279 | int event__synthesize_kernel_mmap(event__handler_t process, | 363 | int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, |
280 | struct perf_session *session, | 364 | struct perf_session *session, |
281 | struct machine *machine, | 365 | struct machine *machine, |
282 | const char *symbol_name) | 366 | const char *symbol_name) |
283 | { | 367 | { |
284 | size_t size; | 368 | size_t size; |
285 | const char *filename, *mmap_name; | 369 | const char *filename, *mmap_name; |
286 | char path[PATH_MAX]; | 370 | char path[PATH_MAX]; |
287 | char name_buff[PATH_MAX]; | 371 | char name_buff[PATH_MAX]; |
288 | struct map *map; | 372 | struct map *map; |
289 | 373 | int err; | |
290 | event_t ev = { | ||
291 | .header = { | ||
292 | .type = PERF_RECORD_MMAP, | ||
293 | }, | ||
294 | }; | ||
295 | /* | 374 | /* |
296 | * We should get this from /sys/kernel/sections/.text, but till that is | 375 | * We should get this from /sys/kernel/sections/.text, but till that is |
297 | * available use this, and after it is use this as a fallback for older | 376 | * available use this, and after it is use this as a fallback for older |
298 | * kernels. | 377 | * kernels. |
299 | */ | 378 | */ |
300 | struct process_symbol_args args = { .name = symbol_name, }; | 379 | struct process_symbol_args args = { .name = symbol_name, }; |
380 | union perf_event *event = zalloc((sizeof(event->mmap) + | ||
381 | session->id_hdr_size)); | ||
382 | if (event == NULL) { | ||
383 | pr_debug("Not enough memory synthesizing mmap event " | ||
384 | "for kernel modules\n"); | ||
385 | return -1; | ||
386 | } | ||
301 | 387 | ||
302 | mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); | 388 | mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); |
303 | if (machine__is_host(machine)) { | 389 | if (machine__is_host(machine)) { |
@@ -305,10 +391,10 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
305 | * kernel uses PERF_RECORD_MISC_USER for user space maps, | 391 | * kernel uses PERF_RECORD_MISC_USER for user space maps, |
306 | * see kernel/perf_event.c __perf_event_mmap | 392 | * see kernel/perf_event.c __perf_event_mmap |
307 | */ | 393 | */ |
308 | ev.header.misc = PERF_RECORD_MISC_KERNEL; | 394 | event->header.misc = PERF_RECORD_MISC_KERNEL; |
309 | filename = "/proc/kallsyms"; | 395 | filename = "/proc/kallsyms"; |
310 | } else { | 396 | } else { |
311 | ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; | 397 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
312 | if (machine__is_default_guest(machine)) | 398 | if (machine__is_default_guest(machine)) |
313 | filename = (char *) symbol_conf.default_guest_kallsyms; | 399 | filename = (char *) symbol_conf.default_guest_kallsyms; |
314 | else { | 400 | else { |
@@ -321,54 +407,32 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
321 | return -ENOENT; | 407 | return -ENOENT; |
322 | 408 | ||
323 | map = machine->vmlinux_maps[MAP__FUNCTION]; | 409 | map = machine->vmlinux_maps[MAP__FUNCTION]; |
324 | size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), | 410 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), |
325 | "%s%s", mmap_name, symbol_name) + 1; | 411 | "%s%s", mmap_name, symbol_name) + 1; |
326 | size = ALIGN(size, sizeof(u64)); | 412 | size = ALIGN(size, sizeof(u64)); |
327 | ev.mmap.header.size = (sizeof(ev.mmap) - | 413 | event->mmap.header.type = PERF_RECORD_MMAP; |
328 | (sizeof(ev.mmap.filename) - size)); | 414 | event->mmap.header.size = (sizeof(event->mmap) - |
329 | ev.mmap.pgoff = args.start; | 415 | (sizeof(event->mmap.filename) - size) + session->id_hdr_size); |
330 | ev.mmap.start = map->start; | 416 | event->mmap.pgoff = args.start; |
331 | ev.mmap.len = map->end - ev.mmap.start; | 417 | event->mmap.start = map->start; |
332 | ev.mmap.pid = machine->pid; | 418 | event->mmap.len = map->end - event->mmap.start; |
333 | 419 | event->mmap.pid = machine->pid; | |
334 | return process(&ev, session); | 420 | |
335 | } | 421 | err = process(event, &synth_sample, session); |
336 | 422 | free(event); | |
337 | static void thread__comm_adjust(struct thread *self, struct hists *hists) | 423 | |
338 | { | 424 | return err; |
339 | char *comm = self->comm; | ||
340 | |||
341 | if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep && | ||
342 | (!symbol_conf.comm_list || | ||
343 | strlist__has_entry(symbol_conf.comm_list, comm))) { | ||
344 | u16 slen = strlen(comm); | ||
345 | |||
346 | if (hists__new_col_len(hists, HISTC_COMM, slen)) | ||
347 | hists__set_col_len(hists, HISTC_THREAD, slen + 6); | ||
348 | } | ||
349 | } | 425 | } |
350 | 426 | ||
351 | static int thread__set_comm_adjust(struct thread *self, const char *comm, | 427 | int perf_event__process_comm(union perf_event *event, |
352 | struct hists *hists) | 428 | struct perf_sample *sample __used, |
353 | { | 429 | struct perf_session *session) |
354 | int ret = thread__set_comm(self, comm); | ||
355 | |||
356 | if (ret) | ||
357 | return ret; | ||
358 | |||
359 | thread__comm_adjust(self, hists); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | int event__process_comm(event_t *self, struct perf_session *session) | ||
365 | { | 430 | { |
366 | struct thread *thread = perf_session__findnew(session, self->comm.tid); | 431 | struct thread *thread = perf_session__findnew(session, event->comm.tid); |
367 | 432 | ||
368 | dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid); | 433 | dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); |
369 | 434 | ||
370 | if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm, | 435 | if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { |
371 | &session->hists)) { | ||
372 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); | 436 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); |
373 | return -1; | 437 | return -1; |
374 | } | 438 | } |
@@ -376,27 +440,31 @@ int event__process_comm(event_t *self, struct perf_session *session) | |||
376 | return 0; | 440 | return 0; |
377 | } | 441 | } |
378 | 442 | ||
379 | int event__process_lost(event_t *self, struct perf_session *session) | 443 | int perf_event__process_lost(union perf_event *event, |
444 | struct perf_sample *sample __used, | ||
445 | struct perf_session *session) | ||
380 | { | 446 | { |
381 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); | 447 | dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", |
382 | session->hists.stats.total_lost += self->lost.lost; | 448 | event->lost.id, event->lost.lost); |
449 | session->hists.stats.total_lost += event->lost.lost; | ||
383 | return 0; | 450 | return 0; |
384 | } | 451 | } |
385 | 452 | ||
386 | static void event_set_kernel_mmap_len(struct map **maps, event_t *self) | 453 | static void perf_event__set_kernel_mmap_len(union perf_event *event, |
454 | struct map **maps) | ||
387 | { | 455 | { |
388 | maps[MAP__FUNCTION]->start = self->mmap.start; | 456 | maps[MAP__FUNCTION]->start = event->mmap.start; |
389 | maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; | 457 | maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len; |
390 | /* | 458 | /* |
391 | * Be a bit paranoid here, some perf.data file came with | 459 | * Be a bit paranoid here, some perf.data file came with |
392 | * a zero sized synthesized MMAP event for the kernel. | 460 | * a zero sized synthesized MMAP event for the kernel. |
393 | */ | 461 | */ |
394 | if (maps[MAP__FUNCTION]->end == 0) | 462 | if (maps[MAP__FUNCTION]->end == 0) |
395 | maps[MAP__FUNCTION]->end = ~0UL; | 463 | maps[MAP__FUNCTION]->end = ~0ULL; |
396 | } | 464 | } |
397 | 465 | ||
398 | static int event__process_kernel_mmap(event_t *self, | 466 | static int perf_event__process_kernel_mmap(union perf_event *event, |
399 | struct perf_session *session) | 467 | struct perf_session *session) |
400 | { | 468 | { |
401 | struct map *map; | 469 | struct map *map; |
402 | char kmmap_prefix[PATH_MAX]; | 470 | char kmmap_prefix[PATH_MAX]; |
@@ -404,9 +472,9 @@ static int event__process_kernel_mmap(event_t *self, | |||
404 | enum dso_kernel_type kernel_type; | 472 | enum dso_kernel_type kernel_type; |
405 | bool is_kernel_mmap; | 473 | bool is_kernel_mmap; |
406 | 474 | ||
407 | machine = perf_session__findnew_machine(session, self->mmap.pid); | 475 | machine = perf_session__findnew_machine(session, event->mmap.pid); |
408 | if (!machine) { | 476 | if (!machine) { |
409 | pr_err("Can't find id %d's machine\n", self->mmap.pid); | 477 | pr_err("Can't find id %d's machine\n", event->mmap.pid); |
410 | goto out_problem; | 478 | goto out_problem; |
411 | } | 479 | } |
412 | 480 | ||
@@ -416,17 +484,17 @@ static int event__process_kernel_mmap(event_t *self, | |||
416 | else | 484 | else |
417 | kernel_type = DSO_TYPE_GUEST_KERNEL; | 485 | kernel_type = DSO_TYPE_GUEST_KERNEL; |
418 | 486 | ||
419 | is_kernel_mmap = memcmp(self->mmap.filename, | 487 | is_kernel_mmap = memcmp(event->mmap.filename, |
420 | kmmap_prefix, | 488 | kmmap_prefix, |
421 | strlen(kmmap_prefix)) == 0; | 489 | strlen(kmmap_prefix)) == 0; |
422 | if (self->mmap.filename[0] == '/' || | 490 | if (event->mmap.filename[0] == '/' || |
423 | (!is_kernel_mmap && self->mmap.filename[0] == '[')) { | 491 | (!is_kernel_mmap && event->mmap.filename[0] == '[')) { |
424 | 492 | ||
425 | char short_module_name[1024]; | 493 | char short_module_name[1024]; |
426 | char *name, *dot; | 494 | char *name, *dot; |
427 | 495 | ||
428 | if (self->mmap.filename[0] == '/') { | 496 | if (event->mmap.filename[0] == '/') { |
429 | name = strrchr(self->mmap.filename, '/'); | 497 | name = strrchr(event->mmap.filename, '/'); |
430 | if (name == NULL) | 498 | if (name == NULL) |
431 | goto out_problem; | 499 | goto out_problem; |
432 | 500 | ||
@@ -438,10 +506,10 @@ static int event__process_kernel_mmap(event_t *self, | |||
438 | "[%.*s]", (int)(dot - name), name); | 506 | "[%.*s]", (int)(dot - name), name); |
439 | strxfrchar(short_module_name, '-', '_'); | 507 | strxfrchar(short_module_name, '-', '_'); |
440 | } else | 508 | } else |
441 | strcpy(short_module_name, self->mmap.filename); | 509 | strcpy(short_module_name, event->mmap.filename); |
442 | 510 | ||
443 | map = machine__new_module(machine, self->mmap.start, | 511 | map = machine__new_module(machine, event->mmap.start, |
444 | self->mmap.filename); | 512 | event->mmap.filename); |
445 | if (map == NULL) | 513 | if (map == NULL) |
446 | goto out_problem; | 514 | goto out_problem; |
447 | 515 | ||
@@ -451,9 +519,9 @@ static int event__process_kernel_mmap(event_t *self, | |||
451 | 519 | ||
452 | map->dso->short_name = name; | 520 | map->dso->short_name = name; |
453 | map->dso->sname_alloc = 1; | 521 | map->dso->sname_alloc = 1; |
454 | map->end = map->start + self->mmap.len; | 522 | map->end = map->start + event->mmap.len; |
455 | } else if (is_kernel_mmap) { | 523 | } else if (is_kernel_mmap) { |
456 | const char *symbol_name = (self->mmap.filename + | 524 | const char *symbol_name = (event->mmap.filename + |
457 | strlen(kmmap_prefix)); | 525 | strlen(kmmap_prefix)); |
458 | /* | 526 | /* |
459 | * Should be there already, from the build-id table in | 527 | * Should be there already, from the build-id table in |
@@ -468,10 +536,19 @@ static int event__process_kernel_mmap(event_t *self, | |||
468 | if (__machine__create_kernel_maps(machine, kernel) < 0) | 536 | if (__machine__create_kernel_maps(machine, kernel) < 0) |
469 | goto out_problem; | 537 | goto out_problem; |
470 | 538 | ||
471 | event_set_kernel_mmap_len(machine->vmlinux_maps, self); | 539 | perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); |
472 | perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | 540 | |
473 | symbol_name, | 541 | /* |
474 | self->mmap.pgoff); | 542 | * Avoid using a zero address (kptr_restrict) for the ref reloc |
543 | * symbol. Effectively having zero here means that at record | ||
544 | * time /proc/sys/kernel/kptr_restrict was non zero. | ||
545 | */ | ||
546 | if (event->mmap.pgoff != 0) { | ||
547 | perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | ||
548 | symbol_name, | ||
549 | event->mmap.pgoff); | ||
550 | } | ||
551 | |||
475 | if (machine__is_default_guest(machine)) { | 552 | if (machine__is_default_guest(machine)) { |
476 | /* | 553 | /* |
477 | * preload dso of guest kernel and modules | 554 | * preload dso of guest kernel and modules |
@@ -485,21 +562,23 @@ out_problem: | |||
485 | return -1; | 562 | return -1; |
486 | } | 563 | } |
487 | 564 | ||
488 | int event__process_mmap(event_t *self, struct perf_session *session) | 565 | int perf_event__process_mmap(union perf_event *event, |
566 | struct perf_sample *sample __used, | ||
567 | struct perf_session *session) | ||
489 | { | 568 | { |
490 | struct machine *machine; | 569 | struct machine *machine; |
491 | struct thread *thread; | 570 | struct thread *thread; |
492 | struct map *map; | 571 | struct map *map; |
493 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 572 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
494 | int ret = 0; | 573 | int ret = 0; |
495 | 574 | ||
496 | dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", | 575 | dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", |
497 | self->mmap.pid, self->mmap.tid, self->mmap.start, | 576 | event->mmap.pid, event->mmap.tid, event->mmap.start, |
498 | self->mmap.len, self->mmap.pgoff, self->mmap.filename); | 577 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); |
499 | 578 | ||
500 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | 579 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || |
501 | cpumode == PERF_RECORD_MISC_KERNEL) { | 580 | cpumode == PERF_RECORD_MISC_KERNEL) { |
502 | ret = event__process_kernel_mmap(self, session); | 581 | ret = perf_event__process_kernel_mmap(event, session); |
503 | if (ret < 0) | 582 | if (ret < 0) |
504 | goto out_problem; | 583 | goto out_problem; |
505 | return 0; | 584 | return 0; |
@@ -508,12 +587,12 @@ int event__process_mmap(event_t *self, struct perf_session *session) | |||
508 | machine = perf_session__find_host_machine(session); | 587 | machine = perf_session__find_host_machine(session); |
509 | if (machine == NULL) | 588 | if (machine == NULL) |
510 | goto out_problem; | 589 | goto out_problem; |
511 | thread = perf_session__findnew(session, self->mmap.pid); | 590 | thread = perf_session__findnew(session, event->mmap.pid); |
512 | if (thread == NULL) | 591 | if (thread == NULL) |
513 | goto out_problem; | 592 | goto out_problem; |
514 | map = map__new(&machine->user_dsos, self->mmap.start, | 593 | map = map__new(&machine->user_dsos, event->mmap.start, |
515 | self->mmap.len, self->mmap.pgoff, | 594 | event->mmap.len, event->mmap.pgoff, |
516 | self->mmap.pid, self->mmap.filename, | 595 | event->mmap.pid, event->mmap.filename, |
517 | MAP__FUNCTION); | 596 | MAP__FUNCTION); |
518 | if (map == NULL) | 597 | if (map == NULL) |
519 | goto out_problem; | 598 | goto out_problem; |
@@ -526,15 +605,17 @@ out_problem: | |||
526 | return 0; | 605 | return 0; |
527 | } | 606 | } |
528 | 607 | ||
529 | int event__process_task(event_t *self, struct perf_session *session) | 608 | int perf_event__process_task(union perf_event *event, |
609 | struct perf_sample *sample __used, | ||
610 | struct perf_session *session) | ||
530 | { | 611 | { |
531 | struct thread *thread = perf_session__findnew(session, self->fork.tid); | 612 | struct thread *thread = perf_session__findnew(session, event->fork.tid); |
532 | struct thread *parent = perf_session__findnew(session, self->fork.ptid); | 613 | struct thread *parent = perf_session__findnew(session, event->fork.ptid); |
533 | 614 | ||
534 | dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, | 615 | dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, |
535 | self->fork.ppid, self->fork.ptid); | 616 | event->fork.ppid, event->fork.ptid); |
536 | 617 | ||
537 | if (self->header.type == PERF_RECORD_EXIT) { | 618 | if (event->header.type == PERF_RECORD_EXIT) { |
538 | perf_session__remove_thread(session, thread); | 619 | perf_session__remove_thread(session, thread); |
539 | return 0; | 620 | return 0; |
540 | } | 621 | } |
@@ -548,19 +629,22 @@ int event__process_task(event_t *self, struct perf_session *session) | |||
548 | return 0; | 629 | return 0; |
549 | } | 630 | } |
550 | 631 | ||
551 | int event__process(event_t *event, struct perf_session *session) | 632 | int perf_event__process(union perf_event *event, struct perf_sample *sample, |
633 | struct perf_session *session) | ||
552 | { | 634 | { |
553 | switch (event->header.type) { | 635 | switch (event->header.type) { |
554 | case PERF_RECORD_COMM: | 636 | case PERF_RECORD_COMM: |
555 | event__process_comm(event, session); | 637 | perf_event__process_comm(event, sample, session); |
556 | break; | 638 | break; |
557 | case PERF_RECORD_MMAP: | 639 | case PERF_RECORD_MMAP: |
558 | event__process_mmap(event, session); | 640 | perf_event__process_mmap(event, sample, session); |
559 | break; | 641 | break; |
560 | case PERF_RECORD_FORK: | 642 | case PERF_RECORD_FORK: |
561 | case PERF_RECORD_EXIT: | 643 | case PERF_RECORD_EXIT: |
562 | event__process_task(event, session); | 644 | perf_event__process_task(event, sample, session); |
563 | break; | 645 | break; |
646 | case PERF_RECORD_LOST: | ||
647 | perf_event__process_lost(event, sample, session); | ||
564 | default: | 648 | default: |
565 | break; | 649 | break; |
566 | } | 650 | } |
@@ -635,7 +719,7 @@ try_again: | |||
635 | * in the whole kernel symbol list. | 719 | * in the whole kernel symbol list. |
636 | */ | 720 | */ |
637 | if ((long long)al->addr < 0 && | 721 | if ((long long)al->addr < 0 && |
638 | cpumode == PERF_RECORD_MISC_KERNEL && | 722 | cpumode == PERF_RECORD_MISC_USER && |
639 | machine && mg != &machine->kmaps) { | 723 | machine && mg != &machine->kmaps) { |
640 | mg = &machine->kmaps; | 724 | mg = &machine->kmaps; |
641 | goto try_again; | 725 | goto try_again; |
@@ -657,49 +741,15 @@ void thread__find_addr_location(struct thread *self, | |||
657 | al->sym = NULL; | 741 | al->sym = NULL; |
658 | } | 742 | } |
659 | 743 | ||
660 | static void dso__calc_col_width(struct dso *self, struct hists *hists) | 744 | int perf_event__preprocess_sample(const union perf_event *event, |
661 | { | 745 | struct perf_session *session, |
662 | if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep && | 746 | struct addr_location *al, |
663 | (!symbol_conf.dso_list || | 747 | struct perf_sample *sample, |
664 | strlist__has_entry(symbol_conf.dso_list, self->name))) { | 748 | symbol_filter_t filter) |
665 | u16 slen = dso__name_len(self); | ||
666 | hists__new_col_len(hists, HISTC_DSO, slen); | ||
667 | } | ||
668 | |||
669 | self->slen_calculated = 1; | ||
670 | } | ||
671 | |||
672 | int event__preprocess_sample(const event_t *self, struct perf_session *session, | ||
673 | struct addr_location *al, struct sample_data *data, | ||
674 | symbol_filter_t filter) | ||
675 | { | 749 | { |
676 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 750 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
677 | struct thread *thread; | 751 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
678 | |||
679 | event__parse_sample(self, session->sample_type, data); | ||
680 | |||
681 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n", | ||
682 | self->header.misc, data->pid, data->tid, data->ip, | ||
683 | data->period, data->cpu); | ||
684 | 752 | ||
685 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
686 | unsigned int i; | ||
687 | |||
688 | dump_printf("... chain: nr:%Lu\n", data->callchain->nr); | ||
689 | |||
690 | if (!ip_callchain__valid(data->callchain, self)) { | ||
691 | pr_debug("call-chain problem with event, " | ||
692 | "skipping it.\n"); | ||
693 | goto out_filtered; | ||
694 | } | ||
695 | |||
696 | if (dump_trace) { | ||
697 | for (i = 0; i < data->callchain->nr; i++) | ||
698 | dump_printf("..... %2d: %016Lx\n", | ||
699 | i, data->callchain->ips[i]); | ||
700 | } | ||
701 | } | ||
702 | thread = perf_session__findnew(session, self->ip.pid); | ||
703 | if (thread == NULL) | 753 | if (thread == NULL) |
704 | return -1; | 754 | return -1; |
705 | 755 | ||
@@ -720,12 +770,12 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
720 | machine__create_kernel_maps(&session->host_machine); | 770 | machine__create_kernel_maps(&session->host_machine); |
721 | 771 | ||
722 | thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, | 772 | thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, |
723 | self->ip.pid, self->ip.ip, al); | 773 | event->ip.pid, event->ip.ip, al); |
724 | dump_printf(" ...... dso: %s\n", | 774 | dump_printf(" ...... dso: %s\n", |
725 | al->map ? al->map->dso->long_name : | 775 | al->map ? al->map->dso->long_name : |
726 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 776 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
727 | al->sym = NULL; | 777 | al->sym = NULL; |
728 | al->cpu = data->cpu; | 778 | al->cpu = sample->cpu; |
729 | 779 | ||
730 | if (al->map) { | 780 | if (al->map) { |
731 | if (symbol_conf.dso_list && | 781 | if (symbol_conf.dso_list && |
@@ -736,23 +786,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
736 | strlist__has_entry(symbol_conf.dso_list, | 786 | strlist__has_entry(symbol_conf.dso_list, |
737 | al->map->dso->long_name))))) | 787 | al->map->dso->long_name))))) |
738 | goto out_filtered; | 788 | goto out_filtered; |
739 | /* | ||
740 | * We have to do this here as we may have a dso with no symbol | ||
741 | * hit that has a name longer than the ones with symbols | ||
742 | * sampled. | ||
743 | */ | ||
744 | if (!sort_dso.elide && !al->map->dso->slen_calculated) | ||
745 | dso__calc_col_width(al->map->dso, &session->hists); | ||
746 | 789 | ||
747 | al->sym = map__find_symbol(al->map, al->addr, filter); | 790 | al->sym = map__find_symbol(al->map, al->addr, filter); |
748 | } else { | ||
749 | const unsigned int unresolved_col_width = BITS_PER_LONG / 4; | ||
750 | |||
751 | if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width && | ||
752 | !symbol_conf.col_width_list_str && !symbol_conf.field_sep && | ||
753 | !symbol_conf.dso_list) | ||
754 | hists__set_col_len(&session->hists, HISTC_DSO, | ||
755 | unresolved_col_width); | ||
756 | } | 791 | } |
757 | 792 | ||
758 | if (symbol_conf.sym_list && al->sym && | 793 | if (symbol_conf.sym_list && al->sym && |
@@ -765,72 +800,3 @@ out_filtered: | |||
765 | al->filtered = true; | 800 | al->filtered = true; |
766 | return 0; | 801 | return 0; |
767 | } | 802 | } |
768 | |||
769 | int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) | ||
770 | { | ||
771 | const u64 *array = event->sample.array; | ||
772 | |||
773 | if (type & PERF_SAMPLE_IP) { | ||
774 | data->ip = event->ip.ip; | ||
775 | array++; | ||
776 | } | ||
777 | |||
778 | if (type & PERF_SAMPLE_TID) { | ||
779 | u32 *p = (u32 *)array; | ||
780 | data->pid = p[0]; | ||
781 | data->tid = p[1]; | ||
782 | array++; | ||
783 | } | ||
784 | |||
785 | if (type & PERF_SAMPLE_TIME) { | ||
786 | data->time = *array; | ||
787 | array++; | ||
788 | } | ||
789 | |||
790 | if (type & PERF_SAMPLE_ADDR) { | ||
791 | data->addr = *array; | ||
792 | array++; | ||
793 | } | ||
794 | |||
795 | data->id = -1ULL; | ||
796 | if (type & PERF_SAMPLE_ID) { | ||
797 | data->id = *array; | ||
798 | array++; | ||
799 | } | ||
800 | |||
801 | if (type & PERF_SAMPLE_STREAM_ID) { | ||
802 | data->stream_id = *array; | ||
803 | array++; | ||
804 | } | ||
805 | |||
806 | if (type & PERF_SAMPLE_CPU) { | ||
807 | u32 *p = (u32 *)array; | ||
808 | data->cpu = *p; | ||
809 | array++; | ||
810 | } else | ||
811 | data->cpu = -1; | ||
812 | |||
813 | if (type & PERF_SAMPLE_PERIOD) { | ||
814 | data->period = *array; | ||
815 | array++; | ||
816 | } | ||
817 | |||
818 | if (type & PERF_SAMPLE_READ) { | ||
819 | pr_debug("PERF_SAMPLE_READ is unsuported for now\n"); | ||
820 | return -1; | ||
821 | } | ||
822 | |||
823 | if (type & PERF_SAMPLE_CALLCHAIN) { | ||
824 | data->callchain = (struct ip_callchain *)array; | ||
825 | array += 1 + data->callchain->nr; | ||
826 | } | ||
827 | |||
828 | if (type & PERF_SAMPLE_RAW) { | ||
829 | u32 *p = (u32 *)array; | ||
830 | data->raw_size = *p; | ||
831 | p++; | ||
832 | data->raw_data = p; | ||
833 | } | ||
834 | |||
835 | return 0; | ||
836 | } | ||