aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-01-13 10:22:17 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-13 11:39:43 -0500
commitb7cece76783c68fb391f9882235b4b0c9c300c46 (patch)
tree8a0224493acc3cf74c218384a3b76b3e47c131a2 /tools/perf/util/event.c
parentff314d3903c2843de65c2148f66f277f2440ed26 (diff)
perf tools: Encode kernel module mappings in perf.data
We were always looking at the running machine /proc/modules, even when processing a perf.data file, which only makes sense when we're doing 'perf record' and 'perf report' on the same machine, and in close sucession, or if we don't use modules at all, right Peter? ;-) Now, at 'perf record' time we read /proc/modules, find the long path for modules, and put them as PERF_MMAP events, just like we did to encode the reloc reference symbol for vmlinux. Talking about that now it is encoded in .pgoff, so that we can use .{start,len} to store the address boundaries for the kernel so that when we reconstruct the kmaps tree we can do lookups right away, without having to fixup the end of the kernel maps like we did in the past (and now only in perf record). One more step in the 'perf archive' direction when we'll finally be able to collect data in one machine and analyse in another. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1263396139-4798-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r--tools/perf/util/event.c106
1 files changed, 94 insertions, 12 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index bfb3d872b9f5..4f3e7ef33b83 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -154,6 +154,36 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
154 return 0; 154 return 0;
155} 155}
156 156
157int event__synthesize_modules(event__handler_t process,
158 struct perf_session *session)
159{
160 struct rb_node *nd;
161
162 for (nd = rb_first(&session->kmaps.maps[MAP__FUNCTION]);
163 nd; nd = rb_next(nd)) {
164 event_t ev;
165 size_t size;
166 struct map *pos = rb_entry(nd, struct map, rb_node);
167
168 if (pos->dso->kernel)
169 continue;
170
171 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
172 memset(&ev, 0, sizeof(ev));
173 ev.mmap.header.type = PERF_RECORD_MMAP;
174 ev.mmap.header.size = (sizeof(ev.mmap) -
175 (sizeof(ev.mmap.filename) - size));
176 ev.mmap.start = pos->start;
177 ev.mmap.len = pos->end - pos->start;
178
179 memcpy(ev.mmap.filename, pos->dso->long_name,
180 pos->dso->long_name_len + 1);
181 process(&ev, session);
182 }
183
184 return 0;
185}
186
157int event__synthesize_thread(pid_t pid, event__handler_t process, 187int event__synthesize_thread(pid_t pid, event__handler_t process,
158 struct perf_session *session) 188 struct perf_session *session)
159{ 189{
@@ -222,7 +252,9 @@ int event__synthesize_kernel_mmap(event__handler_t process,
222 "[kernel.kallsyms.%s]", symbol_name) + 1; 252 "[kernel.kallsyms.%s]", symbol_name) + 1;
223 size = ALIGN(size, sizeof(u64)); 253 size = ALIGN(size, sizeof(u64));
224 ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); 254 ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size));
225 ev.mmap.start = args.start; 255 ev.mmap.pgoff = args.start;
256 ev.mmap.start = session->vmlinux_maps[MAP__FUNCTION]->start;
257 ev.mmap.len = session->vmlinux_maps[MAP__FUNCTION]->end - ev.mmap.start ;
226 258
227 return process(&ev, session); 259 return process(&ev, session);
228} 260}
@@ -280,7 +312,6 @@ int event__process_mmap(event_t *self, struct perf_session *session)
280{ 312{
281 struct thread *thread; 313 struct thread *thread;
282 struct map *map; 314 struct map *map;
283 static const char kmmap_prefix[] = "[kernel.kallsyms.";
284 315
285 dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n", 316 dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n",
286 self->mmap.pid, self->mmap.tid, 317 self->mmap.pid, self->mmap.tid,
@@ -289,13 +320,61 @@ int event__process_mmap(event_t *self, struct perf_session *session)
289 (void *)(long)self->mmap.pgoff, 320 (void *)(long)self->mmap.pgoff,
290 self->mmap.filename); 321 self->mmap.filename);
291 322
292 if (self->mmap.pid == 0 && 323 if (self->mmap.pid == 0) {
293 memcmp(self->mmap.filename, kmmap_prefix, 324 static const char kmmap_prefix[] = "[kernel.kallsyms.";
294 sizeof(kmmap_prefix) - 1) == 0) { 325
295 const char *symbol_name = (self->mmap.filename + 326 if (self->mmap.filename[0] == '/') {
296 sizeof(kmmap_prefix) - 1); 327 char short_module_name[1024];
297 perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name, 328 char *name = strrchr(self->mmap.filename, '/'), *dot;
298 self->mmap.start); 329
330 if (name == NULL)
331 goto out_problem;
332
333 ++name; /* skip / */
334 dot = strrchr(name, '.');
335 if (dot == NULL)
336 goto out_problem;
337
338 snprintf(short_module_name, sizeof(short_module_name),
339 "[%.*s]", (int)(dot - name), name);
340 strxfrchar(short_module_name, '-', '_');
341
342 map = perf_session__new_module_map(session,
343 self->mmap.start,
344 short_module_name);
345 if (map == NULL)
346 goto out_problem;
347
348 name = strdup(self->mmap.filename);
349 if (name == NULL)
350 goto out_problem;
351
352 dso__set_long_name(map->dso, name);
353 map->end = map->start + self->mmap.len;
354 } else if (memcmp(self->mmap.filename, kmmap_prefix,
355 sizeof(kmmap_prefix) - 1) == 0) {
356 const char *symbol_name = (self->mmap.filename +
357 sizeof(kmmap_prefix) - 1);
358 /*
359 * Should be there already, from the build-id table in
360 * the header.
361 */
362 struct dso *kernel = __dsos__findnew(&dsos__kernel,
363 "[kernel.kallsyms]");
364 if (kernel == NULL)
365 goto out_problem;
366
367 if (__map_groups__create_kernel_maps(&session->kmaps,
368 session->vmlinux_maps,
369 kernel) < 0)
370 goto out_problem;
371
372 session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start;
373 session->vmlinux_maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len;
374
375 perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name,
376 self->mmap.pgoff);
377 }
299 return 0; 378 return 0;
300 } 379 }
301 380
@@ -304,10 +383,13 @@ int event__process_mmap(event_t *self, struct perf_session *session)
304 session->cwd, session->cwdlen); 383 session->cwd, session->cwdlen);
305 384
306 if (thread == NULL || map == NULL) 385 if (thread == NULL || map == NULL)
307 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 386 goto out_problem;
308 else 387
309 thread__insert_map(thread, map); 388 thread__insert_map(thread, map);
389 return 0;
310 390
391out_problem:
392 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
311 return 0; 393 return 0;
312} 394}
313 395