aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r--tools/perf/util/event.c285
1 files changed, 200 insertions, 85 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 34510f441975..e4cdc1ebe0fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -33,11 +33,10 @@ static struct sample_data synth_sample = {
33 .period = 1, 33 .period = 1,
34}; 34};
35 35
36static pid_t event__synthesize_comm(pid_t pid, int full, 36static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
37 event__handler_t process, 37 event__handler_t process,
38 struct perf_session *session) 38 struct perf_session *session)
39{ 39{
40 event_t ev;
41 char filename[PATH_MAX]; 40 char filename[PATH_MAX];
42 char bf[BUFSIZ]; 41 char bf[BUFSIZ];
43 FILE *fp; 42 FILE *fp;
@@ -58,34 +57,39 @@ out_race:
58 return 0; 57 return 0;
59 } 58 }
60 59
61 memset(&ev.comm, 0, sizeof(ev.comm)); 60 memset(&event->comm, 0, sizeof(event->comm));
62 while (!ev.comm.comm[0] || !ev.comm.pid) { 61
63 if (fgets(bf, sizeof(bf), fp) == NULL) 62 while (!event->comm.comm[0] || !event->comm.pid) {
64 goto out_failure; 63 if (fgets(bf, sizeof(bf), fp) == NULL) {
64 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
65 goto out;
66 }
65 67
66 if (memcmp(bf, "Name:", 5) == 0) { 68 if (memcmp(bf, "Name:", 5) == 0) {
67 char *name = bf + 5; 69 char *name = bf + 5;
68 while (*name && isspace(*name)) 70 while (*name && isspace(*name))
69 ++name; 71 ++name;
70 size = strlen(name) - 1; 72 size = strlen(name) - 1;
71 memcpy(ev.comm.comm, name, size++); 73 memcpy(event->comm.comm, name, size++);
72 } else if (memcmp(bf, "Tgid:", 5) == 0) { 74 } else if (memcmp(bf, "Tgid:", 5) == 0) {
73 char *tgids = bf + 5; 75 char *tgids = bf + 5;
74 while (*tgids && isspace(*tgids)) 76 while (*tgids && isspace(*tgids))
75 ++tgids; 77 ++tgids;
76 tgid = ev.comm.pid = atoi(tgids); 78 tgid = event->comm.pid = atoi(tgids);
77 } 79 }
78 } 80 }
79 81
80 ev.comm.header.type = PERF_RECORD_COMM; 82 event->comm.header.type = PERF_RECORD_COMM;
81 size = ALIGN(size, sizeof(u64)); 83 size = ALIGN(size, sizeof(u64));
82 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); 84 memset(event->comm.comm + size, 0, session->id_hdr_size);
83 85 event->comm.header.size = (sizeof(event->comm) -
86 (sizeof(event->comm.comm) - size) +
87 session->id_hdr_size);
84 if (!full) { 88 if (!full) {
85 ev.comm.tid = pid; 89 event->comm.tid = pid;
86 90
87 process(&ev, &synth_sample, session); 91 process(event, &synth_sample, session);
88 goto out_fclose; 92 goto out;
89 } 93 }
90 94
91 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 95 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -100,22 +104,19 @@ out_race:
100 if (*end) 104 if (*end)
101 continue; 105 continue;
102 106
103 ev.comm.tid = pid; 107 event->comm.tid = pid;
104 108
105 process(&ev, &synth_sample, session); 109 process(event, &synth_sample, session);
106 } 110 }
107 closedir(tasks);
108 111
109out_fclose: 112 closedir(tasks);
113out:
110 fclose(fp); 114 fclose(fp);
111 return tgid;
112 115
113out_failure: 116 return tgid;
114 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
115 return -1;
116} 117}
117 118
118static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, 119static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
119 event__handler_t process, 120 event__handler_t process,
120 struct perf_session *session) 121 struct perf_session *session)
121{ 122{
@@ -133,29 +134,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
133 return -1; 134 return -1;
134 } 135 }
135 136
137 event->header.type = PERF_RECORD_MMAP;
138 /*
139 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
140 */
141 event->header.misc = PERF_RECORD_MISC_USER;
142
136 while (1) { 143 while (1) {
137 char bf[BUFSIZ], *pbf = bf; 144 char bf[BUFSIZ], *pbf = bf;
138 event_t ev = {
139 .header = {
140 .type = PERF_RECORD_MMAP,
141 /*
142 * Just like the kernel, see __perf_event_mmap
143 * in kernel/perf_event.c
144 */
145 .misc = PERF_RECORD_MISC_USER,
146 },
147 };
148 int n; 145 int n;
149 size_t size; 146 size_t size;
150 if (fgets(bf, sizeof(bf), fp) == NULL) 147 if (fgets(bf, sizeof(bf), fp) == NULL)
151 break; 148 break;
152 149
153 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 150 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
154 n = hex2u64(pbf, &ev.mmap.start); 151 n = hex2u64(pbf, &event->mmap.start);
155 if (n < 0) 152 if (n < 0)
156 continue; 153 continue;
157 pbf += n + 1; 154 pbf += n + 1;
158 n = hex2u64(pbf, &ev.mmap.len); 155 n = hex2u64(pbf, &event->mmap.len);
159 if (n < 0) 156 if (n < 0)
160 continue; 157 continue;
161 pbf += n + 3; 158 pbf += n + 3;
@@ -170,19 +167,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
170 continue; 167 continue;
171 168
172 pbf += 3; 169 pbf += 3;
173 n = hex2u64(pbf, &ev.mmap.pgoff); 170 n = hex2u64(pbf, &event->mmap.pgoff);
174 171
175 size = strlen(execname); 172 size = strlen(execname);
176 execname[size - 1] = '\0'; /* Remove \n */ 173 execname[size - 1] = '\0'; /* Remove \n */
177 memcpy(ev.mmap.filename, execname, size); 174 memcpy(event->mmap.filename, execname, size);
178 size = ALIGN(size, sizeof(u64)); 175 size = ALIGN(size, sizeof(u64));
179 ev.mmap.len -= ev.mmap.start; 176 event->mmap.len -= event->mmap.start;
180 ev.mmap.header.size = (sizeof(ev.mmap) - 177 event->mmap.header.size = (sizeof(event->mmap) -
181 (sizeof(ev.mmap.filename) - size)); 178 (sizeof(event->mmap.filename) - size));
182 ev.mmap.pid = tgid; 179 memset(event->mmap.filename + size, 0, session->id_hdr_size);
183 ev.mmap.tid = pid; 180 event->mmap.header.size += session->id_hdr_size;
184 181 event->mmap.pid = tgid;
185 process(&ev, &synth_sample, session); 182 event->mmap.tid = pid;
183
184 process(event, &synth_sample, session);
186 } 185 }
187 } 186 }
188 187
@@ -196,20 +195,27 @@ int event__synthesize_modules(event__handler_t process,
196{ 195{
197 struct rb_node *nd; 196 struct rb_node *nd;
198 struct map_groups *kmaps = &machine->kmaps; 197 struct map_groups *kmaps = &machine->kmaps;
199 u16 misc; 198 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
199
200 if (event == NULL) {
201 pr_debug("Not enough memory synthesizing mmap event "
202 "for kernel modules\n");
203 return -1;
204 }
205
206 event->header.type = PERF_RECORD_MMAP;
200 207
201 /* 208 /*
202 * kernel uses 0 for user space maps, see kernel/perf_event.c 209 * kernel uses 0 for user space maps, see kernel/perf_event.c
203 * __perf_event_mmap 210 * __perf_event_mmap
204 */ 211 */
205 if (machine__is_host(machine)) 212 if (machine__is_host(machine))
206 misc = PERF_RECORD_MISC_KERNEL; 213 event->header.misc = PERF_RECORD_MISC_KERNEL;
207 else 214 else
208 misc = PERF_RECORD_MISC_GUEST_KERNEL; 215 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
209 216
210 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 217 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
211 nd; nd = rb_next(nd)) { 218 nd; nd = rb_next(nd)) {
212 event_t ev;
213 size_t size; 219 size_t size;
214 struct map *pos = rb_entry(nd, struct map, rb_node); 220 struct map *pos = rb_entry(nd, struct map, rb_node);
215 221
@@ -217,39 +223,78 @@ int event__synthesize_modules(event__handler_t process,
217 continue; 223 continue;
218 224
219 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 225 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
220 memset(&ev, 0, sizeof(ev)); 226 event->mmap.header.type = PERF_RECORD_MMAP;
221 ev.mmap.header.misc = misc; 227 event->mmap.header.size = (sizeof(event->mmap) -
222 ev.mmap.header.type = PERF_RECORD_MMAP; 228 (sizeof(event->mmap.filename) - size));
223 ev.mmap.header.size = (sizeof(ev.mmap) - 229 memset(event->mmap.filename + size, 0, session->id_hdr_size);
224 (sizeof(ev.mmap.filename) - size)); 230 event->mmap.header.size += session->id_hdr_size;
225 ev.mmap.start = pos->start; 231 event->mmap.start = pos->start;
226 ev.mmap.len = pos->end - pos->start; 232 event->mmap.len = pos->end - pos->start;
227 ev.mmap.pid = machine->pid; 233 event->mmap.pid = machine->pid;
228 234
229 memcpy(ev.mmap.filename, pos->dso->long_name, 235 memcpy(event->mmap.filename, pos->dso->long_name,
230 pos->dso->long_name_len + 1); 236 pos->dso->long_name_len + 1);
231 process(&ev, &synth_sample, session); 237 process(event, &synth_sample, session);
232 } 238 }
233 239
240 free(event);
234 return 0; 241 return 0;
235} 242}
236 243
237int event__synthesize_thread(pid_t pid, event__handler_t process, 244static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
238 struct perf_session *session) 245 pid_t pid, event__handler_t process,
246 struct perf_session *session)
239{ 247{
240 pid_t tgid = event__synthesize_comm(pid, 1, process, session); 248 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
249 session);
241 if (tgid == -1) 250 if (tgid == -1)
242 return -1; 251 return -1;
243 return event__synthesize_mmap_events(pid, tgid, process, session); 252 return event__synthesize_mmap_events(mmap_event, pid, tgid,
253 process, session);
244} 254}
245 255
246void event__synthesize_threads(event__handler_t process, 256int event__synthesize_thread(pid_t pid, event__handler_t process,
247 struct perf_session *session) 257 struct perf_session *session)
258{
259 event_t *comm_event, *mmap_event;
260 int err = -1;
261
262 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
263 if (comm_event == NULL)
264 goto out;
265
266 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
267 if (mmap_event == NULL)
268 goto out_free_comm;
269
270 err = __event__synthesize_thread(comm_event, mmap_event, pid,
271 process, session);
272 free(mmap_event);
273out_free_comm:
274 free(comm_event);
275out:
276 return err;
277}
278
279int event__synthesize_threads(event__handler_t process,
280 struct perf_session *session)
248{ 281{
249 DIR *proc; 282 DIR *proc;
250 struct dirent dirent, *next; 283 struct dirent dirent, *next;
284 event_t *comm_event, *mmap_event;
285 int err = -1;
286
287 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
288 if (comm_event == NULL)
289 goto out;
290
291 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
292 if (mmap_event == NULL)
293 goto out_free_comm;
251 294
252 proc = opendir("/proc"); 295 proc = opendir("/proc");
296 if (proc == NULL)
297 goto out_free_mmap;
253 298
254 while (!readdir_r(proc, &dirent, &next) && next) { 299 while (!readdir_r(proc, &dirent, &next) && next) {
255 char *end; 300 char *end;
@@ -258,10 +303,18 @@ void event__synthesize_threads(event__handler_t process,
258 if (*end) /* only interested in proper numerical dirents */ 303 if (*end) /* only interested in proper numerical dirents */
259 continue; 304 continue;
260 305
261 event__synthesize_thread(pid, process, session); 306 __event__synthesize_thread(comm_event, mmap_event, pid,
307 process, session);
262 } 308 }
263 309
264 closedir(proc); 310 closedir(proc);
311 err = 0;
312out_free_mmap:
313 free(mmap_event);
314out_free_comm:
315 free(comm_event);
316out:
317 return err;
265} 318}
266 319
267struct process_symbol_args { 320struct process_symbol_args {
@@ -295,18 +348,20 @@ int event__synthesize_kernel_mmap(event__handler_t process,
295 char path[PATH_MAX]; 348 char path[PATH_MAX];
296 char name_buff[PATH_MAX]; 349 char name_buff[PATH_MAX];
297 struct map *map; 350 struct map *map;
298 351 int err;
299 event_t ev = {
300 .header = {
301 .type = PERF_RECORD_MMAP,
302 },
303 };
304 /* 352 /*
305 * We should get this from /sys/kernel/sections/.text, but till that is 353 * We should get this from /sys/kernel/sections/.text, but till that is
306 * available use this, and after it is use this as a fallback for older 354 * available use this, and after it is use this as a fallback for older
307 * kernels. 355 * kernels.
308 */ 356 */
309 struct process_symbol_args args = { .name = symbol_name, }; 357 struct process_symbol_args args = { .name = symbol_name, };
358 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
359
360 if (event == NULL) {
361 pr_debug("Not enough memory synthesizing mmap event "
362 "for kernel modules\n");
363 return -1;
364 }
310 365
311 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 366 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
312 if (machine__is_host(machine)) { 367 if (machine__is_host(machine)) {
@@ -314,10 +369,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
314 * kernel uses PERF_RECORD_MISC_USER for user space maps, 369 * kernel uses PERF_RECORD_MISC_USER for user space maps,
315 * see kernel/perf_event.c __perf_event_mmap 370 * see kernel/perf_event.c __perf_event_mmap
316 */ 371 */
317 ev.header.misc = PERF_RECORD_MISC_KERNEL; 372 event->header.misc = PERF_RECORD_MISC_KERNEL;
318 filename = "/proc/kallsyms"; 373 filename = "/proc/kallsyms";
319 } else { 374 } else {
320 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 375 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
321 if (machine__is_default_guest(machine)) 376 if (machine__is_default_guest(machine))
322 filename = (char *) symbol_conf.default_guest_kallsyms; 377 filename = (char *) symbol_conf.default_guest_kallsyms;
323 else { 378 else {
@@ -330,17 +385,21 @@ int event__synthesize_kernel_mmap(event__handler_t process,
330 return -ENOENT; 385 return -ENOENT;
331 386
332 map = machine->vmlinux_maps[MAP__FUNCTION]; 387 map = machine->vmlinux_maps[MAP__FUNCTION];
333 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 388 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
334 "%s%s", mmap_name, symbol_name) + 1; 389 "%s%s", mmap_name, symbol_name) + 1;
335 size = ALIGN(size, sizeof(u64)); 390 size = ALIGN(size, sizeof(u64));
336 ev.mmap.header.size = (sizeof(ev.mmap) - 391 event->mmap.header.type = PERF_RECORD_MMAP;
337 (sizeof(ev.mmap.filename) - size)); 392 event->mmap.header.size = (sizeof(event->mmap) -
338 ev.mmap.pgoff = args.start; 393 (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
339 ev.mmap.start = map->start; 394 event->mmap.pgoff = args.start;
340 ev.mmap.len = map->end - ev.mmap.start; 395 event->mmap.start = map->start;
341 ev.mmap.pid = machine->pid; 396 event->mmap.len = map->end - event->mmap.start;
342 397 event->mmap.pid = machine->pid;
343 return process(&ev, &synth_sample, session); 398
399 err = process(event, &synth_sample, session);
400 free(event);
401
402 return err;
344} 403}
345 404
346static void thread__comm_adjust(struct thread *self, struct hists *hists) 405static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -756,9 +815,65 @@ out_filtered:
756 return 0; 815 return 0;
757} 816}
758 817
759int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 818static int event__parse_id_sample(const event_t *event,
819 struct perf_session *session,
820 struct sample_data *sample)
760{ 821{
761 const u64 *array = event->sample.array; 822 const u64 *array;
823 u64 type;
824
825 sample->cpu = sample->pid = sample->tid = -1;
826 sample->stream_id = sample->id = sample->time = -1ULL;
827
828 if (!session->sample_id_all)
829 return 0;
830
831 array = event->sample.array;
832 array += ((event->header.size -
833 sizeof(event->header)) / sizeof(u64)) - 1;
834 type = session->sample_type;
835
836 if (type & PERF_SAMPLE_CPU) {
837 u32 *p = (u32 *)array;
838 sample->cpu = *p;
839 array--;
840 }
841
842 if (type & PERF_SAMPLE_STREAM_ID) {
843 sample->stream_id = *array;
844 array--;
845 }
846
847 if (type & PERF_SAMPLE_ID) {
848 sample->id = *array;
849 array--;
850 }
851
852 if (type & PERF_SAMPLE_TIME) {
853 sample->time = *array;
854 array--;
855 }
856
857 if (type & PERF_SAMPLE_TID) {
858 u32 *p = (u32 *)array;
859 sample->pid = p[0];
860 sample->tid = p[1];
861 }
862
863 return 0;
864}
865
866int event__parse_sample(const event_t *event, struct perf_session *session,
867 struct sample_data *data)
868{
869 const u64 *array;
870 u64 type;
871
872 if (event->header.type != PERF_RECORD_SAMPLE)
873 return event__parse_id_sample(event, session, data);
874
875 array = event->sample.array;
876 type = session->sample_type;
762 877
763 if (type & PERF_SAMPLE_IP) { 878 if (type & PERF_SAMPLE_IP) {
764 data->ip = event->ip.ip; 879 data->ip = event->ip.ip;